Commit 257b7af247b9dbda1c69a1dbb88f4438b8631ee7

Ryan C. Gordon 2015-12-28T13:07:44

Sync up the caps/numlock state properly without sending key events. Partially fixes Bugzilla #2736 and #3125.

diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c
index d4dc0e7..97b90f7 100644
--- a/src/events/SDL_keyboard.c
+++ b/src/events/SDL_keyboard.c
@@ -845,6 +845,19 @@ SDL_SetModState(SDL_Keymod modstate)
     keyboard->modstate = modstate;
 }
 
+/* Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. */
+void
+SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
+{
+    SDL_Keyboard *keyboard = &SDL_keyboard;
+    if (toggle) {
+        keyboard->modstate |= modstate;
+    } else {
+        keyboard->modstate &= ~modstate;
+    }
+}
+
+
 SDL_Keycode
 SDL_GetKeyFromScancode(SDL_Scancode scancode)
 {
diff --git a/src/events/SDL_keyboard_c.h b/src/events/SDL_keyboard_c.h
index 50fb06d..2e51052 100644
--- a/src/events/SDL_keyboard_c.h
+++ b/src/events/SDL_keyboard_c.h
@@ -62,6 +62,9 @@ extern void SDL_KeyboardQuit(void);
 /* Convert to UTF-8 */
 extern char *SDL_UCS4ToUTF8(Uint32 ch, char *dst);
 
+/* Toggle on or off pieces of the keyboard mod state. */
+extern void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle);
+
 #endif /* _SDL_keyboard_c_h */
 
 /* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m
index f27709e..95598e7 100644
--- a/src/video/cocoa/SDL_cocoakeyboard.m
+++ b/src/video/cocoa/SDL_cocoakeyboard.m
@@ -341,8 +341,7 @@ HandleCapsLock(unsigned short scancode,
     newMask = newMods & NSAlphaShiftKeyMask;
 
     if (oldMask != newMask) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
+        SDL_ToggleModState(KMOD_CAPS, newMask != 0);
     }
 }
 
@@ -501,10 +500,7 @@ Cocoa_InitKeyboard(_THIS)
     /* On pre-10.6, you might have the initial capslock key state wrong. */
     if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_6) {
         data->modifierFlags = [NSEvent modifierFlags];
-        if (data->modifierFlags & NSAlphaShiftKeyMask) {
-            SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-            SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
-        }
+        SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSAlphaShiftKeyMask) != 0);
     }
 }
 
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 3ed4078..009d15a 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -589,15 +589,11 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
         [NSMenu setMenuBarVisible:NO];
     }
 
-    /* On pre-10.6, you might have the capslock key state wrong now. */
+    /* On pre-10.6, you might have the capslock key state wrong now because we can't check here. */
     if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_6) {
-        const unsigned int oldflags = _data->videodata->modifierFlags & NSAlphaShiftKeyMask;
         const unsigned int newflags = [NSEvent modifierFlags] & NSAlphaShiftKeyMask;
-        if (oldflags != newflags) {
-            _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSAlphaShiftKeyMask) | newflags;
-            SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-            SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
-        }
+        _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSAlphaShiftKeyMask) | newflags;
+        SDL_ToggleModState(KMOD_CAPS, newflags != 0);
     }
 }
 
diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c
index c98cb3e..1db8bbc 100644
--- a/src/video/windows/SDL_windowskeyboard.c
+++ b/src/video/windows/SDL_windowskeyboard.c
@@ -104,18 +104,8 @@ WIN_InitKeyboard(_THIS)
     SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Windows");
 
     /* Are system caps/num/scroll lock active? Set our state to match. */
-    if (GetKeyState(VK_CAPITAL) & 0x0001) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
-    }
-    if (GetKeyState(VK_NUMLOCK) & 0x0001) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
-    }
-    if (GetKeyState(VK_SCROLL) & 0x0001) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_SCROLLLOCK);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_SCROLLLOCK);
-    }
+    SDL_ToggleModState(KMOD_CAPS, (GetKeyState(VK_CAPITAL) & 0x0001) != 0);
+    SDL_ToggleModState(KMOD_NUM, (GetKeyState(VK_NUMLOCK) & 0x0001) != 0);
 }
 
 void
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 2f730c4..c8addca 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -348,27 +348,10 @@ X11_ReconcileKeyboardState(_THIS)
 
     X11_XQueryKeymap(display, keys);
 
-    /* Get the keyboard modifier state */
+    /* Sync up the keyboard modifier state */
     if (X11_XQueryPointer(display, DefaultRootWindow(display), &junk_window, &junk_window, &x, &y, &x, &y, &mask)) {
-        unsigned num_mask = X11_GetNumLockModifierMask(_this);
-        const Uint8 *keystate = SDL_GetKeyboardState(NULL);
-        Uint8 capslockState = keystate[SDL_SCANCODE_CAPSLOCK];
-        Uint8 numlockState = keystate[SDL_SCANCODE_NUMLOCKCLEAR];
-
-        /* Toggle key mod state if needed */
-        if (!!(mask & LockMask) != !!(SDL_GetModState() & KMOD_CAPS)) {
-            SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-            if (capslockState == SDL_RELEASED) {
-                SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
-            }
-        }
-
-        if (!!(mask & num_mask) != !!(SDL_GetModState() & KMOD_NUM)) {
-            SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
-            if (numlockState == SDL_RELEASED) {
-                SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
-            }
-        }
+        SDL_ToggleModState(KMOD_CAPS, (mask & LockMask) != 0);
+        SDL_ToggleModState(KMOD_NUM, (mask & X11_GetNumLockModifierMask(_this)) != 0);
     }
 
     for (keycode = 0; keycode < 256; ++keycode) {