aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Shuralyov <shurcooL@gmail.com>2014-12-31 18:45:16 -0800
committerDmitri Shuralyov <shurcooL@gmail.com>2015-02-21 18:51:42 -0800
commit580367ced74b6c4fedd851d3378b3537bd2a853b (patch)
tree6c9251cf3912a304085197059dee3a0f97f02728
parentd55884e36b8254966ef9daaee2ea2263e67d6eac (diff)
downloadglfw-580367ced74b6c4fedd851d3378b3537bd2a853b.tar.gz
Update to glfw/glfw@aa7f827e721d8fc4c856f10152ec945169e69665.
-rw-r--r--GLFW_C_REVISION.txt2
-rw-r--r--glfw/include/GLFW/glfw3.h100
-rw-r--r--glfw/include/GLFW/glfw3native.h35
-rw-r--r--glfw/src/CMakeLists.txt5
-rw-r--r--glfw/src/cocoa_init.m133
-rw-r--r--glfw/src/cocoa_monitor.m2
-rw-r--r--glfw/src/cocoa_platform.h3
-rw-r--r--glfw/src/cocoa_window.m369
-rw-r--r--glfw/src/glfw_config.h.in2
-rw-r--r--glfw/src/init.c4
-rw-r--r--glfw/src/input.c19
-rw-r--r--glfw/src/internal.h7
-rw-r--r--glfw/src/linux_joystick.c160
-rw-r--r--glfw/src/linux_joystick.h3
-rw-r--r--glfw/src/mir_init.c96
-rw-r--r--glfw/src/mir_monitor.c138
-rw-r--r--glfw/src/mir_platform.h110
-rw-r--r--glfw/src/mir_window.c658
-rw-r--r--glfw/src/nsgl_context.m47
-rw-r--r--glfw/src/win32_init.c132
-rw-r--r--glfw/src/win32_monitor.c19
-rw-r--r--glfw/src/win32_platform.h4
-rw-r--r--glfw/src/win32_window.c293
-rw-r--r--glfw/src/wl_init.c1
-rw-r--r--glfw/src/wl_platform.h1
-rw-r--r--glfw/src/wl_window.c7
-rw-r--r--glfw/src/x11_init.c159
-rw-r--r--glfw/src/x11_monitor.c7
-rw-r--r--glfw/src/x11_platform.h17
-rw-r--r--glfw/src/x11_window.c61
30 files changed, 1947 insertions, 647 deletions
diff --git a/GLFW_C_REVISION.txt b/GLFW_C_REVISION.txt
index 3b98cb5..0ca9948 100644
--- a/GLFW_C_REVISION.txt
+++ b/GLFW_C_REVISION.txt
@@ -1 +1 @@
-3b9a14fc9c3845afc7b8788a62435bdc02a7daaf
+aa7f827e721d8fc4c856f10152ec945169e69665
diff --git a/glfw/include/GLFW/glfw3.h b/glfw/include/GLFW/glfw3.h
index 83b2ff0..2cba521 100644
--- a/glfw/include/GLFW/glfw3.h
+++ b/glfw/include/GLFW/glfw3.h
@@ -672,6 +672,42 @@ extern "C" {
#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001
#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002
+/*! @defgroup shapes Standard cursor shapes
+ * @ingroup input
+ * @{ */
+
+/*! @brief The regular arrow cursor shape.
+ *
+ * The regular arrow cursor.
+ */
+#define GLFW_ARROW_CURSOR 0x00036001
+/*! @brief The text input I-beam cursor shape.
+ *
+ * The text input I-beam cursor shape.
+ */
+#define GLFW_IBEAM_CURSOR 0x00036002
+/*! @brief The crosshair shape.
+ *
+ * The crosshair shape.
+ */
+#define GLFW_CROSSHAIR_CURSOR 0x00036003
+/*! @brief The hand shape.
+ *
+ * The hand shape.
+ */
+#define GLFW_HAND_CURSOR 0x00036004
+/*! @brief The horizontal resize arrow shape.
+ *
+ * The horizontal resize arrow shape.
+ */
+#define GLFW_HRESIZE_CURSOR 0x00036005
+/*! @brief The vertical resize arrow shape.
+ *
+ * The vertical resize arrow shape.
+ */
+#define GLFW_VRESIZE_CURSOR 0x00036006
+/*! @} */
+
#define GLFW_CONNECTED 0x00040001
#define GLFW_DISCONNECTED 0x00040002
@@ -1013,8 +1049,6 @@ typedef struct GLFWgammaramp
} GLFWgammaramp;
/*! @brief Image data.
- *
- * @ingroup window
*/
typedef struct GLFWimage
{
@@ -1055,6 +1089,12 @@ typedef struct GLFWimage
* bundle, if present. This can be disabled with a
* [compile-time option](@ref compile_options_osx).
*
+ * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to
+ * `"C"` then the environment's locale will be applied to that category. This
+ * is done because character input will not function when `LC_CTYPE` is set to
+ * `"C"`. If another locale was set before this function was called, it will
+ * be left untouched.
+ *
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -1591,6 +1631,9 @@ GLFWAPI void glfwWindowHint(int target, int hint);
* `GLFW_ICON,` it will be set as the icon for the window. If no such icon is
* present, the `IDI_WINLOGO` icon will be used instead.
*
+ * @remarks __Windows:__ The context to share resources with may not be current
+ * on any other thread.
+ *
* @remarks __OS X:__ The GLFW window has no icon, as it is not a document
* window, but the dock icon will be the same as the application bundle's icon.
* For more information on bundles, see the
@@ -1608,7 +1651,8 @@ GLFWAPI void glfwWindowHint(int target, int hint);
* @remarks __X11:__ Some window managers will not respect the placement of
* initially hidden windows.
*
- * @note This function may not be called from a callback.
+ * @par Reentrancy
+ * This function may not be called from a callback.
*
* @par Thread Safety
* This function may only be called from the main thread.
@@ -1636,11 +1680,12 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, G
*
* @param[in] window The window to destroy.
*
- * @note This function may not be called from a callback.
- *
* @note The context of the specified window must not be current on any other
* thread when this function is called.
*
+ * @par Reentrancy
+ * This function may not be called from a callback.
+ *
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -2302,7 +2347,8 @@ GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window
*
* Event processing is not required for joystick input to work.
*
- * @note This function may not be called from a callback.
+ * @par Reentrancy
+ * This function may not be called from a callback.
*
* @par Thread Safety
* This function may only be called from the main thread.
@@ -2345,11 +2391,12 @@ GLFWAPI void glfwPollEvents(void);
*
* Event processing is not required for joystick input to work.
*
- * @note This function may not be called from a callback.
- *
* @note On some platforms, certain callbacks may be called outside of a call
* to one of the event processing functions.
*
+ * @par Reentrancy
+ * This function may not be called from a callback.
+ *
* @par Thread Safety
* This function may only be called from the main thread.
*
@@ -2606,7 +2653,7 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
*/
GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
-/*! @brief Creates a cursor.
+/*! @brief Creates a custom cursor.
*
* Creates a new cursor that can be made the system cursor for a window with
* @ref glfwSetCursor. The cursor can be destroyed with @ref
@@ -2623,16 +2670,18 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
* @return A new cursor ready to use or `NULL` if an
* [error](@ref error_handling) occurred.
*
- * @note This function may not be called from a callback.
- *
* @par Pointer Lifetime
* The specified image data is copied before this function returns.
*
+ * @par Reentrancy
+ * This function may not be called from a callback.
+ *
* @par Thread Safety
* This function may only be called from the main thread.
*
* @sa @ref input_cursor
* @sa glfwDestroyCursor
+ * @sa glfwCreateStandardCursor
*
* @par History
* Added in GLFW 3.1.
@@ -2641,6 +2690,32 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
*/
GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);
+/*! @brief Creates a cursor with a standard shape.
+ *
+ * Returns a cursor with a [standard shape](@ref shapes), which can be made the
+ * system cursor for a window with @ref glfwSetCursor.
+ *
+ * @param[in] shape One of the [standard shapes](@ref shapes).
+ *
+ * @return A new cursor ready to use or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @par Reentrancy
+ * This function may not be called from a callback.
+ *
+ * @par Thread Safety
+ * This function may only be called from the main thread.
+ *
+ * @sa @ref input_cursor
+ * @sa glfwCreateCursor
+ *
+ * @par History
+ * Added in GLFW 3.1.
+ *
+ * @ingroup input
+ */
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);
+
/*! @brief Destroys a cursor.
*
* This function destroys a cursor previously created with @ref
@@ -2649,7 +2724,8 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
*
* @param[in] cursor The cursor object to destroy.
*
- * @note This function may not be called from a callback.
+ * @par Reentrancy
+ * This function may not be called from a callback.
*
* @par Thread Safety
* This function may only be called from the main thread.
diff --git a/glfw/include/GLFW/glfw3native.h b/glfw/include/GLFW/glfw3native.h
index c00d57c..881f504 100644
--- a/glfw/include/GLFW/glfw3native.h
+++ b/glfw/include/GLFW/glfw3native.h
@@ -108,9 +108,9 @@ extern "C" {
*************************************************************************/
#if defined(GLFW_EXPOSE_NATIVE_WIN32)
-/*! @brief Returns the display device name of the specified monitor.
+/*! @brief Returns the adapter device name of the specified monitor.
*
- * @return The UTF-8 encoded display device name (`DISPLAY_DEVICE.DeviceName`)
+ * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`)
* of the specified monitor, or `NULL` if an [error](@ref error_handling)
* occurred.
*
@@ -122,6 +122,22 @@ extern "C" {
*
* @ingroup native
*/
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor);
+
+/*! @brief Returns the display device name of the specified monitor.
+ *
+ * @return The UTF-8 encoded display device name (for example
+ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @par Thread Safety
+ * This function may be called from any thread. Access is not synchronized.
+ *
+ * @par History
+ * Added in GLFW 3.1.
+ *
+ * @ingroup native
+ */
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor);
/*! @brief Returns the `HWND` of the specified window.
@@ -222,6 +238,21 @@ GLFWAPI id glfwGetNSGLContext(GLFWwindow* window);
*/
GLFWAPI Display* glfwGetX11Display(void);
+/*! @brief Returns the `RRCrtc` of the specified monitor.
+ *
+ * @return The `RRCrtc` of the specified monitor, or `None` if an
+ * [error](@ref error_handling) occurred.
+ *
+ * @par Thread Safety
+ * This function may be called from any thread. Access is not synchronized.
+ *
+ * @par History
+ * Added in GLFW 3.1.
+ *
+ * @ingroup native
+ */
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
+
/*! @brief Returns the `RROutput` of the specified monitor.
*
* @return The `RROutput` of the specified monitor, or `None` if an
diff --git a/glfw/src/CMakeLists.txt b/glfw/src/CMakeLists.txt
index e006a8f..9ba9fc5 100644
--- a/glfw/src/CMakeLists.txt
+++ b/glfw/src/CMakeLists.txt
@@ -30,6 +30,11 @@ elseif (_GLFW_WAYLAND)
posix_time.h posix_tls.h xkb_unicode.h)
set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c)
+elseif (_GLFW_MIR)
+ set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
+ posix_time.h posix_tls.h xkb_unicode.h)
+ set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
+ linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c)
endif()
if (_GLFW_EGL)
diff --git a/glfw/src/cocoa_init.m b/glfw/src/cocoa_init.m
index afb1a54..1bcee9d 100644
--- a/glfw/src/cocoa_init.m
+++ b/glfw/src/cocoa_init.m
@@ -68,6 +68,128 @@ static void changeToResourcesDirectory(void)
#endif /* _GLFW_USE_CHDIR */
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));
+
+ _glfw.ns.publicKeys[0x1D] = GLFW_KEY_0;
+ _glfw.ns.publicKeys[0x12] = GLFW_KEY_1;
+ _glfw.ns.publicKeys[0x13] = GLFW_KEY_2;
+ _glfw.ns.publicKeys[0x14] = GLFW_KEY_3;
+ _glfw.ns.publicKeys[0x15] = GLFW_KEY_4;
+ _glfw.ns.publicKeys[0x17] = GLFW_KEY_5;
+ _glfw.ns.publicKeys[0x16] = GLFW_KEY_6;
+ _glfw.ns.publicKeys[0x1A] = GLFW_KEY_7;
+ _glfw.ns.publicKeys[0x1C] = GLFW_KEY_8;
+ _glfw.ns.publicKeys[0x19] = GLFW_KEY_9;
+ _glfw.ns.publicKeys[0x00] = GLFW_KEY_A;
+ _glfw.ns.publicKeys[0x0B] = GLFW_KEY_B;
+ _glfw.ns.publicKeys[0x08] = GLFW_KEY_C;
+ _glfw.ns.publicKeys[0x02] = GLFW_KEY_D;
+ _glfw.ns.publicKeys[0x0E] = GLFW_KEY_E;
+ _glfw.ns.publicKeys[0x03] = GLFW_KEY_F;
+ _glfw.ns.publicKeys[0x05] = GLFW_KEY_G;
+ _glfw.ns.publicKeys[0x04] = GLFW_KEY_H;
+ _glfw.ns.publicKeys[0x22] = GLFW_KEY_I;
+ _glfw.ns.publicKeys[0x26] = GLFW_KEY_J;
+ _glfw.ns.publicKeys[0x28] = GLFW_KEY_K;
+ _glfw.ns.publicKeys[0x25] = GLFW_KEY_L;
+ _glfw.ns.publicKeys[0x2E] = GLFW_KEY_M;
+ _glfw.ns.publicKeys[0x2D] = GLFW_KEY_N;
+ _glfw.ns.publicKeys[0x1F] = GLFW_KEY_O;
+ _glfw.ns.publicKeys[0x23] = GLFW_KEY_P;
+ _glfw.ns.publicKeys[0x0C] = GLFW_KEY_Q;
+ _glfw.ns.publicKeys[0x0F] = GLFW_KEY_R;
+ _glfw.ns.publicKeys[0x01] = GLFW_KEY_S;
+ _glfw.ns.publicKeys[0x11] = GLFW_KEY_T;
+ _glfw.ns.publicKeys[0x20] = GLFW_KEY_U;
+ _glfw.ns.publicKeys[0x09] = GLFW_KEY_V;
+ _glfw.ns.publicKeys[0x0D] = GLFW_KEY_W;
+ _glfw.ns.publicKeys[0x07] = GLFW_KEY_X;
+ _glfw.ns.publicKeys[0x10] = GLFW_KEY_Y;
+ _glfw.ns.publicKeys[0x06] = GLFW_KEY_Z;
+
+ _glfw.ns.publicKeys[0x27] = GLFW_KEY_APOSTROPHE;
+ _glfw.ns.publicKeys[0x2A] = GLFW_KEY_BACKSLASH;
+ _glfw.ns.publicKeys[0x2B] = GLFW_KEY_COMMA;
+ _glfw.ns.publicKeys[0x18] = GLFW_KEY_EQUAL;
+ _glfw.ns.publicKeys[0x32] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.ns.publicKeys[0x21] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.ns.publicKeys[0x1B] = GLFW_KEY_MINUS;
+ _glfw.ns.publicKeys[0x2F] = GLFW_KEY_PERIOD;
+ _glfw.ns.publicKeys[0x1E] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.ns.publicKeys[0x29] = GLFW_KEY_SEMICOLON;
+ _glfw.ns.publicKeys[0x2C] = GLFW_KEY_SLASH;
+ _glfw.ns.publicKeys[0x0A] = GLFW_KEY_WORLD_1;
+
+ _glfw.ns.publicKeys[0x33] = GLFW_KEY_BACKSPACE;
+ _glfw.ns.publicKeys[0x39] = GLFW_KEY_CAPS_LOCK;
+ _glfw.ns.publicKeys[0x75] = GLFW_KEY_DELETE;
+ _glfw.ns.publicKeys[0x7D] = GLFW_KEY_DOWN;
+ _glfw.ns.publicKeys[0x77] = GLFW_KEY_END;
+ _glfw.ns.publicKeys[0x24] = GLFW_KEY_ENTER;
+ _glfw.ns.publicKeys[0x35] = GLFW_KEY_ESCAPE;
+ _glfw.ns.publicKeys[0x7A] = GLFW_KEY_F1;
+ _glfw.ns.publicKeys[0x78] = GLFW_KEY_F2;
+ _glfw.ns.publicKeys[0x63] = GLFW_KEY_F3;
+ _glfw.ns.publicKeys[0x76] = GLFW_KEY_F4;
+ _glfw.ns.publicKeys[0x60] = GLFW_KEY_F5;
+ _glfw.ns.publicKeys[0x61] = GLFW_KEY_F6;
+ _glfw.ns.publicKeys[0x62] = GLFW_KEY_F7;
+ _glfw.ns.publicKeys[0x64] = GLFW_KEY_F8;
+ _glfw.ns.publicKeys[0x65] = GLFW_KEY_F9;
+ _glfw.ns.publicKeys[0x6D] = GLFW_KEY_F10;
+ _glfw.ns.publicKeys[0x67] = GLFW_KEY_F11;
+ _glfw.ns.publicKeys[0x6F] = GLFW_KEY_F12;
+ _glfw.ns.publicKeys[0x69] = GLFW_KEY_F13;
+ _glfw.ns.publicKeys[0x6B] = GLFW_KEY_F14;
+ _glfw.ns.publicKeys[0x71] = GLFW_KEY_F15;
+ _glfw.ns.publicKeys[0x6A] = GLFW_KEY_F16;
+ _glfw.ns.publicKeys[0x40] = GLFW_KEY_F17;
+ _glfw.ns.publicKeys[0x4F] = GLFW_KEY_F18;
+ _glfw.ns.publicKeys[0x50] = GLFW_KEY_F19;
+ _glfw.ns.publicKeys[0x5A] = GLFW_KEY_F20;
+ _glfw.ns.publicKeys[0x73] = GLFW_KEY_HOME;
+ _glfw.ns.publicKeys[0x72] = GLFW_KEY_INSERT;
+ _glfw.ns.publicKeys[0x7B] = GLFW_KEY_LEFT;
+ _glfw.ns.publicKeys[0x3A] = GLFW_KEY_LEFT_ALT;
+ _glfw.ns.publicKeys[0x3B] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.ns.publicKeys[0x38] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.ns.publicKeys[0x37] = GLFW_KEY_LEFT_SUPER;
+ _glfw.ns.publicKeys[0x6E] = GLFW_KEY_MENU;
+ _glfw.ns.publicKeys[0x47] = GLFW_KEY_NUM_LOCK;
+ _glfw.ns.publicKeys[0x79] = GLFW_KEY_PAGE_DOWN;
+ _glfw.ns.publicKeys[0x74] = GLFW_KEY_PAGE_UP;
+ _glfw.ns.publicKeys[0x7C] = GLFW_KEY_RIGHT;
+ _glfw.ns.publicKeys[0x3D] = GLFW_KEY_RIGHT_ALT;
+ _glfw.ns.publicKeys[0x3E] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.ns.publicKeys[0x3C] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.ns.publicKeys[0x36] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.ns.publicKeys[0x31] = GLFW_KEY_SPACE;
+ _glfw.ns.publicKeys[0x30] = GLFW_KEY_TAB;
+ _glfw.ns.publicKeys[0x7E] = GLFW_KEY_UP;
+
+ _glfw.ns.publicKeys[0x52] = GLFW_KEY_KP_0;
+ _glfw.ns.publicKeys[0x53] = GLFW_KEY_KP_1;
+ _glfw.ns.publicKeys[0x54] = GLFW_KEY_KP_2;
+ _glfw.ns.publicKeys[0x55] = GLFW_KEY_KP_3;
+ _glfw.ns.publicKeys[0x56] = GLFW_KEY_KP_4;
+ _glfw.ns.publicKeys[0x57] = GLFW_KEY_KP_5;
+ _glfw.ns.publicKeys[0x58] = GLFW_KEY_KP_6;
+ _glfw.ns.publicKeys[0x59] = GLFW_KEY_KP_7;
+ _glfw.ns.publicKeys[0x5B] = GLFW_KEY_KP_8;
+ _glfw.ns.publicKeys[0x5C] = GLFW_KEY_KP_9;
+ _glfw.ns.publicKeys[0x45] = GLFW_KEY_KP_ADD;
+ _glfw.ns.publicKeys[0x41] = GLFW_KEY_KP_DECIMAL;
+ _glfw.ns.publicKeys[0x4B] = GLFW_KEY_KP_DIVIDE;
+ _glfw.ns.publicKeys[0x4C] = GLFW_KEY_KP_ENTER;
+ _glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL;
+ _glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;
+}
+
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
@@ -81,6 +203,8 @@ int _glfwPlatformInit(void)
changeToResourcesDirectory();
#endif
+ createKeyTables();
+
_glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (!_glfw.ns.eventSource)
return GL_FALSE;
@@ -104,9 +228,12 @@ void _glfwPlatformTerminate(void)
_glfw.ns.eventSource = NULL;
}
- [NSApp setDelegate:nil];
- [_glfw.ns.delegate release];
- _glfw.ns.delegate = nil;
+ id delegate = [NSApp delegate];
+ if (delegate)
+ {
+ [delegate release];
+ [NSApp setDelegate:nil];
+ }
[_glfw.ns.autoreleasePool release];
_glfw.ns.autoreleasePool = nil;
diff --git a/glfw/src/cocoa_monitor.m b/glfw/src/cocoa_monitor.m
index cfb76a7..db3cf71 100644
--- a/glfw/src/cocoa_monitor.m
+++ b/glfw/src/cocoa_monitor.m
@@ -204,7 +204,6 @@ GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired)
monitor->ns.previousMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
CGDisplayFadeReservationToken token = beginFadeReservation();
- CGDisplayCapture(monitor->ns.displayID);
CGDisplaySetDisplayMode(monitor->ns.displayID, native, NULL);
endFadeReservation(token);
}
@@ -231,7 +230,6 @@ void _glfwRestoreVideoMode(_GLFWmonitor* monitor)
CGDisplayFadeReservationToken token = beginFadeReservation();
CGDisplaySetDisplayMode(monitor->ns.displayID,
monitor->ns.previousMode, NULL);
- CGDisplayRelease(monitor->ns.displayID);
endFadeReservation(token);
CGDisplayModeRelease(monitor->ns.previousMode);
diff --git a/glfw/src/cocoa_platform.h b/glfw/src/cocoa_platform.h
index 6b768c7..6aafa32 100644
--- a/glfw/src/cocoa_platform.h
+++ b/glfw/src/cocoa_platform.h
@@ -62,7 +62,6 @@ typedef struct _GLFWwindowNS
id delegate;
id view;
unsigned int modifierFlags;
- int cursorInside;
} _GLFWwindowNS;
@@ -72,10 +71,10 @@ typedef struct _GLFWwindowNS
typedef struct _GLFWlibraryNS
{
CGEventSourceRef eventSource;
- id delegate;
id autoreleasePool;
id cursor;
+ short int publicKeys[256];
char* clipboardString;
} _GLFWlibraryNS;
diff --git a/glfw/src/cocoa_window.m b/glfw/src/cocoa_window.m
index a804d6d..7c04af9 100644
--- a/glfw/src/cocoa_window.m
+++ b/glfw/src/cocoa_window.m
@@ -32,6 +32,29 @@
#include <crt_externs.h>
+// Returns the specified standard cursor
+//
+static NSCursor* getStandardCursor(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return [NSCursor arrowCursor];
+ case GLFW_IBEAM_CURSOR:
+ return [NSCursor IBeamCursor];
+ case GLFW_CROSSHAIR_CURSOR:
+ return [NSCursor crosshairCursor];
+ case GLFW_HAND_CURSOR:
+ return [NSCursor pointingHandCursor];
+ case GLFW_HRESIZE_CURSOR:
+ return [NSCursor resizeLeftRightCursor];
+ case GLFW_VRESIZE_CURSOR:
+ return [NSCursor resizeUpDownCursor];
+ }
+
+ return nil;
+}
+
// Center the cursor in the view of the window
//
static void centerCursor(_GLFWwindow *window)
@@ -41,72 +64,42 @@ static void centerCursor(_GLFWwindow *window)
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
}
-// Get the cursor object that window uses in the specified cursor mode
+// Update the cursor to match the specified cursor mode
//
-static NSCursor* getModeCursor(_GLFWwindow* window)
+static void updateModeCursor(_GLFWwindow* window)
{
if (window->cursorMode == GLFW_CURSOR_NORMAL)
{
if (window->cursor)
- return (NSCursor*) window->cursor->ns.object;
+ [(NSCursor*) window->cursor->ns.object set];
else
- return [NSCursor arrowCursor];
+ [[NSCursor arrowCursor] set];
}
else
- return (NSCursor*) _glfw.ns.cursor;
-}
-
-// Update the cursor to match the specified cursor mode
-//
-static void updateModeCursor(_GLFWwindow* window)
-{
- // This is required for the cursor to update if it's inside the window
- [getModeCursor(window) set];
-
- // This is required for the cursor to update if it's outside the window
- [window->ns.object invalidateCursorRectsForView:window->ns.view];
+ [(NSCursor*) _glfw.ns.cursor set];
}
// Enter fullscreen mode
//
-static void enterFullscreenMode(_GLFWwindow* window)
+static GLboolean enterFullscreenMode(_GLFWwindow* window)
{
- if ([window->ns.view isInFullScreenMode])
- return;
-
- _glfwSetVideoMode(window->monitor, &window->videoMode);
+ GLboolean status;
- NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithBool:NO],
- NSFullScreenModeAllScreens,
- nil];
+ status = _glfwSetVideoMode(window->monitor, &window->videoMode);
- [window->ns.view enterFullScreenMode:window->monitor->ns.screen
- withOptions:options];
+ // NOTE: The window is resized despite mode setting failure to make
+ // glfwSetWindowSize more robust
+ [window->ns.object setFrame:[window->monitor->ns.screen frame]
+ display:YES];
- // HACK: Synthesize focus event as window does not become key when the view
- // is made full screen
- // TODO: Remove this when moving to a full screen window
- _glfwInputWindowFocus(window, GL_TRUE);
+ return status;
}
// Leave fullscreen mode
//
static void leaveFullscreenMode(_GLFWwindow* window)
{
- if (![window->ns.view isInFullScreenMode])
- return;
-
- // HACK: Synthesize focus event as window does not become key when the view
- // is made full screen
- // TODO: Remove this when moving to a full screen window
- _glfwInputWindowFocus(window, GL_FALSE);
-
_glfwRestoreVideoMode(window->monitor);
-
- // Exit full screen after the video restore to avoid a nasty display
- // flickering during the fade
- [window->ns.view exitFullScreenModeWithOptions:nil];
}
// Transforms the specified y-coordinate between the CG display and NS screen
@@ -163,8 +156,6 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidResize:(NSNotification *)notification
{
- [window->nsgl.context update];
-
const NSRect contentRect = [window->ns.view frame];
const NSRect fbRect = convertRectToBacking(window, contentRect);
@@ -178,8 +169,6 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidMove:(NSNotification *)notification
{
- [window->nsgl.context update];
-
int x, y;
_glfwPlatformGetWindowPos(window, &x, &y);
_glfwInputWindowPos(window, x, y);
@@ -195,20 +184,23 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
- (void)windowDidDeminiaturize:(NSNotification *)notification
{
- if (window->monitor)
- enterFullscreenMode(window);
-
_glfwInputWindowIconify(window, GL_FALSE);
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
+ if (window->monitor)
+ enterFullscreenMode(window);
+
_glfwInputWindowFocus(window, GL_TRUE);
_glfwPlatformApplyCursorMode(window);
}
- (void)windowDidResignKey:(NSNotification *)notification
{
+ if (window->monitor)
+ leaveFullscreenMode(window);
+
_glfwInputWindowFocus(window, GL_FALSE);
}
@@ -258,6 +250,13 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)
_glfwInputMonitorChange();
}
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ [NSApp stop:nil];
+
+ _glfwPlatformPostEmptyEvent();
+}
+
@end
// Translates OS X key modifiers into GLFW ones
@@ -282,143 +281,10 @@ static int translateFlags(NSUInteger flags)
//
static int translateKey(unsigned int key)
{
- // Keyboard symbol translation table
- static const unsigned int table[128] =
- {
- /* 00 */ GLFW_KEY_A,
- /* 01 */ GLFW_KEY_S,
- /* 02 */ GLFW_KEY_D,
- /* 03 */ GLFW_KEY_F,
- /* 04 */ GLFW_KEY_H,
- /* 05 */ GLFW_KEY_G,
- /* 06 */ GLFW_KEY_Z,
- /* 07 */ GLFW_KEY_X,
- /* 08 */ GLFW_KEY_C,
- /* 09 */ GLFW_KEY_V,
- /* 0a */ GLFW_KEY_WORLD_1,
- /* 0b */ GLFW_KEY_B,
- /* 0c */ GLFW_KEY_Q,
- /* 0d */ GLFW_KEY_W,
- /* 0e */ GLFW_KEY_E,
- /* 0f */ GLFW_KEY_R,
- /* 10 */ GLFW_KEY_Y,
- /* 11 */ GLFW_KEY_T,
- /* 12 */ GLFW_KEY_1,
- /* 13 */ GLFW_KEY_2,
- /* 14 */ GLFW_KEY_3,
- /* 15 */ GLFW_KEY_4,
- /* 16 */ GLFW_KEY_6,
- /* 17 */ GLFW_KEY_5,
- /* 18 */ GLFW_KEY_EQUAL,
- /* 19 */ GLFW_KEY_9,
- /* 1a */ GLFW_KEY_7,
- /* 1b */ GLFW_KEY_MINUS,
- /* 1c */ GLFW_KEY_8,
- /* 1d */ GLFW_KEY_0,
- /* 1e */ GLFW_KEY_RIGHT_BRACKET,
- /* 1f */ GLFW_KEY_O,
- /* 20 */ GLFW_KEY_U,
- /* 21 */ GLFW_KEY_LEFT_BRACKET,
- /* 22 */ GLFW_KEY_I,
- /* 23 */ GLFW_KEY_P,
- /* 24 */ GLFW_KEY_ENTER,
- /* 25 */ GLFW_KEY_L,
- /* 26 */ GLFW_KEY_J,
- /* 27 */ GLFW_KEY_APOSTROPHE,
- /* 28 */ GLFW_KEY_K,
- /* 29 */ GLFW_KEY_SEMICOLON,
- /* 2a */ GLFW_KEY_BACKSLASH,
- /* 2b */ GLFW_KEY_COMMA,
- /* 2c */ GLFW_KEY_SLASH,
- /* 2d */ GLFW_KEY_N,
- /* 2e */ GLFW_KEY_M,
- /* 2f */ GLFW_KEY_PERIOD,
- /* 30 */ GLFW_KEY_TAB,
- /* 31 */ GLFW_KEY_SPACE,
- /* 32 */ GLFW_KEY_GRAVE_ACCENT,
- /* 33 */ GLFW_KEY_BACKSPACE,
- /* 34 */ GLFW_KEY_UNKNOWN,
- /* 35 */ GLFW_KEY_ESCAPE,
- /* 36 */ GLFW_KEY_RIGHT_SUPER,
- /* 37 */ GLFW_KEY_LEFT_SUPER,
- /* 38 */ GLFW_KEY_LEFT_SHIFT,
- /* 39 */ GLFW_KEY_CAPS_LOCK,
- /* 3a */ GLFW_KEY_LEFT_ALT,
- /* 3b */ GLFW_KEY_LEFT_CONTROL,
- /* 3c */ GLFW_KEY_RIGHT_SHIFT,
- /* 3d */ GLFW_KEY_RIGHT_ALT,
- /* 3e */ GLFW_KEY_RIGHT_CONTROL,
- /* 3f */ GLFW_KEY_UNKNOWN, /* Function */
- /* 40 */ GLFW_KEY_F17,
- /* 41 */ GLFW_KEY_KP_DECIMAL,
- /* 42 */ GLFW_KEY_UNKNOWN,
- /* 43 */ GLFW_KEY_KP_MULTIPLY,
- /* 44 */ GLFW_KEY_UNKNOWN,
- /* 45 */ GLFW_KEY_KP_ADD,
- /* 46 */ GLFW_KEY_UNKNOWN,
- /* 47 */ GLFW_KEY_NUM_LOCK, /* Really KeypadClear... */
- /* 48 */ GLFW_KEY_UNKNOWN, /* VolumeUp */
- /* 49 */ GLFW_KEY_UNKNOWN, /* VolumeDown */
- /* 4a */ GLFW_KEY_UNKNOWN, /* Mute */
- /* 4b */ GLFW_KEY_KP_DIVIDE,
- /* 4c */ GLFW_KEY_KP_ENTER,
- /* 4d */ GLFW_KEY_UNKNOWN,
- /* 4e */ GLFW_KEY_KP_SUBTRACT,
- /* 4f */ GLFW_KEY_F18,
- /* 50 */ GLFW_KEY_F19,
- /* 51 */ GLFW_KEY_KP_EQUAL,
- /* 52 */ GLFW_KEY_KP_0,
- /* 53 */ GLFW_KEY_KP_1,
- /* 54 */ GLFW_KEY_KP_2,
- /* 55 */ GLFW_KEY_KP_3,
- /* 56 */ GLFW_KEY_KP_4,
- /* 57 */ GLFW_KEY_KP_5,
- /* 58 */ GLFW_KEY_KP_6,
- /* 59 */ GLFW_KEY_KP_7,
- /* 5a */ GLFW_KEY_F20,
- /* 5b */ GLFW_KEY_KP_8,
- /* 5c */ GLFW_KEY_KP_9,
- /* 5d */ GLFW_KEY_UNKNOWN,
- /* 5e */ GLFW_KEY_UNKNOWN,
- /* 5f */ GLFW_KEY_UNKNOWN,
- /* 60 */ GLFW_KEY_F5,
- /* 61 */ GLFW_KEY_F6,
- /* 62 */ GLFW_KEY_F7,
- /* 63 */ GLFW_KEY_F3,
- /* 64 */ GLFW_KEY_F8,
- /* 65 */ GLFW_KEY_F9,
- /* 66 */ GLFW_KEY_UNKNOWN,
- /* 67 */ GLFW_KEY_F11,
- /* 68 */ GLFW_KEY_UNKNOWN,
- /* 69 */ GLFW_KEY_F13,
- /* 6a */ GLFW_KEY_F16,
- /* 6b */ GLFW_KEY_F14,
- /* 6c */ GLFW_KEY_UNKNOWN,
- /* 6d */ GLFW_KEY_F10,
- /* 6e */ GLFW_KEY_UNKNOWN,
- /* 6f */ GLFW_KEY_F12,
- /* 70 */ GLFW_KEY_UNKNOWN,
- /* 71 */ GLFW_KEY_F15,
- /* 72 */ GLFW_KEY_INSERT, /* Really Help... */
- /* 73 */ GLFW_KEY_HOME,
- /* 74 */ GLFW_KEY_PAGE_UP,
- /* 75 */ GLFW_KEY_DELETE,
- /* 76 */ GLFW_KEY_F4,
- /* 77 */ GLFW_KEY_END,
- /* 78 */ GLFW_KEY_F2,
- /* 79 */ GLFW_KEY_PAGE_DOWN,
- /* 7a */ GLFW_KEY_F1,
- /* 7b */ GLFW_KEY_LEFT,
- /* 7c */ GLFW_KEY_RIGHT,
- /* 7d */ GLFW_KEY_DOWN,
- /* 7e */ GLFW_KEY_UP,
- /* 7f */ GLFW_KEY_UNKNOWN,
- };
-
- if (key >= 128)
+ if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
return GLFW_KEY_UNKNOWN;
- return table[key];
+ return _glfw.ns.publicKeys[key];
}
@@ -426,7 +292,7 @@ static int translateKey(unsigned int key)
// Content view class for the GLFW window
//------------------------------------------------------------------------
-@interface GLFWContentView : NSView
+@interface GLFWContentView : NSOpenGLView
{
_GLFWwindow* window;
NSTrackingArea* trackingArea;
@@ -454,7 +320,8 @@ static int translateKey(unsigned int key)
- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
{
- self = [super init];
+ self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)
+ pixelFormat:nil];
if (self != nil)
{
window = initWindow;
@@ -572,13 +439,11 @@ static int translateKey(unsigned int key)
- (void)mouseExited:(NSEvent *)event
{
- window->ns.cursorInside = GL_FALSE;
_glfwInputCursorEnter(window, GL_FALSE);
}
- (void)mouseEntered:(NSEvent *)event
{
- window->ns.cursorInside = GL_TRUE;
_glfwInputCursorEnter(window, GL_TRUE);
}
@@ -598,10 +463,12 @@ static int translateKey(unsigned int key)
[trackingArea release];
}
- NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow |
- NSTrackingCursorUpdate |
- NSTrackingInVisibleRect;
+ const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow |
+ NSTrackingEnabledDuringMouseDrag |
+ NSTrackingCursorUpdate |
+ NSTrackingInVisibleRect |
+ NSTrackingAssumeInside;
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:options
@@ -624,7 +491,13 @@ static int translateKey(unsigned int key)
const int plain = !(mods & GLFW_MOD_SUPER);
for (i = 0; i < length; i++)
- _glfwInputChar(window, [characters characterAtIndex:i], mods, plain);
+ {
+ const unichar codepoint = [characters characterAtIndex:i];
+ if ((codepoint & 0xff00) == 0xf700)
+ continue;
+
+ _glfwInputChar(window, codepoint, mods, plain);
+ }
}
- (void)flagsChanged:(NSEvent *)event
@@ -686,11 +559,6 @@ static int translateKey(unsigned int key)
_glfwInputScroll(window, deltaX, deltaY);
}
-- (void)resetCursorRects
-{
- [self addCursorRect:[self bounds] cursor:getModeCursor(window)];
-}
-
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
@@ -925,7 +793,18 @@ static GLboolean initializeAppKit(void)
createMenuBar();
#endif
- [NSApp finishLaunching];
+ // There can only be one application delegate, but we allocate it the
+ // first time a window is created to keep all window code in this file
+ id delegate = [[GLFWApplicationDelegate alloc] init];
+ if (delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create application delegate");
+ return GL_FALSE;
+ }
+
+ [NSApp setDelegate:delegate];
+ [NSApp run];
return GL_TRUE;
}
@@ -956,8 +835,15 @@ static GLboolean createWindow(_GLFWwindow* window,
styleMask |= NSResizableWindowMask;
}
+ NSRect contentRect;
+
+ if (wndconfig->monitor)
+ contentRect = [wndconfig->monitor->ns.screen frame];
+ else
+ contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
+
window->ns.object = [[GLFWWindow alloc]
- initWithContentRect:NSMakeRect(0, 0, wndconfig->width, wndconfig->height)
+ initWithContentRect:contentRect
styleMask:styleMask
backing:NSBackingStoreBuffered
defer:NO];
@@ -968,28 +854,30 @@ static GLboolean createWindow(_GLFWwindow* window,
return GL_FALSE;
}
- window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
-
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
{
-#if defined(_GLFW_USE_RETINA)
- [window->ns.view setWantsBestResolutionOpenGLSurface:YES];
-#endif
-
if (wndconfig->resizable)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
}
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
- if (wndconfig->floating)
- [window->ns.object setLevel:NSFloatingWindowLevel];
+ if (wndconfig->monitor)
+ {
+ [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+ [window->ns.object setHidesOnDeactivate:YES];
+ }
+ else
+ {
+ [window->ns.object center];
+
+ if (wndconfig->floating)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+ }
[window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
- [window->ns.object setContentView:window->ns.view];
[window->ns.object setDelegate:window->ns.delegate];
[window->ns.object setAcceptsMouseMovedEvents:YES];
- [window->ns.object center];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
@@ -1012,31 +900,36 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!initializeAppKit())
return GL_FALSE;
- // There can only be one application delegate, but we allocate it the
- // first time a window is created to keep all window code in this file
- if (_glfw.ns.delegate == nil)
- {
- _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
- if (_glfw.ns.delegate == nil)
- {
- _glfwInputError(GLFW_PLATFORM_ERROR,
- "Cocoa: Failed to create application delegate");
- return GL_FALSE;
- }
-
- [NSApp setDelegate:_glfw.ns.delegate];
- }
-
if (!createWindow(window, wndconfig))
return GL_FALSE;
if (!_glfwCreateContext(window, ctxconfig, fbconfig))
return GL_FALSE;
+ window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
+
+#if defined(_GLFW_USE_RETINA)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)
+ [window->ns.view setWantsBestResolutionOpenGLSurface:YES];
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+#endif /*_GLFW_USE_RETINA*/
+
+ [window->ns.object setContentView:window->ns.view];
+ // NOTE: If you set the pixel format before the context it creates another
+ // context, only to have it destroyed by the next line
+ // We cannot use the view to create the context because that interface
+ // does not support context resource sharing
+ [window->ns.view setOpenGLContext:window->nsgl.context];
+ [window->ns.view setPixelFormat:window->nsgl.pixelFormat];
[window->nsgl.context setView:window->ns.view];
if (wndconfig->monitor)
- enterFullscreenMode(window);
+ {
+ _glfwPlatformShowWindow(window);
+ if (!enterFullscreenMode(window))
+ return GL_FALSE;
+ }
return GL_TRUE;
}
@@ -1132,9 +1025,6 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
{
- if (window->monitor)
- leaveFullscreenMode(window);
-
[window->ns.object miniaturize:nil];
}
@@ -1152,7 +1042,6 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
[NSApp activateIgnoringOtherApps:YES];
[window->ns.object makeKeyAndOrderFront:nil];
- _glfwInputWindowVisibility(window, GL_TRUE);
}
void _glfwPlatformUnhideWindow(_GLFWwindow* window)
@@ -1288,6 +1177,19 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
return GL_TRUE;
}
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ cursor->ns.object = getStandardCursor(shape);
+ if (!cursor->ns.object)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Cocoa: Invalid standard cursor");
+ return GL_FALSE;
+ }
+
+ [cursor->ns.object retain];
+ return GL_TRUE;
+}
+
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->ns.object)
@@ -1296,7 +1198,10 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
{
- if (window->cursorMode == GLFW_CURSOR_NORMAL && window->ns.cursorInside)
+ const NSPoint p = [window->ns.object mouseLocationOutsideOfEventStream];
+
+ if (window->cursorMode == GLFW_CURSOR_NORMAL &&
+ [window->ns.view mouse:p inRect:[window->ns.view frame]])
{
if (cursor)
[(NSCursor*) cursor->ns.object set];
diff --git a/glfw/src/glfw_config.h.in b/glfw/src/glfw_config.h.in
index 11c2aa7..485cac5 100644
--- a/glfw/src/glfw_config.h.in
+++ b/glfw/src/glfw_config.h.in
@@ -42,6 +42,8 @@
#cmakedefine _GLFW_COCOA
// Define this to 1 if building GLFW for Wayland
#cmakedefine _GLFW_WAYLAND
+// Define this to 1 if building GLFW for Mir
+#cmakedefine _GLFW_MIR
// Define this to 1 if building GLFW for EGL
#cmakedefine _GLFW_EGL
diff --git a/glfw/src/init.c b/glfw/src/init.c
index 7e5204a..4a044ed 100644
--- a/glfw/src/init.c
+++ b/glfw/src/init.c
@@ -129,7 +129,7 @@ GLFWAPI int glfwInit(void)
}
_glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
- if (_glfw.monitors == NULL)
+ if (!_glfw.monitorCount)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "No monitors found");
_glfwPlatformTerminate();
@@ -153,11 +153,9 @@ GLFWAPI void glfwTerminate(void)
memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
- // Close all remaining windows
while (_glfw.windowListHead)
glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
- // Destroy all cursors
while (_glfw.cursorListHead)
glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
diff --git a/glfw/src/input.c b/glfw/src/input.c
index a2d8ddc..b1ed02f 100644
--- a/glfw/src/input.c
+++ b/glfw/src/input.c
@@ -382,6 +382,25 @@ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
return (GLFWcursor*) cursor;
}
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
+{
+ _GLFWcursor* cursor;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ cursor = calloc(1, sizeof(_GLFWcursor));
+ cursor->next = _glfw.cursorListHead;
+ _glfw.cursorListHead = cursor;
+
+ if (!_glfwPlatformCreateStandardCursor(cursor, shape))
+ {
+ glfwDestroyCursor((GLFWcursor*) cursor);
+ return NULL;
+ }
+
+ return (GLFWcursor*) cursor;
+}
+
GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
{
_GLFWcursor* cursor = (_GLFWcursor*) handle;
diff --git a/glfw/src/internal.h b/glfw/src/internal.h
index 62504e4..26fcf2a 100644
--- a/glfw/src/internal.h
+++ b/glfw/src/internal.h
@@ -74,6 +74,8 @@ typedef struct _GLFWcursor _GLFWcursor;
#include "x11_platform.h"
#elif defined(_GLFW_WAYLAND)
#include "wl_platform.h"
+#elif defined(_GLFW_MIR)
+ #include "mir_platform.h"
#else
#error "No supported window creation API selected"
#endif
@@ -623,6 +625,11 @@ GLFWglproc _glfwPlatformGetProcAddress(const char* procname);
*/
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
+/*! @copydoc glfwCreateStandardCursor
+ * @ingroup platform
+ */
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
+
/*! @copydoc glfwDestroyCursor
* @ingroup platform
*/
diff --git a/glfw/src/linux_joystick.c b/glfw/src/linux_joystick.c
index c0c4b3d..c93184e 100644
--- a/glfw/src/linux_joystick.c
+++ b/glfw/src/linux_joystick.c
@@ -27,14 +27,14 @@
#include "internal.h"
-#ifdef __linux__
+#if defined(__linux__)
#include <linux/joystick.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/inotify.h>
#include <fcntl.h>
#include <errno.h>
-#include <regex.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
@@ -45,16 +45,34 @@
// Attempt to open the specified joystick device
//
-static int openJoystickDevice(int joy, const char* path)
+static void openJoystickDevice(const char* path)
{
-#ifdef __linux__
+#if defined(__linux__)
char axisCount, buttonCount;
char name[256];
- int fd, version;
+ int joy, fd, version;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.linux_js[joy].present)
+ continue;
+
+ if (strcmp(_glfw.linux_js[joy].path, path) == 0)
+ return;
+ }
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.linux_js[joy].present)
+ break;
+ }
+
+ if (joy > GLFW_JOYSTICK_LAST)
+ return;
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd == -1)
- return GL_FALSE;
+ return;
_glfw.linux_js[joy].fd = fd;
@@ -64,13 +82,14 @@ static int openJoystickDevice(int joy, const char* path)
{
// It's an old 0.x interface (we don't support it)
close(fd);
- return GL_FALSE;
+ return;
}
if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
strncpy(name, "Unknown", sizeof(name));
_glfw.linux_js[joy].name = strdup(name);
+ _glfw.linux_js[joy].path = strdup(path);
ioctl(fd, JSIOCGAXES, &axisCount);
_glfw.linux_js[joy].axisCount = (int) axisCount;
@@ -83,18 +102,34 @@ static int openJoystickDevice(int joy, const char* path)
_glfw.linux_js[joy].present = GL_TRUE;
#endif // __linux__
-
- return GL_TRUE;
}
// Polls for and processes events for all present joysticks
//
static void pollJoystickEvents(void)
{
-#ifdef __linux__
+#if defined(__linux__)
int i;
- ssize_t result;
struct js_event e;
+ ssize_t offset = 0;
+ char buffer[16384];
+
+ const ssize_t size = read(_glfw.x11.inotify.fd, buffer, sizeof(buffer));
+
+ while (size > offset)
+ {
+ regmatch_t match;
+ const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
+
+ if (regexec(&_glfw.x11.inotify.regex, e->name, 1, &match, 0) == 0)
+ {
+ char path[20];
+ snprintf(path, sizeof(path), "/dev/input/%s", e->name);
+ openJoystickDevice(path);
+ }
+
+ offset += sizeof(struct inotify_event) + e->len;
+ }
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
{
@@ -105,19 +140,22 @@ static void pollJoystickEvents(void)
for (;;)
{
errno = 0;
- result = read(_glfw.linux_js[i].fd, &e, sizeof(e));
-
- if (errno == ENODEV)
+ if (read(_glfw.linux_js[i].fd, &e, sizeof(e)) < 0)
{
- free(_glfw.linux_js[i].axes);
- free(_glfw.linux_js[i].buttons);
- free(_glfw.linux_js[i].name);
+ if (errno == ENODEV)
+ {
+ // The joystick was disconnected
- memset(&_glfw.linux_js[i], 0, sizeof(_glfw.linux_js[i]));
- }
+ free(_glfw.linux_js[i].axes);
+ free(_glfw.linux_js[i].buttons);
+ free(_glfw.linux_js[i].name);
+ free(_glfw.linux_js[i].path);
+
+ memset(&_glfw.linux_js[i], 0, sizeof(_glfw.linux_js[i]));
+ }
- if (result == -1)
break;
+ }
// We don't care if it's an init event or not
e.type &= ~JS_EVENT_INIT;
@@ -149,58 +187,69 @@ static void pollJoystickEvents(void)
// Initialize joystick interface
//
-void _glfwInitJoysticks(void)
+int _glfwInitJoysticks(void)
{
-#ifdef __linux__
- int joy = 0;
- size_t i;
- regex_t regex;
+#if defined(__linux__)
+ const char* dirname = "/dev/input";
DIR* dir;
- const char* dirs[] =
- {
- "/dev/input",
- "/dev"
- };
+ struct dirent* entry;
- if (regcomp(&regex, "^js[0-9]\\+$", 0) != 0)
+ _glfw.x11.inotify.fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (_glfw.x11.inotify.fd == -1)
{
- _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to compile regex");
- return;
+ _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to initialize inotify");
+ return GL_FALSE;
}
- for (i = 0; i < sizeof(dirs) / sizeof(dirs[0]); i++)
+ // HACK: Register for IN_ATTRIB as well to get notified when udev is done
+ // This works well in practice but the true way is libudev
+
+ _glfw.x11.inotify.wd = inotify_add_watch(_glfw.x11.inotify.fd,
+ dirname,
+ IN_CREATE | IN_ATTRIB);
+ if (_glfw.x11.inotify.wd == -1)
{
- struct dirent* entry;
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to add watch to %s", dirname);
+ return GL_FALSE;
+ }
- dir = opendir(dirs[i]);
- if (!dir)
- continue;
+ if (regcomp(&_glfw.x11.inotify.regex, "^js[0-9]\\+$", 0) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to compile regex");
+ return GL_FALSE;
+ }
- while ((entry = readdir(dir)))
- {
- char path[20];
- regmatch_t match;
+ dir = opendir(dirname);
+ if (!dir)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Failed to open %s", dirname);
+ return GL_FALSE;
+ }
- if (regexec(&regex, entry->d_name, 1, &match, 0) != 0)
- continue;
+ while ((entry = readdir(dir)))
+ {
+ char path[20];
+ regmatch_t match;
- snprintf(path, sizeof(path), "%s/%s", dirs[i], entry->d_name);
- if (openJoystickDevice(joy, path))
- joy++;
- }
+ if (regexec(&_glfw.x11.inotify.regex, entry->d_name, 1, &match, 0) != 0)
+ continue;
- closedir(dir);
+ snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
+ openJoystickDevice(path);
}
- regfree(&regex);
+ closedir(dir);
#endif // __linux__
+
+ return GL_TRUE;
}
// Close all opened joystick handles
//
void _glfwTerminateJoysticks(void)
{
-#ifdef __linux__
+#if defined(__linux__)
int i;
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
@@ -211,8 +260,17 @@ void _glfwTerminateJoysticks(void)
free(_glfw.linux_js[i].axes);
free(_glfw.linux_js[i].buttons);
free(_glfw.linux_js[i].name);
+ free(_glfw.linux_js[i].path);
}
}
+
+ regfree(&_glfw.x11.inotify.regex);
+
+ if (_glfw.x11.inotify.wd > 0)
+ close(_glfw.x11.inotify.wd);
+
+ if (_glfw.x11.inotify.fd > 0)
+ close(_glfw.x11.inotify.fd);
#endif // __linux__
}
diff --git a/glfw/src/linux_joystick.h b/glfw/src/linux_joystick.h
index 8f713d8..b74a67e 100644
--- a/glfw/src/linux_joystick.h
+++ b/glfw/src/linux_joystick.h
@@ -42,10 +42,11 @@ typedef struct _GLFWjoystickLinux
unsigned char* buttons;
int buttonCount;
char* name;
+ char* path;
} _GLFWjoystickLinux;
-void _glfwInitJoysticks(void);
+int _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
#endif // _linux_joystick_h_
diff --git a/glfw/src/mir_init.c b/glfw/src/mir_init.c
new file mode 100644
index 0000000..fe02e62
--- /dev/null
+++ b/glfw/src/mir_init.c
@@ -0,0 +1,96 @@
+//========================================================================
+// GLFW 3.1 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ int error;
+
+ _glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
+
+ if (!mir_connection_is_valid(_glfw.mir.connection))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to connect to Server");
+ return GL_FALSE;
+ }
+
+ _glfw.mir.display =
+ mir_connection_get_egl_native_display(_glfw.mir.connection);
+
+ if (!_glfwInitContextAPI())
+ return GL_FALSE;
+
+ _glfwInitTimer();
+ _glfwInitJoysticks();
+
+ _glfw.mir.event_queue = calloc(1, sizeof(EventQueue));
+ _glfwInitEventQueue(_glfw.mir.event_queue);
+
+ error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
+ if (error)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Failed to create Event Mutex Error: %i\n", error);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ _glfwTerminateContextAPI();
+ _glfwTerminateJoysticks();
+
+ _glfwDeleteEventQueue(_glfw.mir.event_queue);
+
+ pthread_mutex_destroy(&_glfw.mir.event_mutex);
+
+ mir_connection_release(_glfw.mir.connection);
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ const char* version = _GLFW_VERSION_NUMBER " Mir EGL "
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+
+ return version;
+}
+
diff --git a/glfw/src/mir_monitor.c b/glfw/src/mir_monitor.c
new file mode 100644
index 0000000..bdf47bd
--- /dev/null
+++ b/glfw/src/mir_monitor.c
@@ -0,0 +1,138 @@
+//========================================================================
+// GLFW 3.1 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ int i, found = 0;
+ _GLFWmonitor** monitors = NULL;
+ MirDisplayConfiguration* displayConfig =
+ mir_connection_create_display_config(_glfw.mir.connection);
+
+ *count = 0;
+
+ for (i = 0; i < displayConfig->num_outputs; i++)
+ {
+ const MirDisplayOutput* out = displayConfig->outputs + i;
+
+ if (out->used &&
+ out->connected &&
+ out->num_modes &&
+ out->current_mode < out->num_modes)
+ {
+ found++;
+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
+ monitors[i] = _glfwAllocMonitor("Unknown",
+ out->physical_width_mm,
+ out->physical_height_mm);
+
+ monitors[i]->mir.x = out->position_x;
+ monitors[i]->mir.y = out->position_y;
+ monitors[i]->mir.output_id = out->output_id;
+ monitors[i]->mir.cur_mode = out->current_mode;
+
+ monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
+ &monitors[i]->modeCount);
+ }
+ }
+
+ mir_display_config_destroy(displayConfig);
+
+ *count = found;
+ return monitors;
+}
+
+GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ return first->mir.output_id == second->mir.output_id;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (xpos)
+ *xpos = monitor->mir.x;
+ if (ypos)
+ *ypos = monitor->mir.y;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+ int i;
+ GLFWvidmode* modes = NULL;
+ MirDisplayConfiguration* displayConfig =
+ mir_connection_create_display_config(_glfw.mir.connection);
+
+ for (i = 0; i < displayConfig->num_outputs; i++)
+ {
+ const MirDisplayOutput* out = displayConfig->outputs + i;
+ if (out->output_id != monitor->mir.output_id)
+ continue;
+
+ modes = calloc(out->num_modes, sizeof(GLFWvidmode));
+
+ for (*found = 0; *found < out->num_modes; (*found)++)
+ {
+ modes[*found].width = out->modes[*found].horizontal_resolution;
+ modes[*found].height = out->modes[*found].vertical_resolution;
+ modes[*found].refreshRate = out->modes[*found].refresh_rate;
+ modes[*found].redBits = 8;
+ modes[*found].greenBits = 8;
+ modes[*found].blueBits = 8;
+ }
+
+ break;
+ }
+
+ mir_display_config_destroy(displayConfig);
+
+ return modes;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ *mode = monitor->modes[monitor->mir.cur_mode];
+}
+
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
diff --git a/glfw/src/mir_platform.h b/glfw/src/mir_platform.h
new file mode 100644
index 0000000..7d477e9
--- /dev/null
+++ b/glfw/src/mir_platform.h
@@ -0,0 +1,110 @@
+//========================================================================
+// GLFW 3.1 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _mir_platform_h_
+#define _mir_platform_h_
+
+#include <mir_toolkit/mir_client_library.h>
+
+#include "posix_tls.h"
+#include "posix_time.h"
+#include "linux_joystick.h"
+
+#include <sys/queue.h>
+
+#include <pthread.h>
+
+#if defined(_GLFW_EGL)
+ #include "egl_context.h"
+#else
+ #error "The Mir backend depends on EGL platform support"
+#endif
+
+#define _GLFW_EGL_NATIVE_WINDOW window->mir.window
+#define _GLFW_EGL_NATIVE_DISPLAY _glfw.mir.display
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
+
+// Mir-specific Event Queue
+//
+typedef struct EventQueue
+{
+ TAILQ_HEAD(, EventNode) head;
+} EventQueue;
+
+// Mir-specific per-window data
+//
+typedef struct _GLFWwindowMir
+{
+ MirSurface* surface;
+ int width;
+ int height;
+ MirEGLNativeWindowType window;
+
+} _GLFWwindowMir;
+
+
+// Mir-specific per-monitor data
+//
+typedef struct _GLFWmonitorMir
+{
+ int cur_mode;
+ int output_id;
+ int x;
+ int y;
+
+} _GLFWmonitorMir;
+
+
+// Mir-specific global data
+//
+typedef struct _GLFWlibraryMir
+{
+ MirConnection* connection;
+ MirEGLNativeDisplayType display;
+ EventQueue* event_queue;
+
+ pthread_mutex_t event_mutex;
+ pthread_cond_t event_cond;
+
+} _GLFWlibraryMir;
+
+
+// Mir-specific per-cursor data
+// TODO: Only system cursors are implemented in mir atm. Need to wait for support.
+//
+typedef struct _GLFWcursorMir
+{
+} _GLFWcursorMir;
+
+
+extern void _glfwInitEventQueue(EventQueue* queue);
+extern void _glfwDeleteEventQueue(EventQueue* queue);
+
+#endif // _mir_platform_h_
diff --git a/glfw/src/mir_window.c b/glfw/src/mir_window.c
new file mode 100644
index 0000000..2c8547f
--- /dev/null
+++ b/glfw/src/mir_window.c
@@ -0,0 +1,658 @@
+//========================================================================
+// GLFW 3.1 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+#include "xkb_unicode.h"
+
+#include <linux/input.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+typedef struct EventNode
+{
+ TAILQ_ENTRY(EventNode) entries;
+ MirEvent* event;
+ _GLFWwindow* window;
+} EventNode;
+
+static void deleteNode(EventQueue* queue, EventNode* node)
+{
+ free(node->event);
+ free(node);
+}
+
+static int emptyEventQueue(EventQueue* queue)
+{
+ return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;
+}
+
+static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context)
+{
+ EventNode* new_node = calloc(1, sizeof(EventNode));
+ new_node->event = calloc(1, sizeof(MirEvent));
+ new_node->window = context;
+
+ memcpy(new_node->event, event, sizeof(MirEvent));
+ return new_node;
+}
+
+static void enqueueEvent(MirEvent const* event, _GLFWwindow* context)
+{
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ EventNode* new_node = newEventNode(event, context);
+ TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
+
+ pthread_cond_signal(&_glfw.mir.event_cond);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+}
+
+static EventNode* dequeueEvent(EventQueue* queue)
+{
+ EventNode* node = NULL;
+
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ node = queue->head.tqh_first;
+
+ if (node)
+ TAILQ_REMOVE(&queue->head, node, entries);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+
+ return node;
+}
+
+static MirPixelFormat findValidPixelFormat(void)
+{
+ unsigned int i, validFormats, size = 32;
+ MirPixelFormat formats[size];
+
+ mir_connection_get_available_surface_formats(_glfw.mir.connection, formats,
+ size, &validFormats);
+
+ for (i = 0; i < validFormats; i++)
+ {
+ if (formats[i] == mir_pixel_format_abgr_8888 ||
+ formats[i] == mir_pixel_format_xbgr_8888 ||
+ formats[i] == mir_pixel_format_argb_8888 ||
+ formats[i] == mir_pixel_format_xrgb_8888)
+ {
+ return formats[i];
+ }
+ }
+
+ return mir_pixel_format_invalid;
+}
+
+static int mirModToGLFWMod(uint32_t mods)
+{
+ int publicMods = 0x0;
+
+ if (mods & mir_key_modifier_alt)
+ publicMods |= GLFW_MOD_ALT;
+ else if (mods & mir_key_modifier_shift)
+ publicMods |= GLFW_MOD_SHIFT;
+ else if (mods & mir_key_modifier_ctrl)
+ publicMods |= GLFW_MOD_CONTROL;
+ else if (mods & mir_key_modifier_meta)
+ publicMods |= GLFW_MOD_SUPER;
+
+ return publicMods;
+}
+
+// Taken from wl_init.c
+static int toGLFWKeyCode(uint32_t key)
+{
+ switch (key)
+ {
+ case KEY_GRAVE: return GLFW_KEY_GRAVE_ACCENT;
+ case KEY_1: return GLFW_KEY_1;
+ case KEY_2: return GLFW_KEY_2;
+ case KEY_3: return GLFW_KEY_3;
+ case KEY_4: return GLFW_KEY_4;
+ case KEY_5: return GLFW_KEY_5;
+ case KEY_6: return GLFW_KEY_6;
+ case KEY_7: return GLFW_KEY_7;
+ case KEY_8: return GLFW_KEY_8;
+ case KEY_9: return GLFW_KEY_9;
+ case KEY_0: return GLFW_KEY_0;
+ case KEY_MINUS: return GLFW_KEY_MINUS;
+ case KEY_EQUAL: return GLFW_KEY_EQUAL;
+ case KEY_Q: return GLFW_KEY_Q;
+ case KEY_W: return GLFW_KEY_W;
+ case KEY_E: return GLFW_KEY_E;
+ case KEY_R: return GLFW_KEY_R;
+ case KEY_T: return GLFW_KEY_T;
+ case KEY_Y: return GLFW_KEY_Y;
+ case KEY_U: return GLFW_KEY_U;
+ case KEY_I: return GLFW_KEY_I;
+ case KEY_O: return GLFW_KEY_O;
+ case KEY_P: return GLFW_KEY_P;
+ case KEY_LEFTBRACE: return GLFW_KEY_LEFT_BRACKET;
+ case KEY_RIGHTBRACE: return GLFW_KEY_RIGHT_BRACKET;
+ case KEY_A: return GLFW_KEY_A;
+ case KEY_S: return GLFW_KEY_S;
+ case KEY_D: return GLFW_KEY_D;
+ case KEY_F: return GLFW_KEY_F;
+ case KEY_G: return GLFW_KEY_G;
+ case KEY_H: return GLFW_KEY_H;
+ case KEY_J: return GLFW_KEY_J;
+ case KEY_K: return GLFW_KEY_K;
+ case KEY_L: return GLFW_KEY_L;
+ case KEY_SEMICOLON: return GLFW_KEY_SEMICOLON;
+ case KEY_APOSTROPHE: return GLFW_KEY_APOSTROPHE;
+ case KEY_Z: return GLFW_KEY_Z;
+ case KEY_X: return GLFW_KEY_X;
+ case KEY_C: return GLFW_KEY_C;
+ case KEY_V: return GLFW_KEY_V;
+ case KEY_B: return GLFW_KEY_B;
+ case KEY_N: return GLFW_KEY_N;
+ case KEY_M: return GLFW_KEY_M;
+ case KEY_COMMA: return GLFW_KEY_COMMA;
+ case KEY_DOT: return GLFW_KEY_PERIOD;
+ case KEY_SLASH: return GLFW_KEY_SLASH;
+ case KEY_BACKSLASH: return GLFW_KEY_BACKSLASH;
+ case KEY_ESC: return GLFW_KEY_ESCAPE;
+ case KEY_TAB: return GLFW_KEY_TAB;
+ case KEY_LEFTSHIFT: return GLFW_KEY_LEFT_SHIFT;
+ case KEY_RIGHTSHIFT: return GLFW_KEY_RIGHT_SHIFT;
+ case KEY_LEFTCTRL: return GLFW_KEY_LEFT_CONTROL;
+ case KEY_RIGHTCTRL: return GLFW_KEY_RIGHT_CONTROL;
+ case KEY_LEFTALT: return GLFW_KEY_LEFT_ALT;
+ case KEY_RIGHTALT: return GLFW_KEY_RIGHT_ALT;
+ case KEY_LEFTMETA: return GLFW_KEY_LEFT_SUPER;
+ case KEY_RIGHTMETA: return GLFW_KEY_RIGHT_SUPER;
+ case KEY_MENU: return GLFW_KEY_MENU;
+ case KEY_NUMLOCK: return GLFW_KEY_NUM_LOCK;
+ case KEY_CAPSLOCK: return GLFW_KEY_CAPS_LOCK;
+ case KEY_PRINT: return GLFW_KEY_PRINT_SCREEN;
+ case KEY_SCROLLLOCK: return GLFW_KEY_SCROLL_LOCK;
+ case KEY_PAUSE: return GLFW_KEY_PAUSE;
+ case KEY_DELETE: return GLFW_KEY_DELETE;
+ case KEY_BACKSPACE: return GLFW_KEY_BACKSPACE;
+ case KEY_ENTER: return GLFW_KEY_ENTER;
+ case KEY_HOME: return GLFW_KEY_HOME;
+ case KEY_END: return GLFW_KEY_END;
+ case KEY_PAGEUP: return GLFW_KEY_PAGE_UP;
+ case KEY_PAGEDOWN: return GLFW_KEY_PAGE_DOWN;
+ case KEY_INSERT: return GLFW_KEY_INSERT;
+ case KEY_LEFT: return GLFW_KEY_LEFT;
+ case KEY_RIGHT: return GLFW_KEY_RIGHT;
+ case KEY_DOWN: return GLFW_KEY_DOWN;
+ case KEY_UP: return GLFW_KEY_UP;
+ case KEY_F1: return GLFW_KEY_F1;
+ case KEY_F2: return GLFW_KEY_F2;
+ case KEY_F3: return GLFW_KEY_F3;
+ case KEY_F4: return GLFW_KEY_F4;
+ case KEY_F5: return GLFW_KEY_F5;
+ case KEY_F6: return GLFW_KEY_F6;
+ case KEY_F7: return GLFW_KEY_F7;
+ case KEY_F8: return GLFW_KEY_F8;
+ case KEY_F9: return GLFW_KEY_F9;
+ case KEY_F10: return GLFW_KEY_F10;
+ case KEY_F11: return GLFW_KEY_F11;
+ case KEY_F12: return GLFW_KEY_F12;
+ case KEY_F13: return GLFW_KEY_F13;
+ case KEY_F14: return GLFW_KEY_F14;
+ case KEY_F15: return GLFW_KEY_F15;
+ case KEY_F16: return GLFW_KEY_F16;
+ case KEY_F17: return GLFW_KEY_F17;
+ case KEY_F18: return GLFW_KEY_F18;
+ case KEY_F19: return GLFW_KEY_F19;
+ case KEY_F20: return GLFW_KEY_F20;
+ case KEY_F21: return GLFW_KEY_F21;
+ case KEY_F22: return GLFW_KEY_F22;
+ case KEY_F23: return GLFW_KEY_F23;
+ case KEY_F24: return GLFW_KEY_F24;
+ case KEY_KPSLASH: return GLFW_KEY_KP_DIVIDE;
+ case KEY_KPDOT: return GLFW_KEY_KP_MULTIPLY;
+ case KEY_KPMINUS: return GLFW_KEY_KP_SUBTRACT;
+ case KEY_KPPLUS: return GLFW_KEY_KP_ADD;
+ case KEY_KP0: return GLFW_KEY_KP_0;
+ case KEY_KP1: return GLFW_KEY_KP_1;
+ case KEY_KP2: return GLFW_KEY_KP_2;
+ case KEY_KP3: return GLFW_KEY_KP_3;
+ case KEY_KP4: return GLFW_KEY_KP_4;
+ case KEY_KP5: return GLFW_KEY_KP_5;
+ case KEY_KP6: return GLFW_KEY_KP_6;
+ case KEY_KP7: return GLFW_KEY_KP_7;
+ case KEY_KP8: return GLFW_KEY_KP_8;
+ case KEY_KP9: return GLFW_KEY_KP_9;
+ case KEY_KPCOMMA: return GLFW_KEY_KP_DECIMAL;
+ case KEY_KPEQUAL: return GLFW_KEY_KP_EQUAL;
+ case KEY_KPENTER: return GLFW_KEY_KP_ENTER;
+ default: return GLFW_KEY_UNKNOWN;
+ }
+}
+
+static void handleKeyEvent(const MirKeyEvent key, _GLFWwindow* window)
+{
+ const int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS;
+ const int mods = mirModToGLFWMod(key.modifiers);
+ const long text = _glfwKeySym2Unicode(key.key_code);
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+
+ _glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods);
+
+ if (text != -1)
+ _glfwInputChar(window, text, mods, plain);
+}
+
+static void handleMouseButton(_GLFWwindow* window,
+ int pressed, int mods, MirMotionButton button)
+{
+ static int lastButton;
+ int publicButton;
+ const int publicMods = mirModToGLFWMod(mods);
+
+ switch (button)
+ {
+ case mir_motion_button_primary:
+ publicButton = GLFW_MOUSE_BUTTON_LEFT;
+ break;
+ case mir_motion_button_secondary:
+ publicButton = GLFW_MOUSE_BUTTON_RIGHT;
+ break;
+ case mir_motion_button_tertiary:
+ publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
+ break;
+ case mir_motion_button_forward:
+ // FIXME What is the forward button?
+ publicButton = GLFW_MOUSE_BUTTON_4;
+ break;
+ case mir_motion_button_back:
+ // FIXME What is the back button?
+ publicButton = GLFW_MOUSE_BUTTON_5;
+ break;
+ default:
+ publicButton = lastButton;
+ break;
+ }
+
+ lastButton = publicButton;
+
+ _glfwInputMouseClick(window, publicButton, pressed, publicMods);
+}
+
+static void handleMouseMotion(_GLFWwindow* window, int x, int y)
+{
+ _glfwInputCursorMotion(window, x, y);
+}
+
+static void handleMouseScroll(_GLFWwindow* window, int dx, int dy)
+{
+ _glfwInputScroll(window, dx, dy);
+}
+
+static void handleMouseEvent(const MirMotionEvent motion,
+ int cord_index,
+ _GLFWwindow* window)
+{
+ switch (motion.action)
+ {
+ case mir_motion_action_down:
+ case mir_motion_action_pointer_down:
+ handleMouseButton(window, GLFW_PRESS,
+ motion.modifiers, motion.button_state);
+ break;
+ case mir_motion_action_up:
+ case mir_motion_action_pointer_up:
+ handleMouseButton(window, GLFW_RELEASE,
+ motion.modifiers, motion.button_state);
+ break;
+ case mir_motion_action_hover_move:
+ case mir_motion_action_move:
+ handleMouseMotion(window,
+ motion.pointer_coordinates[cord_index].x,
+ motion.pointer_coordinates[cord_index].y);
+ break;
+ case mir_motion_action_outside:
+ break;
+ case mir_motion_action_scroll:
+ handleMouseScroll(window,
+ motion.pointer_coordinates[cord_index].hscroll,
+ motion.pointer_coordinates[cord_index].vscroll);
+ break;
+ case mir_motion_action_cancel:
+ case mir_motion_action_hover_enter:
+ case mir_motion_action_hover_exit:
+ break;
+ default:
+ break;
+
+ }
+}
+
+static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window)
+{
+ int i;
+ for (i = 0; i < motion.pointer_count; i++)
+ handleMouseEvent(motion, i, window);
+}
+
+static void handleInput(MirEvent const* event, _GLFWwindow* window)
+{
+ switch (event->type)
+ {
+ case mir_event_type_key:
+ handleKeyEvent(event->key, window);
+ break;
+ case mir_event_type_motion:
+ handleMotionEvent(event->motion, window);
+ break;
+ default:
+ break;
+ }
+}
+
+static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context)
+{
+ enqueueEvent(event, context);
+}
+
+static int createSurface(_GLFWwindow* window)
+{
+ MirSurfaceParameters params =
+ {
+ .name = "MirSurface",
+ .width = window->mir.width,
+ .height = window->mir.height,
+ .pixel_format = mir_pixel_format_invalid,
+ .buffer_usage = mir_buffer_usage_hardware,
+ .output_id = mir_display_output_id_invalid
+ };
+
+ MirEventDelegate delegate =
+ {
+ addNewEvent,
+ window
+ };
+
+ params.pixel_format = findValidPixelFormat();
+ if (params.pixel_format == mir_pixel_format_invalid)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to find a correct pixel format");
+ return GL_FALSE;
+ }
+
+ window->mir.surface =
+ mir_connection_create_surface_sync(_glfw.mir.connection, &params);
+ if (!mir_surface_is_valid(window->mir.surface))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to create surface");
+ return GL_FALSE;
+ }
+
+ mir_surface_set_event_handler(window->mir.surface, &delegate);
+
+ return GL_TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInitEventQueue(EventQueue* queue)
+{
+ TAILQ_INIT(&queue->head);
+}
+
+void _glfwDeleteEventQueue(EventQueue* queue)
+{
+ if (queue)
+ {
+ EventNode* node, *node_next;
+ node = queue->head.tqh_first;
+
+ while (node != NULL)
+ {
+ node_next = node->entries.tqe_next;
+
+ TAILQ_REMOVE(&queue->head, node, entries);
+ deleteNode(queue, node);
+
+ node = node_next;
+ }
+
+ free(queue);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!_glfwCreateContext(window, ctxconfig, fbconfig))
+ return GL_FALSE;
+
+ if (wndconfig->monitor)
+ {
+ GLFWvidmode mode;
+ _glfwPlatformGetVideoMode(wndconfig->monitor, &mode);
+
+ mir_surface_set_type(window->mir.surface, mir_surface_state_fullscreen);
+
+ if (wndconfig->width > mode.width || wndconfig->height > mode.height)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Requested surface size is to large (%i %i)",
+ wndconfig->width, wndconfig->height);
+
+ return GL_FALSE;
+ }
+ }
+
+ window->mir.width = wndconfig->width;
+ window->mir.height = wndconfig->height;
+
+ if (!createSurface(window))
+ return GL_FALSE;
+
+ window->mir.window = mir_surface_get_egl_native_window(window->mir.surface);
+
+ return GL_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (mir_surface_is_valid(window->mir.surface))
+ {
+ mir_surface_release_sync(window->mir.surface);
+ window->mir.surface = NULL;
+ }
+
+ _glfwDestroyContext(window);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->mir.width;
+ if (height)
+ *height = window->mir.height;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ mir_surface_set_type(window->mir.surface, mir_surface_state_minimized);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ mir_surface_set_type(window->mir.surface, mir_surface_state_restored);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ EventNode* node = NULL;
+
+ while ((node = dequeueEvent(_glfw.mir.event_queue)))
+ {
+ handleInput(node->event, node->window);
+ deleteNode(_glfw.mir.event_queue, node);
+ }
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ if (emptyEventQueue(_glfw.mir.event_queue))
+ pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->mir.width;
+ if (height)
+ *height = window->mir.height;
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+
+ return GL_FALSE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+
+ return GL_FALSE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformApplyCursorMode(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__);
+
+ return NULL;
+}
+
diff --git a/glfw/src/nsgl_context.m b/glfw/src/nsgl_context.m
index cbdf284..9800977 100644
--- a/glfw/src/nsgl_context.m
+++ b/glfw/src/nsgl_context.m
@@ -124,13 +124,42 @@ int _glfwCreateContext(_GLFWwindow* window,
// Arbitrary array size here
NSOpenGLPixelFormatAttribute attributes[40];
+ ADD_ATTR(NSOpenGLPFAAccelerated);
ADD_ATTR(NSOpenGLPFAClosestPolicy);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
- if (ctxconfig->major > 2)
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+ if (ctxconfig->major >= 4)
+ {
+ ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
+ }
+ else
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+ if (ctxconfig->major >= 3)
+ {
ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+ }
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+ if (ctxconfig->major <= 2)
+ {
+ if (fbconfig->auxBuffers != GLFW_DONT_CARE)
+ ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
+
+ if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
+ fbconfig->accumGreenBits != GLFW_DONT_CARE &&
+ fbconfig->accumBlueBits != GLFW_DONT_CARE &&
+ fbconfig->accumAlphaBits != GLFW_DONT_CARE)
+ {
+ const int accumBits = fbconfig->accumRedBits +
+ fbconfig->accumGreenBits +
+ fbconfig->accumBlueBits +
+ fbconfig->accumAlphaBits;
+
+ ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
+ }
+ }
+
if (fbconfig->redBits != GLFW_DONT_CARE &&
fbconfig->greenBits != GLFW_DONT_CARE &&
fbconfig->blueBits != GLFW_DONT_CARE)
@@ -157,22 +186,6 @@ int _glfwCreateContext(_GLFWwindow* window,
if (fbconfig->stencilBits != GLFW_DONT_CARE)
ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
- if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
- fbconfig->accumGreenBits != GLFW_DONT_CARE &&
- fbconfig->accumBlueBits != GLFW_DONT_CARE &&
- fbconfig->accumAlphaBits != GLFW_DONT_CARE)
- {
- const int accumBits = fbconfig->accumRedBits +
- fbconfig->accumGreenBits +
- fbconfig->accumBlueBits +
- fbconfig->accumAlphaBits;
-
- ADD_ATTR2(NSOpenGLPFAAccumSize, accumBits);
- }
-
- if (fbconfig->auxBuffers != GLFW_DONT_CARE)
- ADD_ATTR2(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
-
if (fbconfig->stereo)
ADD_ATTR(NSOpenGLPFAStereo);
diff --git a/glfw/src/win32_init.c b/glfw/src/win32_init.c
index 5b1c18b..a963689 100644
--- a/glfw/src/win32_init.c
+++ b/glfw/src/win32_init.c
@@ -41,7 +41,7 @@
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on nVidia Optimus systems
//
-GLFWAPI DWORD NvOptimusEnablement = 0x00000001;
+__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
#endif // _GLFW_USE_OPTIMUS_HPG
@@ -120,6 +120,134 @@ static void terminateLibraries(void)
FreeLibrary(_glfw.win32.dwmapi.instance);
}
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
+
+ _glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
+ _glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
+ _glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
+ _glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
+ _glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
+ _glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
+ _glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
+ _glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
+ _glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
+ _glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
+ _glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
+ _glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
+ _glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
+ _glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
+ _glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
+ _glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
+ _glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
+ _glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
+ _glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
+ _glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
+ _glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
+ _glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
+ _glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
+ _glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
+ _glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
+ _glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
+ _glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
+ _glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
+ _glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
+ _glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
+ _glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
+ _glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
+ _glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
+ _glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
+ _glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
+ _glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;
+
+ _glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
+ _glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
+ _glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
+ _glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
+ _glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
+ _glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
+ _glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
+ _glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
+ _glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;
+
+ _glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
+ _glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
+ _glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
+ _glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
+ _glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
+ _glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
+ _glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
+ _glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
+ _glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
+ _glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
+ _glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
+ _glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
+ _glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
+ _glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
+ _glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
+ _glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
+ _glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
+ _glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
+ _glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
+ _glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
+ _glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
+ _glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
+ _glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
+ _glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
+ _glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
+ _glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
+ _glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
+ _glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
+ _glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
+ _glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
+ _glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
+ _glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
+ _glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
+ _glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
+ _glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
+ _glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
+ _glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
+ _glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
+ _glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
+ _glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
+ _glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
+ _glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
+ _glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
+ _glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
+ _glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
+ _glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;
+
+ _glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
+ _glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
+ _glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
+ _glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
+ _glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
+ _glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
+ _glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
+ _glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
+ _glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
+ _glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
+ _glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
+ _glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
+ _glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
+ _glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
+ _glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;
+}
+
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
@@ -202,6 +330,8 @@ int _glfwPlatformInit(void)
if (!initLibraries())
return GL_FALSE;
+ createKeyTables();
+
if (_glfw_SetProcessDPIAware)
_glfw_SetProcessDPIAware();
diff --git a/glfw/src/win32_monitor.c b/glfw/src/win32_monitor.c
index ee44d5d..0690dc1 100644
--- a/glfw/src/win32_monitor.c
+++ b/glfw/src/win32_monitor.c
@@ -161,9 +161,15 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count)
wcscpy(monitors[found]->win32.displayName, display.DeviceName);
WideCharToMultiByte(CP_UTF8, 0,
+ adapter.DeviceName, -1,
+ monitors[found]->win32.publicAdapterName,
+ sizeof(monitors[found]->win32.publicAdapterName),
+ NULL, NULL);
+
+ WideCharToMultiByte(CP_UTF8, 0,
display.DeviceName, -1,
- monitors[found]->win32.nativeName,
- sizeof(monitors[found]->win32.nativeName),
+ monitors[found]->win32.publicDisplayName,
+ sizeof(monitors[found]->win32.publicDisplayName),
NULL, NULL);
if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&
@@ -326,10 +332,17 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->win32.publicAdapterName;
+}
+
GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
- return monitor->win32.nativeName;
+ return monitor->win32.publicDisplayName;
}
diff --git a/glfw/src/win32_platform.h b/glfw/src/win32_platform.h
index 465e487..564c861 100644
--- a/glfw/src/win32_platform.h
+++ b/glfw/src/win32_platform.h
@@ -172,6 +172,7 @@ typedef struct _GLFWlibraryWin32
{
DWORD foregroundLockTimeout;
char* clipboardString;
+ short int publicKeys[512];
// winmm.dll
struct {
@@ -205,7 +206,8 @@ typedef struct _GLFWmonitorWin32
// This size matches the static size of DISPLAY_DEVICE.DeviceName
WCHAR adapterName[32];
WCHAR displayName[32];
- char nativeName[64];
+ char publicAdapterName[64];
+ char publicDisplayName[64];
GLboolean modeChanged;
} _GLFWmonitorWin32;
diff --git a/glfw/src/win32_window.c b/glfw/src/win32_window.c
index f7c531d..c81f91d 100644
--- a/glfw/src/win32_window.c
+++ b/glfw/src/win32_window.c
@@ -112,6 +112,29 @@ static void restoreCursor(_GLFWwindow* window)
}
}
+// Translates a GLFW standard cursor to a resource ID
+//
+static LPWSTR translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return IDC_ARROW;
+ case GLFW_IBEAM_CURSOR:
+ return IDC_IBEAM;
+ case GLFW_CROSSHAIR_CURSOR:
+ return IDC_CROSS;
+ case GLFW_HAND_CURSOR:
+ return IDC_HAND;
+ case GLFW_HRESIZE_CURSOR:
+ return IDC_SIZEWE;
+ case GLFW_VRESIZE_CURSOR:
+ return IDC_SIZENS;
+ }
+
+ return NULL;
+}
+
// Retrieves and translates modifier keys
//
static int getKeyMods(void)
@@ -152,242 +175,44 @@ static int getAsyncKeyMods(void)
//
static int translateKey(WPARAM wParam, LPARAM lParam)
{
- // Check for numeric keypad keys
- // NOTE: This way we always force "NumLock = ON", which is intentional since
- // the returned key code should correspond to a physical location.
- if ((HIWORD(lParam) & 0x100) == 0)
- {
- switch (MapVirtualKey(HIWORD(lParam) & 0xFF, 1))
- {
- case VK_INSERT: return GLFW_KEY_KP_0;
- case VK_END: return GLFW_KEY_KP_1;
- case VK_DOWN: return GLFW_KEY_KP_2;
- case VK_NEXT: return GLFW_KEY_KP_3;
- case VK_LEFT: return GLFW_KEY_KP_4;
- case VK_CLEAR: return GLFW_KEY_KP_5;
- case VK_RIGHT: return GLFW_KEY_KP_6;
- case VK_HOME: return GLFW_KEY_KP_7;
- case VK_UP: return GLFW_KEY_KP_8;
- case VK_PRIOR: return GLFW_KEY_KP_9;
- case VK_DIVIDE: return GLFW_KEY_KP_DIVIDE;
- case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY;
- case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT;
- case VK_ADD: return GLFW_KEY_KP_ADD;
- case VK_DELETE: return GLFW_KEY_KP_DECIMAL;
- default: break;
- }
- }
-
- switch (HIWORD(lParam) & 0xFF)
+ if (wParam == VK_CONTROL)
{
- // handle printable chars except space in a language independent way,
- // using scancodes rather than virtual keys
- // as virtual keys are language dependent.
- // Printable keys are mapped according to US layout.
-
- // Row 0:
- case 0x29: return GLFW_KEY_GRAVE_ACCENT;
- case 0x02: return GLFW_KEY_1;
- case 0x03: return GLFW_KEY_2;
- case 0x04: return GLFW_KEY_3;
- case 0x05: return GLFW_KEY_4;
- case 0x06: return GLFW_KEY_5;
- case 0x07: return GLFW_KEY_6;
- case 0x08: return GLFW_KEY_7;
- case 0x09: return GLFW_KEY_8;
- case 0x0A: return GLFW_KEY_9;
- case 0x0B: return GLFW_KEY_0;
- case 0x0C: return GLFW_KEY_MINUS;
- case 0x0D: return GLFW_KEY_EQUAL;
-
- // Row 1:
- case 0x10: return GLFW_KEY_Q;
- case 0x11: return GLFW_KEY_W;
- case 0x12: return GLFW_KEY_E;
- case 0x13: return GLFW_KEY_R;
- case 0x14: return GLFW_KEY_T;
- case 0x15: return GLFW_KEY_Y;
- case 0x16: return GLFW_KEY_U;
- case 0x17: return GLFW_KEY_I;
- case 0x18: return GLFW_KEY_O;
- case 0x19: return GLFW_KEY_P;
- case 0x1A: return GLFW_KEY_LEFT_BRACKET;
- case 0x1B: return GLFW_KEY_RIGHT_BRACKET;
- // We do not map 0x2B as this is only on US - use vKeys for this to prevent confusion with 0x56
-
- // Row 2:
- case 0x1E: return GLFW_KEY_A;
- case 0x1F: return GLFW_KEY_S;
- case 0x20: return GLFW_KEY_D;
- case 0x21: return GLFW_KEY_F;
- case 0x22: return GLFW_KEY_G;
- case 0x23: return GLFW_KEY_H;
- case 0x24: return GLFW_KEY_J;
- case 0x25: return GLFW_KEY_K;
- case 0x26: return GLFW_KEY_L;
- case 0x27: return GLFW_KEY_SEMICOLON;
- case 0x28: return GLFW_KEY_APOSTROPHE;
-
- // Row 3:
- case 0x2C: return GLFW_KEY_Z;
- case 0x2D: return GLFW_KEY_X;
- case 0x2E: return GLFW_KEY_C;
- case 0x2F: return GLFW_KEY_V;
- case 0x30: return GLFW_KEY_B;
- case 0x31: return GLFW_KEY_N;
- case 0x32: return GLFW_KEY_M;
- case 0x33: return GLFW_KEY_COMMA;
- case 0x34: return GLFW_KEY_PERIOD;
- case 0x35: return GLFW_KEY_SLASH;
- default: break;
- }
-
- // Check which key was pressed or released
- switch (wParam)
- {
- // The SHIFT keys require special handling
- case VK_SHIFT:
- {
- // Compare scan code for this key with that of VK_RSHIFT in
- // order to determine which shift key was pressed (left or
- // right)
- const DWORD scancode = MapVirtualKey(VK_RSHIFT, 0);
- if ((DWORD) ((lParam & 0x01ff0000) >> 16) == scancode)
- return GLFW_KEY_RIGHT_SHIFT;
-
- return GLFW_KEY_LEFT_SHIFT;
- }
-
// The CTRL keys require special handling
- case VK_CONTROL:
- {
- MSG next;
- DWORD time;
- // Is this an extended key (i.e. right key)?
- if (lParam & 0x01000000)
- return GLFW_KEY_RIGHT_CONTROL;
+ MSG next;
+ DWORD time;
+
+ // Is this an extended key (i.e. right key)?
+ if (lParam & 0x01000000)
+ return GLFW_KEY_RIGHT_CONTROL;
- // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
- // want the RALT message, so we try to see if the next message
- // is a RALT message. In that case, this is a false LCTRL!
- time = GetMessageTime();
+ // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
+ // want the RALT message, so we try to see if the next message
+ // is a RALT message. In that case, this is a false LCTRL!
+ time = GetMessageTime();
- if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
+ if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
+ {
+ if (next.message == WM_KEYDOWN ||
+ next.message == WM_SYSKEYDOWN ||
+ next.message == WM_KEYUP ||
+ next.message == WM_SYSKEYUP)
{
- if (next.message == WM_KEYDOWN ||
- next.message == WM_SYSKEYDOWN ||
- next.message == WM_KEYUP ||
- next.message == WM_SYSKEYUP)
+ if (next.wParam == VK_MENU &&
+ (next.lParam & 0x01000000) &&
+ next.time == time)
{
- if (next.wParam == VK_MENU &&
- (next.lParam & 0x01000000) &&
- next.time == time)
- {
- // Next message is a RALT down message, which
- // means that this is not a proper LCTRL message
- return _GLFW_KEY_INVALID;
- }
+ // Next message is a RALT down message, which
+ // means that this is not a proper LCTRL message
+ return _GLFW_KEY_INVALID;
}
}
-
- return GLFW_KEY_LEFT_CONTROL;
- }
-
- // The ALT keys require special handling
- case VK_MENU:
- {
- // Is this an extended key (i.e. right key)?
- if (lParam & 0x01000000)
- return GLFW_KEY_RIGHT_ALT;
-
- return GLFW_KEY_LEFT_ALT;
- }
-
- // The ENTER keys require special handling
- case VK_RETURN:
- {
- // Is this an extended key (i.e. right key)?
- if (lParam & 0x01000000)
- return GLFW_KEY_KP_ENTER;
-
- return GLFW_KEY_ENTER;
}
- // Funcion keys (non-printable keys)
- case VK_ESCAPE: return GLFW_KEY_ESCAPE;
- case VK_TAB: return GLFW_KEY_TAB;
- case VK_BACK: return GLFW_KEY_BACKSPACE;
- case VK_HOME: return GLFW_KEY_HOME;
- case VK_END: return GLFW_KEY_END;
- case VK_PRIOR: return GLFW_KEY_PAGE_UP;
- case VK_NEXT: return GLFW_KEY_PAGE_DOWN;
- case VK_INSERT: return GLFW_KEY_INSERT;
- case VK_DELETE: return GLFW_KEY_DELETE;
- case VK_LEFT: return GLFW_KEY_LEFT;
- case VK_UP: return GLFW_KEY_UP;
- case VK_RIGHT: return GLFW_KEY_RIGHT;
- case VK_DOWN: return GLFW_KEY_DOWN;
- case VK_F1: return GLFW_KEY_F1;
- case VK_F2: return GLFW_KEY_F2;
- case VK_F3: return GLFW_KEY_F3;
- case VK_F4: return GLFW_KEY_F4;
- case VK_F5: return GLFW_KEY_F5;
- case VK_F6: return GLFW_KEY_F6;
- case VK_F7: return GLFW_KEY_F7;
- case VK_F8: return GLFW_KEY_F8;
- case VK_F9: return GLFW_KEY_F9;
- case VK_F10: return GLFW_KEY_F10;
- case VK_F11: return GLFW_KEY_F11;
- case VK_F12: return GLFW_KEY_F12;
- case VK_F13: return GLFW_KEY_F13;
- case VK_F14: return GLFW_KEY_F14;
- case VK_F15: return GLFW_KEY_F15;
- case VK_F16: return GLFW_KEY_F16;
- case VK_F17: return GLFW_KEY_F17;
- case VK_F18: return GLFW_KEY_F18;
- case VK_F19: return GLFW_KEY_F19;
- case VK_F20: return GLFW_KEY_F20;
- case VK_F21: return GLFW_KEY_F21;
- case VK_F22: return GLFW_KEY_F22;
- case VK_F23: return GLFW_KEY_F23;
- case VK_F24: return GLFW_KEY_F24;
- case VK_NUMLOCK: return GLFW_KEY_NUM_LOCK;
- case VK_CAPITAL: return GLFW_KEY_CAPS_LOCK;
- case VK_SNAPSHOT: return GLFW_KEY_PRINT_SCREEN;
- case VK_SCROLL: return GLFW_KEY_SCROLL_LOCK;
- case VK_PAUSE: return GLFW_KEY_PAUSE;
- case VK_LWIN: return GLFW_KEY_LEFT_SUPER;
- case VK_RWIN: return GLFW_KEY_RIGHT_SUPER;
- case VK_APPS: return GLFW_KEY_MENU;
-
- // Numeric keypad
- case VK_NUMPAD0: return GLFW_KEY_KP_0;
- case VK_NUMPAD1: return GLFW_KEY_KP_1;
- case VK_NUMPAD2: return GLFW_KEY_KP_2;
- case VK_NUMPAD3: return GLFW_KEY_KP_3;
- case VK_NUMPAD4: return GLFW_KEY_KP_4;
- case VK_NUMPAD5: return GLFW_KEY_KP_5;
- case VK_NUMPAD6: return GLFW_KEY_KP_6;
- case VK_NUMPAD7: return GLFW_KEY_KP_7;
- case VK_NUMPAD8: return GLFW_KEY_KP_8;
- case VK_NUMPAD9: return GLFW_KEY_KP_9;
- case VK_DIVIDE: return GLFW_KEY_KP_DIVIDE;
- case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY;
- case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT;
- case VK_ADD: return GLFW_KEY_KP_ADD;
- case VK_DECIMAL: return GLFW_KEY_KP_DECIMAL;
-
- // Printable keys are mapped according to US layout
- case VK_SPACE: return GLFW_KEY_SPACE;
- case 0xDC: return GLFW_KEY_BACKSLASH;
- case 0xDF: return GLFW_KEY_WORLD_1;
- case 0xE2: return GLFW_KEY_WORLD_2;
- default: break;
+ return GLFW_KEY_LEFT_CONTROL;
}
- // No matching translation was found
- return GLFW_KEY_UNKNOWN;
+ return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
}
// Enter fullscreen mode
@@ -1221,6 +1046,8 @@ void _glfwPlatformPollEvents(void)
if (msg.message == WM_QUIT)
{
// Treat WM_QUIT as a close on all windows
+ // While GLFW does not itself post WM_QUIT, other processes may post
+ // it to this one, for example Task Manager
window = _glfw.windowListHead;
while (window)
@@ -1374,6 +1201,26 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
return GL_TRUE;
}
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ LPCWSTR native = translateCursorShape(shape);
+ if (!native)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Win32: Invalid standard cursor");
+ return GL_FALSE;
+ }
+
+ cursor->win32.handle = CopyCursor(LoadCursorW(NULL, native));
+ if (!cursor->win32.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to retrieve shared cursor");
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->win32.handle)
diff --git a/glfw/src/wl_init.c b/glfw/src/wl_init.c
index 9105df7..0269ee3 100644
--- a/glfw/src/wl_init.c
+++ b/glfw/src/wl_init.c
@@ -600,6 +600,7 @@ int _glfwPlatformInit(void)
void _glfwPlatformTerminate(void)
{
_glfwTerminateContextAPI();
+ _glfwTerminateJoysticks();
if (_glfw.wl.cursorTheme)
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
diff --git a/glfw/src/wl_platform.h b/glfw/src/wl_platform.h
index a498e38..66736b5 100644
--- a/glfw/src/wl_platform.h
+++ b/glfw/src/wl_platform.h
@@ -64,7 +64,6 @@ typedef struct _GLFWwindowWayland
struct wl_surface* surface;
struct wl_egl_window* native;
struct wl_shell_surface* shell_surface;
- EGLSurface egl_surface;
struct wl_callback* callback;
_GLFWcursor* currentCursor;
} _GLFWwindowWayland;
diff --git a/glfw/src/wl_window.c b/glfw/src/wl_window.c
index 9ace38f..ce71dbd 100644
--- a/glfw/src/wl_window.c
+++ b/glfw/src/wl_window.c
@@ -422,6 +422,13 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
return GL_TRUE;
}
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ // TODO
+ fprintf(stderr, "_glfwPlatformCreateStandardCursor not implemented yet\n");
+ return GL_FALSE;
+}
+
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
wl_buffer_destroy(cursor->wl.buffer);
diff --git a/glfw/src/x11_init.c b/glfw/src/x11_init.c
index ea0b693..e2063a1 100644
--- a/glfw/src/x11_init.c
+++ b/glfw/src/x11_init.c
@@ -33,16 +33,17 @@
#include <string.h>
#include <limits.h>
#include <stdio.h>
+#include <locale.h>
// Translate an X11 key code to a GLFW key code.
//
-static int translateKey(int keyCode)
+static int translateKey(int scancode)
{
int keySym;
// Valid key code range is [8,255], according to the XLib manual
- if (keyCode < 8 || keyCode > 255)
+ if (scancode < 8 || scancode > 255)
return GLFW_KEY_UNKNOWN;
if (_glfw.x11.xkb.available)
@@ -51,7 +52,7 @@ static int translateKey(int keyCode)
// Note: This way we always force "NumLock = ON", which is intentional
// since the returned key code should correspond to a physical
// location.
- keySym = XkbKeycodeToKeysym(_glfw.x11.display, keyCode, 0, 1);
+ keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 1);
switch (keySym)
{
case XK_KP_0: return GLFW_KEY_KP_0;
@@ -74,14 +75,14 @@ static int translateKey(int keyCode)
// Now try pimary keysym for function keys (non-printable keys). These
// should not be layout dependent (i.e. US layout and international
// layouts should give the same result).
- keySym = XkbKeycodeToKeysym(_glfw.x11.display, keyCode, 0, 0);
+ keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0);
}
else
{
int dummy;
KeySym* keySyms;
- keySyms = XGetKeyboardMapping(_glfw.x11.display, keyCode, 1, &dummy);
+ keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
keySym = keySyms[0];
XFree(keySyms);
}
@@ -226,106 +227,97 @@ static int translateKey(int keyCode)
return GLFW_KEY_UNKNOWN;
}
-// Update the key code LUT
+// Create key code translation tables
//
-static void updateKeyCodeLUT(void)
+static void createKeyTables(void)
{
- int i, keyCode, keyCodeGLFW;
- char name[XkbKeyNameLength + 1];
- XkbDescPtr descr;
+ int scancode, key;
- // Clear the LUT
- for (keyCode = 0; keyCode < 256; keyCode++)
- _glfw.x11.keyCodeLUT[keyCode] = GLFW_KEY_UNKNOWN;
+ memset(_glfw.x11.publicKeys, -1, sizeof(_glfw.x11.publicKeys));
if (_glfw.x11.xkb.available)
{
// Use XKB to determine physical key locations independently of the current
// keyboard layout
- // Get keyboard description
- descr = XkbGetKeyboard(_glfw.x11.display,
- XkbAllComponentsMask,
- XkbUseCoreKbd);
+ char name[XkbKeyNameLength + 1];
+ XkbDescPtr descr = XkbGetKeyboard(_glfw.x11.display,
+ XkbAllComponentsMask,
+ XkbUseCoreKbd);
// Find the X11 key code -> GLFW key code mapping
- for (keyCode = descr->min_key_code; keyCode <= descr->max_key_code; ++keyCode)
+ for (scancode = descr->min_key_code; scancode <= descr->max_key_code; scancode++)
{
- // Get the key name
- for (i = 0; i < XkbKeyNameLength; i++)
- name[i] = descr->names->keys[keyCode].name[i];
-
+ memcpy(name, descr->names->keys[scancode].name, XkbKeyNameLength);
name[XkbKeyNameLength] = 0;
// Map the key name to a GLFW key code. Note: We only map printable
// keys here, and we use the US keyboard layout. The rest of the
// keys (function keys) are mapped using traditional KeySym
// translations.
- if (strcmp(name, "TLDE") == 0) keyCodeGLFW = GLFW_KEY_GRAVE_ACCENT;
- else if (strcmp(name, "AE01") == 0) keyCodeGLFW = GLFW_KEY_1;
- else if (strcmp(name, "AE02") == 0) keyCodeGLFW = GLFW_KEY_2;
- else if (strcmp(name, "AE03") == 0) keyCodeGLFW = GLFW_KEY_3;
- else if (strcmp(name, "AE04") == 0) keyCodeGLFW = GLFW_KEY_4;
- else if (strcmp(name, "AE05") == 0) keyCodeGLFW = GLFW_KEY_5;
- else if (strcmp(name, "AE06") == 0) keyCodeGLFW = GLFW_KEY_6;
- else if (strcmp(name, "AE07") == 0) keyCodeGLFW = GLFW_KEY_7;
- else if (strcmp(name, "AE08") == 0) keyCodeGLFW = GLFW_KEY_8;
- else if (strcmp(name, "AE09") == 0) keyCodeGLFW = GLFW_KEY_9;
- else if (strcmp(name, "AE10") == 0) keyCodeGLFW = GLFW_KEY_0;
- else if (strcmp(name, "AE11") == 0) keyCodeGLFW = GLFW_KEY_MINUS;
- else if (strcmp(name, "AE12") == 0) keyCodeGLFW = GLFW_KEY_EQUAL;
- else if (strcmp(name, "AD01") == 0) keyCodeGLFW = GLFW_KEY_Q;
- else if (strcmp(name, "AD02") == 0) keyCodeGLFW = GLFW_KEY_W;
- else if (strcmp(name, "AD03") == 0) keyCodeGLFW = GLFW_KEY_E;
- else if (strcmp(name, "AD04") == 0) keyCodeGLFW = GLFW_KEY_R;
- else if (strcmp(name, "AD05") == 0) keyCodeGLFW = GLFW_KEY_T;
- else if (strcmp(name, "AD06") == 0) keyCodeGLFW = GLFW_KEY_Y;
- else if (strcmp(name, "AD07") == 0) keyCodeGLFW = GLFW_KEY_U;
- else if (strcmp(name, "AD08") == 0) keyCodeGLFW = GLFW_KEY_I;
- else if (strcmp(name, "AD09") == 0) keyCodeGLFW = GLFW_KEY_O;
- else if (strcmp(name, "AD10") == 0) keyCodeGLFW = GLFW_KEY_P;
- else if (strcmp(name, "AD11") == 0) keyCodeGLFW = GLFW_KEY_LEFT_BRACKET;
- else if (strcmp(name, "AD12") == 0) keyCodeGLFW = GLFW_KEY_RIGHT_BRACKET;
- else if (strcmp(name, "AC01") == 0) keyCodeGLFW = GLFW_KEY_A;
- else if (strcmp(name, "AC02") == 0) keyCodeGLFW = GLFW_KEY_S;
- else if (strcmp(name, "AC03") == 0) keyCodeGLFW = GLFW_KEY_D;
- else if (strcmp(name, "AC04") == 0) keyCodeGLFW = GLFW_KEY_F;
- else if (strcmp(name, "AC05") == 0) keyCodeGLFW = GLFW_KEY_G;
- else if (strcmp(name, "AC06") == 0) keyCodeGLFW = GLFW_KEY_H;
- else if (strcmp(name, "AC07") == 0) keyCodeGLFW = GLFW_KEY_J;
- else if (strcmp(name, "AC08") == 0) keyCodeGLFW = GLFW_KEY_K;
- else if (strcmp(name, "AC09") == 0) keyCodeGLFW = GLFW_KEY_L;
- else if (strcmp(name, "AC10") == 0) keyCodeGLFW = GLFW_KEY_SEMICOLON;
- else if (strcmp(name, "AC11") == 0) keyCodeGLFW = GLFW_KEY_APOSTROPHE;
- else if (strcmp(name, "AB01") == 0) keyCodeGLFW = GLFW_KEY_Z;
- else if (strcmp(name, "AB02") == 0) keyCodeGLFW = GLFW_KEY_X;
- else if (strcmp(name, "AB03") == 0) keyCodeGLFW = GLFW_KEY_C;
- else if (strcmp(name, "AB04") == 0) keyCodeGLFW = GLFW_KEY_V;
- else if (strcmp(name, "AB05") == 0) keyCodeGLFW = GLFW_KEY_B;
- else if (strcmp(name, "AB06") == 0) keyCodeGLFW = GLFW_KEY_N;
- else if (strcmp(name, "AB07") == 0) keyCodeGLFW = GLFW_KEY_M;
- else if (strcmp(name, "AB08") == 0) keyCodeGLFW = GLFW_KEY_COMMA;
- else if (strcmp(name, "AB09") == 0) keyCodeGLFW = GLFW_KEY_PERIOD;
- else if (strcmp(name, "AB10") == 0) keyCodeGLFW = GLFW_KEY_SLASH;
- else if (strcmp(name, "BKSL") == 0) keyCodeGLFW = GLFW_KEY_BACKSLASH;
- else if (strcmp(name, "LSGT") == 0) keyCodeGLFW = GLFW_KEY_WORLD_1;
- else keyCodeGLFW = GLFW_KEY_UNKNOWN;
-
- // Update the key code LUT
- if ((keyCode >= 0) && (keyCode < 256))
- _glfw.x11.keyCodeLUT[keyCode] = keyCodeGLFW;
+ if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
+ else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
+ else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
+ else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
+ else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
+ else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
+ else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
+ else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
+ else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
+ else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
+ else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
+ else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
+ else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
+ else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
+ else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
+ else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
+ else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
+ else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
+ else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
+ else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
+ else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
+ else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
+ else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
+ else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
+ else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
+ else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
+ else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
+ else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
+ else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
+ else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
+ else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
+ else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
+ else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
+ else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
+ else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
+ else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
+ else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
+ else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
+ else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
+ else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
+ else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
+ else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
+ else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
+ else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
+ else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
+ else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
+ else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
+ else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
+ else key = GLFW_KEY_UNKNOWN;
+
+ if ((scancode >= 0) && (scancode < 256))
+ _glfw.x11.publicKeys[scancode] = key;
}
- // Free the keyboard description
XkbFreeKeyboard(descr, 0, True);
}
// Translate the un-translated key codes using traditional X11 KeySym
// lookups
- for (keyCode = 0; keyCode < 256; keyCode++)
+ for (scancode = 0; scancode < 256; scancode++)
{
- if (_glfw.x11.keyCodeLUT[keyCode] < 0)
- _glfw.x11.keyCodeLUT[keyCode] = translateKey(keyCode);
+ if (_glfw.x11.publicKeys[scancode] < 0)
+ _glfw.x11.publicKeys[scancode] = translateKey(scancode);
}
}
@@ -585,7 +577,7 @@ static GLboolean initExtensions(void)
// Update the key code LUT
// FIXME: We should listen to XkbMapNotify events to track changes to
// the keyboard mapping.
- updateKeyCodeLUT();
+ createKeyTables();
// Detect whether an EWMH-conformant window manager is running
detectEWMH();
@@ -718,6 +710,9 @@ Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
int _glfwPlatformInit(void)
{
+ if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
+ setlocale(LC_CTYPE, "");
+
XInitThreads();
_glfw.x11.display = XOpenDisplay(NULL);
@@ -754,8 +749,10 @@ int _glfwPlatformInit(void)
if (!_glfwInitContextAPI())
return GL_FALSE;
+ if (!_glfwInitJoysticks())
+ return GL_FALSE;
+
_glfwInitTimer();
- _glfwInitJoysticks();
return GL_TRUE;
}
diff --git a/glfw/src/x11_monitor.c b/glfw/src/x11_monitor.c
index 36d914d..fb6b0ef 100644
--- a/glfw/src/x11_monitor.c
+++ b/glfw/src/x11_monitor.c
@@ -465,6 +465,13 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(None);
+ return monitor->x11.crtc;
+}
+
GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
{
_GLFWmonitor* monitor = (_GLFWmonitor*) handle;
diff --git a/glfw/src/x11_platform.h b/glfw/src/x11_platform.h
index a69705b..17503b7 100644
--- a/glfw/src/x11_platform.h
+++ b/glfw/src/x11_platform.h
@@ -31,6 +31,8 @@
#include <unistd.h>
#include <signal.h>
#include <stdint.h>
+#include <regex.h>
+
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
@@ -115,11 +117,10 @@ typedef struct _GLFWlibraryX11
GLboolean hasEWMH;
// Most recent error code received by X error handler
int errorCode;
-
+ // Clipboard string (while the selection is owned)
char* clipboardString;
-
- // LUT for mapping X11 key codes to GLFW key codes
- int keyCodeLUT[256];
+ // X11 keycode to GLFW key LUT
+ short int publicKeys[256];
// Window manager atoms
Atom WM_PROTOCOLS;
@@ -215,6 +216,14 @@ typedef struct _GLFWlibraryX11
int versionMinor;
} xinerama;
+#if defined(__linux__)
+ struct {
+ int fd;
+ int wd;
+ regex_t regex;
+ } inotify;
+#endif
+
} _GLFWlibraryX11;
diff --git a/glfw/src/x11_window.c b/glfw/src/x11_window.c
index 8fa6c97..8373487 100644
--- a/glfw/src/x11_window.c
+++ b/glfw/src/x11_window.c
@@ -27,6 +27,8 @@
#include "internal.h"
+#include <X11/cursorfont.h>
+
#include <sys/select.h>
#include <string.h>
@@ -66,6 +68,29 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;
}
+// Translates a GLFW standard cursor to a font cursor shape
+//
+static int translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return XC_arrow;
+ case GLFW_IBEAM_CURSOR:
+ return XC_xterm;
+ case GLFW_CROSSHAIR_CURSOR:
+ return XC_crosshair;
+ case GLFW_HAND_CURSOR:
+ return XC_hand1;
+ case GLFW_HRESIZE_CURSOR:
+ return XC_sb_h_double_arrow;
+ case GLFW_VRESIZE_CURSOR:
+ return XC_sb_v_double_arrow;
+ }
+
+ return 0;
+}
+
// Translates an X event modifier state mask
//
static int translateState(int state)
@@ -86,13 +111,13 @@ static int translateState(int state)
// Translates an X Window key to internal coding
//
-static int translateKey(int keycode)
+static int translateKey(int scancode)
{
- // Use the pre-filled LUT (see updateKeyCodeLUT() in x11_init.c)
- if (keycode < 0 || keycode > 255)
+ // Use the pre-filled LUT (see createKeyTables() in x11_init.c)
+ if (scancode < 0 || scancode > 255)
return GLFW_KEY_UNKNOWN;
- return _glfw.x11.keyCodeLUT[keycode];
+ return _glfw.x11.publicKeys[scancode];
}
// Return the GLFW window corresponding to the specified X11 window
@@ -777,14 +802,16 @@ static void enterFullscreenMode(_GLFWwindow* window)
{
// In override-redirect mode we have divorced ourselves from the
// window manager, so we need to do everything manually
-
+ int xpos, ypos;
GLFWvidmode mode;
+
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
_glfwPlatformGetVideoMode(window->monitor, &mode);
XRaiseWindow(_glfw.x11.display, window->x11.handle);
XSetInputFocus(_glfw.x11.display, window->x11.handle,
RevertToParent, CurrentTime);
- XMoveWindow(_glfw.x11.display, window->x11.handle, 0, 0);
+ XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);
XResizeWindow(_glfw.x11.display, window->x11.handle,
mode.width, mode.height);
}
@@ -1729,12 +1756,32 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
int xhot, int yhot)
{
cursor->x11.handle = _glfwCreateCursor(image, xhot, yhot);
- if (cursor->x11.handle == None)
+ if (!cursor->x11.handle)
return GL_FALSE;
return GL_TRUE;
}
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ const unsigned int native = translateCursorShape(shape);
+ if (!native)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "X11: Invalid standard cursor");
+ return GL_FALSE;
+ }
+
+ cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
+ if (!cursor->x11.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create standard cursor");
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
{
if (cursor->x11.handle)