68
68
// Weston uses a ratio of 10 units per scroll tick
69
69
#define WAYLAND_WHEEL_AXIS_UNIT 10
70
70
71
- // xkbcommon as of 1.4.1 doesn't have a name macro for the mode key
72
- #ifndef XKB_MOD_NAME_MODE
73
- #define XKB_MOD_NAME_MODE "Mod5"
71
+ // "Mod5" is typically level 3 shift, which SDL calls SDL_KMOD_MODE (AltGr).
72
+ #ifndef XKB_MOD_NAME_MOD5
73
+ #define XKB_MOD_NAME_MOD5 "Mod5"
74
+ #endif
75
+
76
+ // "Mod3" is typically level 5 shift, but is often remapped.
77
+ #ifndef XKB_MOD_NAME_MOD3
78
+ #define XKB_MOD_NAME_MOD3 "Mod3"
74
79
#endif
75
80
76
81
// Keyboard and mouse names to match XWayland
@@ -1267,28 +1272,46 @@ static void Wayland_keymap_iter(struct xkb_keymap *keymap, xkb_keycode_t key, vo
1267
1272
{
1268
1273
Wayland_Keymap * sdlKeymap = (Wayland_Keymap * )data ;
1269
1274
const xkb_keysym_t * syms ;
1270
- SDL_Scancode scancode ;
1271
-
1272
- scancode = SDL_GetScancodeFromTable (SDL_SCANCODE_TABLE_XFREE86_2 , (key - 8 ));
1275
+ const SDL_Scancode scancode = SDL_GetScancodeFromTable (SDL_SCANCODE_TABLE_XFREE86_2 , (key - 8 ));
1273
1276
if (scancode == SDL_SCANCODE_UNKNOWN ) {
1274
1277
return ;
1275
1278
}
1276
1279
1277
1280
if (WAYLAND_xkb_state_key_get_syms (sdlKeymap -> state , key , & syms ) > 0 ) {
1278
1281
uint32_t keycode = SDL_KeySymToUcs4 (syms [0 ]);
1282
+ bool key_is_unknown = false;
1279
1283
1280
1284
if (!keycode ) {
1281
- const SDL_Scancode sc = SDL_GetScancodeFromKeySym (syms [0 ], key );
1285
+ switch (syms [0 ]) {
1286
+ // The default SDL scancode table sets this to right alt instead of AltGr/Mode, so handle it separately.
1287
+ case XKB_KEY_ISO_Level3_Shift :
1288
+ keycode = SDLK_MODE ;
1289
+ break ;
1290
+
1291
+ /* The default SDL scancode table sets Meta L/R to the GUI keys, and Hyper R to app menu, which is
1292
+ * correct as far as physical key placement goes, but these keys are functionally distinct from the
1293
+ * default keycodes SDL returns for the scancodes, so they are set to unknown.
1294
+ *
1295
+ * SDL has no scancode mapping for Hyper L or Level 5 Shift.
1296
+ */
1297
+ case XKB_KEY_Meta_L :
1298
+ case XKB_KEY_Meta_R :
1299
+ case XKB_KEY_Hyper_L :
1300
+ case XKB_KEY_Hyper_R :
1301
+ case XKB_KEY_ISO_Level5_Shift :
1302
+ keycode = SDLK_UNKNOWN ;
1303
+ key_is_unknown = true;
1304
+ break ;
1282
1305
1283
- // Note: The default SDL scancode table sets this to right alt instead of AltGr/Mode, so handle it separately.
1284
- if (syms [0 ] != XKB_KEY_ISO_Level3_Shift ) {
1306
+ default :
1307
+ {
1308
+ const SDL_Scancode sc = SDL_GetScancodeFromKeySym (syms [0 ], key );
1285
1309
keycode = SDL_GetKeymapKeycode (NULL , sc , sdlKeymap -> modstate );
1286
- } else {
1287
- keycode = SDLK_MODE ;
1310
+ } break ;
1288
1311
}
1289
1312
}
1290
1313
1291
- if (!keycode ) {
1314
+ if (!keycode && ! key_is_unknown ) {
1292
1315
switch (scancode ) {
1293
1316
case SDL_SCANCODE_RETURN :
1294
1317
keycode = SDLK_RETURN ;
@@ -1326,10 +1349,18 @@ static void Wayland_UpdateKeymap(struct SDL_WaylandInput *input)
1326
1349
{ SDL_KMOD_SHIFT , input -> xkb .idx_shift },
1327
1350
{ SDL_KMOD_CAPS , input -> xkb .idx_caps },
1328
1351
{ SDL_KMOD_SHIFT | SDL_KMOD_CAPS , input -> xkb .idx_shift | input -> xkb .idx_caps },
1329
- { SDL_KMOD_MODE , input -> xkb .idx_mode },
1330
- { SDL_KMOD_MODE | SDL_KMOD_SHIFT , input -> xkb .idx_mode | input -> xkb .idx_shift },
1331
- { SDL_KMOD_MODE | SDL_KMOD_CAPS , input -> xkb .idx_mode | input -> xkb .idx_caps },
1332
- { SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS , input -> xkb .idx_mode | input -> xkb .idx_shift | input -> xkb .idx_caps }
1352
+ { SDL_KMOD_MODE , input -> xkb .idx_mod5 },
1353
+ { SDL_KMOD_MODE | SDL_KMOD_SHIFT , input -> xkb .idx_mod5 | input -> xkb .idx_shift },
1354
+ { SDL_KMOD_MODE | SDL_KMOD_CAPS , input -> xkb .idx_mod5 | input -> xkb .idx_caps },
1355
+ { SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS , input -> xkb .idx_mod5 | input -> xkb .idx_shift | input -> xkb .idx_caps },
1356
+ { SDL_KMOD_LEVEL5 , input -> xkb .idx_mod3 },
1357
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_SHIFT , input -> xkb .idx_mod3 | input -> xkb .idx_shift },
1358
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_CAPS , input -> xkb .idx_mod3 | input -> xkb .idx_caps },
1359
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_SHIFT | SDL_KMOD_CAPS , input -> xkb .idx_mod3 | input -> xkb .idx_shift | input -> xkb .idx_caps },
1360
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE , input -> xkb .idx_mod3 | input -> xkb .idx_mod5 },
1361
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_SHIFT , input -> xkb .idx_mod3 | input -> xkb .idx_mod5 | input -> xkb .idx_shift },
1362
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_CAPS , input -> xkb .idx_mod3 | input -> xkb .idx_mod5 | input -> xkb .idx_caps },
1363
+ { SDL_KMOD_LEVEL5 | SDL_KMOD_MODE | SDL_KMOD_SHIFT | SDL_KMOD_CAPS , input -> xkb .idx_mod3 | input -> xkb .idx_mod5 | input -> xkb .idx_shift | input -> xkb .idx_caps },
1333
1364
};
1334
1365
1335
1366
if (!input -> keyboard_is_virtual ) {
@@ -1350,7 +1381,7 @@ static void Wayland_UpdateKeymap(struct SDL_WaylandInput *input)
1350
1381
for (int i = 0 ; i < SDL_arraysize (keymod_masks ); ++ i ) {
1351
1382
keymap .modstate = keymod_masks [i ].sdl_mask ;
1352
1383
WAYLAND_xkb_state_update_mask (keymap .state ,
1353
- keymod_masks [i ].xkb_mask & (input -> xkb .idx_shift | input -> xkb .idx_mode ), 0 , keymod_masks [i ].xkb_mask & input -> xkb .idx_caps ,
1384
+ keymod_masks [i ].xkb_mask & (input -> xkb .idx_shift | input -> xkb .idx_mod5 | input -> xkb . idx_mod3 ), 0 , keymod_masks [i ].xkb_mask & input -> xkb .idx_caps ,
1354
1385
0 , 0 , input -> xkb .current_group );
1355
1386
WAYLAND_xkb_keymap_key_for_each (input -> xkb .keymap ,
1356
1387
Wayland_keymap_iter ,
@@ -1413,7 +1444,8 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
1413
1444
input -> xkb .idx_ctrl = 1 << GET_MOD_INDEX (CTRL );
1414
1445
input -> xkb .idx_alt = 1 << GET_MOD_INDEX (ALT );
1415
1446
input -> xkb .idx_gui = 1 << GET_MOD_INDEX (LOGO );
1416
- input -> xkb .idx_mode = 1 << GET_MOD_INDEX (MODE );
1447
+ input -> xkb .idx_mod3 = 1 << GET_MOD_INDEX (MOD3 );
1448
+ input -> xkb .idx_mod5 = 1 << GET_MOD_INDEX (MOD5 );
1417
1449
input -> xkb .idx_num = 1 << GET_MOD_INDEX (NUM );
1418
1450
input -> xkb .idx_caps = 1 << GET_MOD_INDEX (CAPS );
1419
1451
#undef GET_MOD_INDEX
@@ -1488,59 +1520,77 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
1488
1520
* Virtual keyboards can have arbitrary layouts, arbitrary scancodes/keycodes, etc...
1489
1521
* Key presses from these devices must be looked up by their keysym value.
1490
1522
*/
1491
- static SDL_Scancode Wayland_get_scancode_from_key (struct SDL_WaylandInput * input , uint32_t key )
1523
+ static void Wayland_get_scancode_from_key (struct SDL_WaylandInput * input , uint32_t keycode , SDL_Scancode * scancode )
1492
1524
{
1493
- SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN ;
1525
+ const xkb_keysym_t * syms ;
1494
1526
1495
1527
if (!input -> keyboard_is_virtual ) {
1496
- scancode = SDL_GetScancodeFromTable (SDL_SCANCODE_TABLE_XFREE86_2 , key - 8 );
1528
+ * scancode = SDL_GetScancodeFromTable (SDL_SCANCODE_TABLE_XFREE86_2 , keycode );
1497
1529
} else {
1498
- const xkb_keysym_t * syms ;
1499
- if (WAYLAND_xkb_keymap_key_get_syms_by_level (input -> xkb .keymap , key , input -> xkb .current_group , 0 , & syms ) > 0 ) {
1500
- scancode = SDL_GetScancodeFromKeySym (syms [0 ], key );
1530
+ if (WAYLAND_xkb_keymap_key_get_syms_by_level (input -> xkb .keymap , keycode + 8 , input -> xkb .current_group , 0 , & syms ) > 0 ) {
1531
+ * scancode = SDL_GetScancodeFromKeySym (syms [0 ], keycode + 8 );
1501
1532
}
1502
1533
}
1503
-
1504
- return scancode ;
1505
1534
}
1506
1535
1507
- static void Wayland_ReconcileModifiers (struct SDL_WaylandInput * input )
1536
+ static void Wayland_ReconcileModifiers (struct SDL_WaylandInput * input , bool key_pressed )
1508
1537
{
1509
- // Handle pressed modifiers for virtual keyboards that may not send keystrokes.
1510
- if (input -> keyboard_is_virtual ) {
1538
+ /* Handle explicit pressed modifier state. This will correct the modifier state
1539
+ * if common modifier keys were remapped and the modifiers presumed to be set
1540
+ * during a key press event were incorrect, or if the modifier was set to the
1541
+ * pressed state via means other than pressing the physical key.
1542
+ */
1543
+ if (!key_pressed ) {
1511
1544
if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_shift ) {
1512
- input -> pressed_modifiers |= SDL_KMOD_SHIFT ;
1545
+ if (!(input -> pressed_modifiers & SDL_KMOD_SHIFT )) {
1546
+ input -> pressed_modifiers |= SDL_KMOD_SHIFT ;
1547
+ }
1513
1548
} else {
1514
1549
input -> pressed_modifiers &= ~SDL_KMOD_SHIFT ;
1515
1550
}
1516
1551
1517
1552
if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_ctrl ) {
1518
- input -> pressed_modifiers |= SDL_KMOD_CTRL ;
1553
+ if (!(input -> pressed_modifiers & SDL_KMOD_CTRL )) {
1554
+ input -> pressed_modifiers |= SDL_KMOD_CTRL ;
1555
+ }
1519
1556
} else {
1520
1557
input -> pressed_modifiers &= ~SDL_KMOD_CTRL ;
1521
1558
}
1522
1559
1523
1560
if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_alt ) {
1524
- input -> pressed_modifiers |= SDL_KMOD_ALT ;
1561
+ if (!(input -> pressed_modifiers & SDL_KMOD_ALT )) {
1562
+ input -> pressed_modifiers |= SDL_KMOD_ALT ;
1563
+ }
1525
1564
} else {
1526
1565
input -> pressed_modifiers &= ~SDL_KMOD_ALT ;
1527
1566
}
1528
1567
1529
1568
if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_gui ) {
1530
- input -> pressed_modifiers |= SDL_KMOD_GUI ;
1569
+ if (!(input -> pressed_modifiers & SDL_KMOD_GUI )) {
1570
+ input -> pressed_modifiers |= SDL_KMOD_GUI ;
1571
+ }
1531
1572
} else {
1532
1573
input -> pressed_modifiers &= ~SDL_KMOD_GUI ;
1533
1574
}
1534
1575
1535
- if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_mode ) {
1536
- input -> pressed_modifiers |= SDL_KMOD_MODE ;
1576
+ if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_mod3 ) {
1577
+ if (!(input -> pressed_modifiers & SDL_KMOD_LEVEL5 )) {
1578
+ input -> pressed_modifiers |= SDL_KMOD_LEVEL5 ;
1579
+ }
1580
+ } else {
1581
+ input -> pressed_modifiers &= ~SDL_KMOD_LEVEL5 ;
1582
+ }
1583
+
1584
+ if (input -> xkb .wl_pressed_modifiers & input -> xkb .idx_mod5 ) {
1585
+ if (!(input -> pressed_modifiers & SDL_KMOD_MODE )) {
1586
+ input -> pressed_modifiers |= SDL_KMOD_MODE ;
1587
+ }
1537
1588
} else {
1538
1589
input -> pressed_modifiers &= ~SDL_KMOD_MODE ;
1539
1590
}
1540
1591
}
1541
1592
1542
- /*
1543
- * If a latch or lock was activated by a keypress, the latch/lock will
1593
+ /* If a latch or lock was activated by a keypress, the latch/lock will
1544
1594
* be tied to the specific left/right key that initiated it. Otherwise,
1545
1595
* the ambiguous left/right combo is used.
1546
1596
*
@@ -1591,7 +1641,16 @@ static void Wayland_ReconcileModifiers(struct SDL_WaylandInput *input)
1591
1641
input -> locked_modifiers &= ~SDL_KMOD_GUI ;
1592
1642
}
1593
1643
1594
- if (input -> xkb .wl_locked_modifiers & input -> xkb .idx_mode ) {
1644
+ /* The Mod3 modifier corresponds to no particular SDL keycode, so it is
1645
+ * only activated by the backend modifier callback.
1646
+ */
1647
+ if (input -> xkb .wl_locked_modifiers & input -> xkb .idx_mod3 ) {
1648
+ input -> locked_modifiers |= SDL_KMOD_LEVEL5 ;
1649
+ } else {
1650
+ input -> locked_modifiers &= ~SDL_KMOD_LEVEL5 ;
1651
+ }
1652
+
1653
+ if (input -> xkb .wl_locked_modifiers & input -> xkb .idx_mod5 ) {
1595
1654
input -> locked_modifiers |= SDL_KMOD_MODE ;
1596
1655
} else {
1597
1656
input -> locked_modifiers &= ~SDL_KMOD_MODE ;
@@ -1618,6 +1677,12 @@ static void Wayland_HandleModifierKeys(struct SDL_WaylandInput *input, SDL_Scanc
1618
1677
const SDL_Keycode keycode = SDL_GetKeyFromScancode (scancode , SDL_KMOD_NONE , false);
1619
1678
SDL_Keymod mod ;
1620
1679
1680
+ /* SDL clients expect modifier state to be activated at the same time as the
1681
+ * source keypress, so we set pressed modifier state with the usual modifier
1682
+ * keys here, as the explicit modifier event won't arrive until after the
1683
+ * keypress event. If this is wrong, it will be corrected when the explicit
1684
+ * modifier state is sent at a later time.
1685
+ */
1621
1686
switch (keycode ) {
1622
1687
case SDLK_LSHIFT :
1623
1688
mod = SDL_KMOD_LSHIFT ;
@@ -1656,7 +1721,7 @@ static void Wayland_HandleModifierKeys(struct SDL_WaylandInput *input, SDL_Scanc
1656
1721
input -> pressed_modifiers &= ~mod ;
1657
1722
}
1658
1723
1659
- Wayland_ReconcileModifiers (input );
1724
+ Wayland_ReconcileModifiers (input , true );
1660
1725
}
1661
1726
1662
1727
static void keyboard_handle_enter (void * data , struct wl_keyboard * keyboard ,
@@ -1694,7 +1759,9 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
1694
1759
window -> last_focus_event_time_ns = timestamp ;
1695
1760
1696
1761
wl_array_for_each (key , keys ) {
1697
- const SDL_Scancode scancode = Wayland_get_scancode_from_key (input , * key + 8 );
1762
+ SDL_Scancode scancode ;
1763
+
1764
+ Wayland_get_scancode_from_key (input , * key , & scancode );
1698
1765
const SDL_Keycode keycode = SDL_GetKeyFromScancode (scancode , SDL_KMOD_NONE , false);
1699
1766
1700
1767
switch (keycode ) {
@@ -1842,7 +1909,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
1842
1909
keyboard_input_get_text (text , input , key , false, & handled_by_ime );
1843
1910
}
1844
1911
1845
- scancode = Wayland_get_scancode_from_key (input , key + 8 );
1912
+ Wayland_get_scancode_from_key (input , key , & scancode );
1846
1913
Wayland_HandleModifierKeys (input , scancode , state == WL_KEYBOARD_KEY_STATE_PRESSED );
1847
1914
Uint64 timestamp = Wayland_GetKeyboardTimestamp (input , time );
1848
1915
SDL_SendKeyboardKeyIgnoreModifiers (timestamp , input -> keyboard_id , key , scancode , (state == WL_KEYBOARD_KEY_STATE_PRESSED ));
@@ -1878,7 +1945,7 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
1878
1945
input -> xkb .wl_pressed_modifiers = mods_depressed ;
1879
1946
input -> xkb .wl_locked_modifiers = mods_latched | mods_locked ;
1880
1947
1881
- Wayland_ReconcileModifiers (input );
1948
+ Wayland_ReconcileModifiers (input , false );
1882
1949
1883
1950
// If a key is repeating, update the text to apply the modifier.
1884
1951
if (keyboard_repeat_is_set (& input -> keyboard_repeat )) {
0 commit comments