mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-09-14 06:58:53 +00:00
Re-apply remap_modifiers to a reloaded xkb keymap state
On X11 glfw_xkb_compile_keymap() gets its state from xkb_x11_state_new_from_device(), which seeds it with the server's physical modifier mask. Every other path into that state goes through glfw_xkb_update_modifiers(), where the permutation is applied, so after a keymap reload the state held physical modifiers until the next XkbStateNotify happened to arrive. Any key pressed in that window was encoded with the modifier on the keycap: with ctrl held across a reload under `remap_modifiers ctrl:super`, Ctrl+A reached the child as a literal 0x01. Keymap reloads are routine - switching layout causes one, and so does any client asking X for a keysym it must bind to a spare keycode. Re-apply the permutation to the freshly loaded state, after glfw_xkb_update_masks() has computed the modifier indices it is expressed in. On Wayland the new state is empty, so this is a no-op there.
This commit is contained in:
parent
48625a824d
commit
bd0a39f495
1 changed files with 38 additions and 0 deletions
38
glfw/xkb_glfw.c
vendored
38
glfw/xkb_glfw.c
vendored
|
|
@ -724,6 +724,39 @@ update_modifiers(_GLFWXKBData *xkb) {
|
|||
xkb->states.activeUnknownModifiers = active_unknown_modifiers(xkb, xkb->states.state);
|
||||
}
|
||||
|
||||
#ifdef _GLFW_X11
|
||||
static xkb_mod_mask_t remap_xkb_mask(_GLFWXKBData *xkb, xkb_mod_mask_t mask);
|
||||
|
||||
// A freshly loaded state is seeded from the server's live modifier state by
|
||||
// xkb_x11_state_new_from_device(), which knows nothing about remap_modifiers.
|
||||
// Every other way the state changes goes through glfw_xkb_update_modifiers(),
|
||||
// where the permutation is applied, so without this the state holds physical
|
||||
// modifiers from the reload until the next XkbStateNotify happens to arrive, and
|
||||
// key events in that window report the modifier on the keycap rather than the
|
||||
// one it was remapped to.
|
||||
//
|
||||
// X11 only: elsewhere xkb_glfw_load_state() is xkb_state_new(), which starts
|
||||
// empty, so there is nothing to re-apply.
|
||||
static void
|
||||
reapply_modifier_remap_to_state(_GLFWXKBData *xkb) {
|
||||
if (!_glfw.modifierRemapMask || !xkb->states.state) return;
|
||||
const xkb_mod_mask_t depressed = xkb_state_serialize_mods(xkb->states.state, XKB_STATE_MODS_DEPRESSED);
|
||||
const xkb_mod_mask_t latched = xkb_state_serialize_mods(xkb->states.state, XKB_STATE_MODS_LATCHED);
|
||||
const xkb_mod_mask_t locked = xkb_state_serialize_mods(xkb->states.state, XKB_STATE_MODS_LOCKED);
|
||||
const xkb_mod_mask_t remapped = remap_xkb_mask(xkb, depressed);
|
||||
if (remapped == depressed && latched == remap_xkb_mask(xkb, latched) && locked == remap_xkb_mask(xkb, locked)) return;
|
||||
debug("remap_modifier: re-applying to reloaded xkb state, depressed 0x%x -> 0x%x\n", depressed, remapped);
|
||||
xkb_state_update_mask(
|
||||
xkb->states.state,
|
||||
remapped,
|
||||
remap_xkb_mask(xkb, latched),
|
||||
remap_xkb_mask(xkb, locked),
|
||||
xkb_state_serialize_layout(xkb->states.state, XKB_STATE_LAYOUT_DEPRESSED),
|
||||
xkb_state_serialize_layout(xkb->states.state, XKB_STATE_LAYOUT_LATCHED),
|
||||
xkb_state_serialize_layout(xkb->states.state, XKB_STATE_LAYOUT_LOCKED));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
||||
const char *err;
|
||||
|
|
@ -751,6 +784,11 @@ glfw_xkb_compile_keymap(_GLFWXKBData *xkb, const char *map_str) {
|
|||
i != xkb->capsLockIdx && i != xkb->numLockIdx)
|
||||
xkb->unknownModifiers[j++] = i;
|
||||
}
|
||||
#ifdef _GLFW_X11
|
||||
// after glfw_xkb_update_masks(), which computes the modifier indices the
|
||||
// remap is expressed in, and before update_modifiers() reads the state
|
||||
reapply_modifier_remap_to_state(xkb);
|
||||
#endif
|
||||
xkb->states.modifiers = 0;
|
||||
xkb->states.activeUnknownModifiers = 0;
|
||||
update_modifiers(xkb);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue