mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-01-10 15:23:24 +00:00
wayland: Restore valid state information when building keymaps
The spec doesn't guarantee that a modifier event won't arrive before a keymap event, or that it will always be sent after a keymap change if the modifiers and layout index haven't changed, so restore any valid state after allocation when building a new keymap.
This commit is contained in:
@@ -1663,6 +1663,11 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||
}
|
||||
|
||||
WAYLAND_xkb_keymap_key_for_each(seat->keyboard.xkb.keymap, Wayland_KeymapIterator, seat);
|
||||
|
||||
// Restore any previously set modifier/layout information, if valid.
|
||||
WAYLAND_xkb_state_update_mask(seat->keyboard.xkb.state,
|
||||
seat->keyboard.xkb.wl_pressed_modifiers, seat->keyboard.xkb.wl_latched_modifiers, seat->keyboard.xkb.wl_locked_modifiers,
|
||||
0, 0, seat->keyboard.xkb.current_layout < seat->keyboard.xkb.num_layouts ? seat->keyboard.xkb.current_layout : 0);
|
||||
Wayland_SeatSetKeymap(seat);
|
||||
}
|
||||
|
||||
@@ -1806,7 +1811,9 @@ static void Wayland_ReconcileModifiers(SDL_WaylandSeat *seat, bool key_pressed)
|
||||
* The modifier will remain active until the latch/lock is released by
|
||||
* the system.
|
||||
*/
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.shift_mask) {
|
||||
const xkb_mod_mask_t xkb_locked_modifiers = seat->keyboard.xkb.wl_latched_modifiers | seat->keyboard.xkb.wl_locked_modifiers;
|
||||
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.shift_mask) {
|
||||
if (seat->keyboard.pressed_modifiers & SDL_KMOD_SHIFT) {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_SHIFT;
|
||||
seat->keyboard.locked_modifiers |= (seat->keyboard.pressed_modifiers & SDL_KMOD_SHIFT);
|
||||
@@ -1817,7 +1824,7 @@ static void Wayland_ReconcileModifiers(SDL_WaylandSeat *seat, bool key_pressed)
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_SHIFT;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.ctrl_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.ctrl_mask) {
|
||||
if (seat->keyboard.pressed_modifiers & SDL_KMOD_CTRL) {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_CTRL;
|
||||
seat->keyboard.locked_modifiers |= (seat->keyboard.pressed_modifiers & SDL_KMOD_CTRL);
|
||||
@@ -1828,7 +1835,7 @@ static void Wayland_ReconcileModifiers(SDL_WaylandSeat *seat, bool key_pressed)
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_CTRL;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.alt_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.alt_mask) {
|
||||
if (seat->keyboard.pressed_modifiers & SDL_KMOD_ALT) {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_ALT;
|
||||
seat->keyboard.locked_modifiers |= (seat->keyboard.pressed_modifiers & SDL_KMOD_ALT);
|
||||
@@ -1839,7 +1846,7 @@ static void Wayland_ReconcileModifiers(SDL_WaylandSeat *seat, bool key_pressed)
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_ALT;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.gui_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.gui_mask) {
|
||||
if (seat->keyboard.pressed_modifiers & SDL_KMOD_GUI) {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_GUI;
|
||||
seat->keyboard.locked_modifiers |= (seat->keyboard.pressed_modifiers & SDL_KMOD_GUI);
|
||||
@@ -1850,26 +1857,26 @@ static void Wayland_ReconcileModifiers(SDL_WaylandSeat *seat, bool key_pressed)
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_GUI;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.level3_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.level3_mask) {
|
||||
seat->keyboard.locked_modifiers |= SDL_KMOD_MODE;
|
||||
} else {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_MODE;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.level5_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.level5_mask) {
|
||||
seat->keyboard.locked_modifiers |= SDL_KMOD_LEVEL5;
|
||||
} else {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_LEVEL5;
|
||||
}
|
||||
|
||||
// Capslock and Numlock can only be locked, not pressed.
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.caps_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.caps_mask) {
|
||||
seat->keyboard.locked_modifiers |= SDL_KMOD_CAPS;
|
||||
} else {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_CAPS;
|
||||
}
|
||||
|
||||
if (seat->keyboard.xkb.wl_locked_modifiers & seat->keyboard.xkb.num_mask) {
|
||||
if (xkb_locked_modifiers & seat->keyboard.xkb.num_mask) {
|
||||
seat->keyboard.locked_modifiers |= SDL_KMOD_NUM;
|
||||
} else {
|
||||
seat->keyboard.locked_modifiers &= ~SDL_KMOD_NUM;
|
||||
@@ -2195,20 +2202,23 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t group)
|
||||
{
|
||||
SDL_WaylandSeat *seat = data;
|
||||
const uint32_t previous_layout = seat->keyboard.xkb.current_layout;
|
||||
|
||||
if (seat->keyboard.xkb.state == NULL) {
|
||||
/* if we get a modifier notification before the keymap, there's nothing we can do with the information
|
||||
*/
|
||||
seat->keyboard.xkb.wl_pressed_modifiers = mods_depressed;
|
||||
seat->keyboard.xkb.wl_latched_modifiers = mods_latched;
|
||||
seat->keyboard.xkb.wl_locked_modifiers = mods_locked;
|
||||
seat->keyboard.xkb.current_layout = group;
|
||||
|
||||
Wayland_ReconcileModifiers(seat, false);
|
||||
|
||||
// If we get a modifier notification before the keymap, there's no further state to update yet.
|
||||
if (!seat->keyboard.xkb.state) {
|
||||
return;
|
||||
}
|
||||
|
||||
WAYLAND_xkb_state_update_mask(seat->keyboard.xkb.state, mods_depressed, mods_latched,
|
||||
mods_locked, 0, 0, group);
|
||||
|
||||
seat->keyboard.xkb.wl_pressed_modifiers = mods_depressed;
|
||||
seat->keyboard.xkb.wl_locked_modifiers = mods_latched | mods_locked;
|
||||
|
||||
Wayland_ReconcileModifiers(seat, false);
|
||||
WAYLAND_xkb_state_update_mask(seat->keyboard.xkb.state,
|
||||
mods_depressed, mods_latched, mods_locked,
|
||||
0, 0, group);
|
||||
|
||||
// If a key is repeating, update the text to apply the modifier.
|
||||
if (keyboard_repeat_is_set(&seat->keyboard.repeat)) {
|
||||
@@ -2220,8 +2230,7 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||
}
|
||||
}
|
||||
|
||||
if (group != seat->keyboard.xkb.current_layout) {
|
||||
seat->keyboard.xkb.current_layout = group;
|
||||
if (group != previous_layout) {
|
||||
Wayland_SeatSetKeymap(seat);
|
||||
|
||||
if (seat->keyboard.xkb.compose_state) {
|
||||
|
||||
@@ -110,6 +110,7 @@ typedef struct SDL_WaylandSeat
|
||||
|
||||
// Current system modifier flags
|
||||
xkb_mod_mask_t wl_pressed_modifiers;
|
||||
xkb_mod_mask_t wl_latched_modifiers;
|
||||
xkb_mod_mask_t wl_locked_modifiers;
|
||||
} xkb;
|
||||
} keyboard;
|
||||
|
||||
Reference in New Issue
Block a user