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)
This commit is contained in:
Xo Wang 2015-07-26 18:40:54 -07:00
parent 460e5d792d
commit 8b5f92134a

View File

@ -168,6 +168,29 @@ static int translateKey(unsigned int key)
return _glfw.ns.publicKeys[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 // Delegate for window related notifications
@ -528,17 +551,26 @@ static int translateKey(unsigned int key)
[event modifierFlags] & NSDeviceIndependentModifierFlagsMask; [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
const int key = translateKey([event keyCode]); const int key = translateKey([event keyCode]);
const int mods = translateFlags(modifierFlags); 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) if (window->keys[key] == GLFW_PRESS)
action = GLFW_RELEASE; action = GLFW_RELEASE;
else else
action = GLFW_PRESS; 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; action = GLFW_PRESS;
else else
// Modifier key was released or the flag change was not for this key
action = GLFW_RELEASE; action = GLFW_RELEASE;
window->ns.modifierFlags = modifierFlags; window->ns.modifierFlags = modifierFlags;
@ -899,6 +931,12 @@ static GLboolean createWindow(_GLFWwindow* window,
window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow: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 defined(_GLFW_USE_RETINA)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)