From 8b5f92134a4f9109f95f38fd7fd31e228ef07a68 Mon Sep 17 00:00:00 2001 From: Xo Wang Date: Sun, 26 Jul 2015 18:40:54 -0700 Subject: [PATCH] Fix OS X spurious key pressed event when modifier key is held during window creation Fixes #566. - Initialize modifierFlags to user state when opening window - Match flagsChanged keycode to corresponding bit in modifierFlags to filter out unrelated events - Only toggle key state if modifier bits are already set (not just if they haven't changed) --- src/cocoa_window.m | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 69c37565d..91c8da945 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -168,6 +168,29 @@ static int translateKey(unsigned int key) return _glfw.ns.publicKeys[key]; } +// Translate a GLFW keycode to a mask for its GLFW modifier flag bit +// +static int translateKeyToFlagMask(int key) +{ + switch (key) + { + case GLFW_KEY_LEFT_SHIFT: + case GLFW_KEY_RIGHT_SHIFT: + return GLFW_MOD_SHIFT; + case GLFW_KEY_LEFT_CONTROL: + case GLFW_KEY_RIGHT_CONTROL: + return GLFW_MOD_CONTROL; + case GLFW_KEY_LEFT_ALT: + case GLFW_KEY_RIGHT_ALT: + return GLFW_MOD_ALT; + case GLFW_KEY_LEFT_SUPER: + case GLFW_KEY_RIGHT_SUPER: + return GLFW_MOD_SUPER; + default: + return 0; + } +} + //------------------------------------------------------------------------ // Delegate for window related notifications @@ -528,17 +551,26 @@ static int translateKey(unsigned int key) [event modifierFlags] & NSDeviceIndependentModifierFlagsMask; const int key = translateKey([event keyCode]); const int mods = translateFlags(modifierFlags); + // Process flag change as a key press only if the key and flag match + const int flagMask = translateKeyToFlagMask(key); + const int modsMasked = mods & flagMask; + const int prevModsMasked = + translateFlags(window->ns.modifierFlags) & flagMask; - if (modifierFlags == window->ns.modifierFlags) + if ((modsMasked & prevModsMasked) != 0) { + // Toggle key state if key is already held, to handle left and right + // modifier keys being held simultaneously if (window->keys[key] == GLFW_PRESS) action = GLFW_RELEASE; else action = GLFW_PRESS; } - else if (modifierFlags > window->ns.modifierFlags) + else if (modsMasked > prevModsMasked) + // The bit corresponding to the key is set in the new flags action = GLFW_PRESS; else + // Modifier key was released or the flag change was not for this key action = GLFW_RELEASE; window->ns.modifierFlags = modifierFlags; @@ -899,6 +931,12 @@ static GLboolean createWindow(_GLFWwindow* window, window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window]; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 + // Initialize modifiers state with any already held modifiers + window->ns.modifierFlags = + [NSEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; +#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ + #if defined(_GLFW_USE_RETINA) #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)