@@ -246,54 +246,133 @@ static void X11_HandleGenericEvent(SDL_VideoDevice *_this, XEvent *xev)
246
246
}
247
247
#endif // SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
248
248
249
- static unsigned X11_GetNumLockModifierMask ( SDL_VideoDevice * _this )
249
+ static void X11_ReconcileModifiers ( SDL_VideoData * viddata )
250
250
{
251
- SDL_VideoData * videodata = _this -> internal ;
252
- Display * display = videodata -> display ;
253
- unsigned num_mask = 0 ;
254
- int i , j ;
255
- XModifierKeymap * xmods ;
256
- unsigned n ;
257
-
258
- xmods = X11_XGetModifierMapping (display );
259
- n = xmods -> max_keypermod ;
260
- for (i = 3 ; i < 8 ; i ++ ) {
261
- for (j = 0 ; j < n ; j ++ ) {
262
- KeyCode kc = xmods -> modifiermap [i * n + j ];
263
- if (videodata -> key_layout [kc ] == SDL_SCANCODE_NUMLOCKCLEAR ) {
264
- num_mask = 1 << i ;
265
- break ;
266
- }
251
+ Window junk_window ;
252
+ int x , y ;
253
+ Uint32 xk_modifiers = 0 ;
254
+
255
+ X11_XQueryPointer (viddata -> display , DefaultRootWindow (viddata -> display ), & junk_window , & junk_window , & x , & y , & x , & y , & xk_modifiers );
256
+
257
+ /* If a modifier was activated by a keypress, it will be tied to the
258
+ * specific left/right key that initiated it. Otherwise, the ambiguous
259
+ * left/right combo is used.
260
+ */
261
+ if (xk_modifiers & ShiftMask ) {
262
+ if (!(viddata -> xkb .active_modifiers & SDL_KMOD_SHIFT )) {
263
+ viddata -> xkb .active_modifiers |= SDL_KMOD_SHIFT ;
264
+ }
265
+ } else {
266
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_SHIFT ;
267
+ }
268
+
269
+ if (xk_modifiers & ControlMask ) {
270
+ if (!(viddata -> xkb .active_modifiers & SDL_KMOD_CTRL )) {
271
+ viddata -> xkb .active_modifiers |= SDL_KMOD_CTRL ;
272
+ }
273
+ } else {
274
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_CTRL ;
275
+ }
276
+
277
+ // Mod1 is used for the Alt keys
278
+ if (xk_modifiers & Mod1Mask ) {
279
+ if (!(viddata -> xkb .active_modifiers & SDL_KMOD_ALT )) {
280
+ viddata -> xkb .active_modifiers |= SDL_KMOD_ALT ;
281
+ }
282
+ } else {
283
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_ALT ;
284
+ }
285
+
286
+ // Mod4 is used for the Super (aka GUI/Logo) keys.
287
+ if (xk_modifiers & Mod4Mask ) {
288
+ if (!(viddata -> xkb .active_modifiers & SDL_KMOD_GUI )) {
289
+ viddata -> xkb .active_modifiers |= SDL_KMOD_GUI ;
267
290
}
291
+ } else {
292
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_GUI ;
293
+ }
294
+
295
+ // Mod3 is typically Level 5 shift.
296
+ if (xk_modifiers & Mod3Mask ) {
297
+ viddata -> xkb .active_modifiers |= SDL_KMOD_LEVEL5 ;
298
+ } else {
299
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_LEVEL5 ;
300
+ }
301
+
302
+ // Mod5 is typically Level 3 shift (aka AltGr).
303
+ if (xk_modifiers & Mod5Mask ) {
304
+ viddata -> xkb .active_modifiers |= SDL_KMOD_MODE ;
305
+ } else {
306
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_MODE ;
307
+ }
308
+
309
+ if (xk_modifiers & viddata -> xkb .numlock_mask ) {
310
+ viddata -> xkb .active_modifiers |= SDL_KMOD_NUM ;
311
+ } else {
312
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_NUM ;
313
+ }
314
+
315
+ if (xk_modifiers & viddata -> xkb .scrolllock_mask ) {
316
+ viddata -> xkb .active_modifiers |= SDL_KMOD_SCROLL ;
317
+ } else {
318
+ viddata -> xkb .active_modifiers &= ~SDL_KMOD_SCROLL ;
268
319
}
269
- X11_XFreeModifiermap (xmods );
270
320
271
- return num_mask ;
321
+ SDL_SetModState ( viddata -> xkb . active_modifiers ) ;
272
322
}
273
323
274
- static unsigned X11_GetScrollLockModifierMask ( SDL_VideoDevice * _this )
324
+ static void X11_HandleModifierKeys ( SDL_VideoData * viddata , SDL_Scancode scancode , bool pressed , bool reconcile )
275
325
{
276
- SDL_VideoData * videodata = _this -> internal ;
277
- Display * display = videodata -> display ;
278
- unsigned num_mask = 0 ;
279
- int i , j ;
280
- XModifierKeymap * xmods ;
281
- unsigned n ;
282
-
283
- xmods = X11_XGetModifierMapping (display );
284
- n = xmods -> max_keypermod ;
285
- for (i = 3 ; i < 8 ; i ++ ) {
286
- for (j = 0 ; j < n ; j ++ ) {
287
- KeyCode kc = xmods -> modifiermap [i * n + j ];
288
- if (videodata -> key_layout [kc ] == SDL_SCANCODE_SCROLLLOCK ) {
289
- num_mask = 1 << i ;
290
- break ;
291
- }
292
- }
326
+ const SDL_Keycode keycode = SDL_GetKeyFromScancode (scancode , SDL_KMOD_NONE , false);
327
+ SDL_Keymod mod = SDL_KMOD_NONE ;
328
+
329
+ /* SDL clients expect modifier state to be activated at the same time as the
330
+ * source keypress, so we set pressed modifier state with the usual modifier
331
+ * keys here, as the explicit modifier event won't arrive until after the
332
+ * keypress event. If this is wrong, it will be corrected when the explicit
333
+ * modifier state is checked.
334
+ */
335
+ switch (keycode ) {
336
+ case SDLK_LSHIFT :
337
+ mod = SDL_KMOD_LSHIFT ;
338
+ break ;
339
+ case SDLK_RSHIFT :
340
+ mod = SDL_KMOD_RSHIFT ;
341
+ break ;
342
+ case SDLK_LCTRL :
343
+ mod = SDL_KMOD_LCTRL ;
344
+ break ;
345
+ case SDLK_RCTRL :
346
+ mod = SDL_KMOD_RCTRL ;
347
+ break ;
348
+ case SDLK_LALT :
349
+ mod = SDL_KMOD_LALT ;
350
+ break ;
351
+ case SDLK_RALT :
352
+ mod = SDL_KMOD_RALT ;
353
+ break ;
354
+ case SDLK_LGUI :
355
+ mod = SDL_KMOD_LGUI ;
356
+ break ;
357
+ case SDLK_RGUI :
358
+ mod = SDL_KMOD_RGUI ;
359
+ break ;
360
+ case SDLK_MODE :
361
+ mod = SDL_KMOD_MODE ;
362
+ break ;
363
+ default :
364
+ return ;
293
365
}
294
- X11_XFreeModifiermap (xmods );
295
366
296
- return num_mask ;
367
+ if (pressed ) {
368
+ viddata -> xkb .active_modifiers |= mod ;
369
+ } else {
370
+ viddata -> xkb .active_modifiers &= ~mod ;
371
+ }
372
+
373
+ if (reconcile ) {
374
+ X11_ReconcileModifiers (viddata );
375
+ }
297
376
}
298
377
299
378
void X11_ReconcileKeyboardState (SDL_VideoDevice * _this )
@@ -302,20 +381,10 @@ void X11_ReconcileKeyboardState(SDL_VideoDevice *_this)
302
381
Display * display = videodata -> display ;
303
382
char keys [32 ];
304
383
int keycode ;
305
- Window junk_window ;
306
- int x , y ;
307
- unsigned int mask ;
308
384
const bool * keyboardState ;
309
385
310
386
X11_XQueryKeymap (display , keys );
311
387
312
- // Sync up the keyboard modifier state
313
- if (X11_XQueryPointer (display , DefaultRootWindow (display ), & junk_window , & junk_window , & x , & y , & x , & y , & mask )) {
314
- SDL_ToggleModState (SDL_KMOD_CAPS , (mask & LockMask ) ? true : false);
315
- SDL_ToggleModState (SDL_KMOD_NUM , (mask & X11_GetNumLockModifierMask (_this )) ? true : false);
316
- SDL_ToggleModState (SDL_KMOD_SCROLL , (mask & X11_GetScrollLockModifierMask (_this )) ? true : false);
317
- }
318
-
319
388
keyboardState = SDL_GetKeyboardState (0 );
320
389
for (keycode = 0 ; keycode < SDL_arraysize (videodata -> key_layout ); ++ keycode ) {
321
390
SDL_Scancode scancode = videodata -> key_layout [keycode ];
@@ -334,15 +403,19 @@ void X11_ReconcileKeyboardState(SDL_VideoDevice *_this)
334
403
case SDLK_LGUI :
335
404
case SDLK_RGUI :
336
405
case SDLK_MODE :
337
- SDL_SendKeyboardKey (0 , SDL_GLOBAL_KEYBOARD_ID , keycode , scancode , true);
406
+ X11_HandleModifierKeys (videodata , scancode , true, false);
407
+ SDL_SendKeyboardKeyIgnoreModifiers (0 , SDL_GLOBAL_KEYBOARD_ID , keycode , scancode , true);
338
408
break ;
339
409
default :
340
410
break ;
341
411
}
342
412
} else if (!x11KeyPressed && sdlKeyPressed ) {
343
- SDL_SendKeyboardKey (0 , SDL_GLOBAL_KEYBOARD_ID , keycode , scancode , false);
413
+ X11_HandleModifierKeys (videodata , scancode , false, false);
414
+ SDL_SendKeyboardKeyIgnoreModifiers (0 , SDL_GLOBAL_KEYBOARD_ID , keycode , scancode , false);
344
415
}
345
416
}
417
+
418
+ X11_ReconcileModifiers (videodata );
346
419
}
347
420
348
421
static void X11_DispatchFocusIn (SDL_VideoDevice * _this , SDL_WindowData * data )
@@ -853,8 +926,10 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
853
926
videodata -> filter_time = xevent -> xkey .time ;
854
927
855
928
if (orig_event_type == KeyPress ) {
856
- SDL_SendKeyboardKey (timestamp , keyboardID , orig_keycode , scancode , true);
929
+ X11_HandleModifierKeys (videodata , scancode , true, true);
930
+ SDL_SendKeyboardKeyIgnoreModifiers (timestamp , keyboardID , orig_keycode , scancode , true);
857
931
} else {
932
+ X11_HandleModifierKeys (videodata , scancode , false, true);
858
933
SDL_SendKeyboardKey (timestamp , keyboardID , orig_keycode , scancode , false);
859
934
}
860
935
#endif
@@ -881,7 +956,8 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
881
956
if (xevent -> type == KeyPress ) {
882
957
// Don't send the key if it looks like a duplicate of a filtered key sent by an IME
883
958
if (xevent -> xkey .keycode != videodata -> filter_code || xevent -> xkey .time != videodata -> filter_time ) {
884
- SDL_SendKeyboardKey (timestamp , keyboardID , keycode , videodata -> key_layout [keycode ], true);
959
+ X11_HandleModifierKeys (videodata , videodata -> key_layout [keycode ], true, true);
960
+ SDL_SendKeyboardKeyIgnoreModifiers (timestamp , keyboardID , keycode , videodata -> key_layout [keycode ], true);
885
961
}
886
962
if (* text ) {
887
963
text [text_length ] = '\0' ;
@@ -892,7 +968,8 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_
892
968
// We're about to get a repeated key down, ignore the key up
893
969
return ;
894
970
}
895
- SDL_SendKeyboardKey (timestamp , keyboardID , keycode , videodata -> key_layout [keycode ], false);
971
+ X11_HandleModifierKeys (videodata , videodata -> key_layout [keycode ], false, true);
972
+ SDL_SendKeyboardKeyIgnoreModifiers (timestamp , keyboardID , keycode , videodata -> key_layout [keycode ], false);
896
973
}
897
974
}
898
975
@@ -1101,10 +1178,10 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
1101
1178
#endif
1102
1179
if (SDL_GetKeyboardFocus () != NULL ) {
1103
1180
#ifdef SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM
1104
- if (videodata -> xkb ) {
1181
+ if (videodata -> xkb . desc_ptr ) {
1105
1182
XkbStateRec state ;
1106
1183
if (X11_XkbGetState (videodata -> display , XkbUseCoreKbd , & state ) == Success ) {
1107
- if (state .group != videodata -> xkb_group ) {
1184
+ if (state .group != videodata -> xkb . current_group ) {
1108
1185
// Only rebuild the keymap if the layout has changed.
1109
1186
X11_UpdateKeymap (_this , true);
1110
1187
}
0 commit comments