Keyboard: eat key before running mapping
To see why this is needed, compare the following flows:
- user: press key 'j' with Super already pressed
- Keyboard: handle mapping, focusing next view
- Seat: send wl_keyboard.enter with keys Super and 'j'
- Keyboard: eat key 'j'
versus:
- user: press key 'j' with Super already pressed
- Keyboard: eat key 'j'
- Keyboard: handle mapping, focusing next view
- Seat: send wl_keyboard.enter with key Super.
The necessity of this was already mentioned in 1e3b8ed1; however,
without a comment in code, it was removed in 393bfb42
as superfluous.
Hopefully, the newly added comment will prevent such mistakes in the
future.
Fixes https://github.com/riverwm/river/issues/978
This commit is contained in:
parent
66f1881a72
commit
4685f6906d
@ -143,7 +143,10 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
|
|||||||
// We can only eat a key on press; never on release
|
// We can only eat a key on press; never on release
|
||||||
if (released) break :blk self.eaten_keycodes.remove(event.keycode);
|
if (released) break :blk self.eaten_keycodes.remove(event.keycode);
|
||||||
|
|
||||||
if (self.device.seat.handleMapping(keycode, modifiers, released, xkb_state)) {
|
if (self.device.seat.hasMapping(keycode, modifiers, released, xkb_state)) {
|
||||||
|
// The key needs to be eaten before the mapping is run
|
||||||
|
// Otherwise the mapping may e.g. trigger a focus change which sends an incorrect
|
||||||
|
// wl_keyboard.enter event since eaten_keycodes has not yet been updated.
|
||||||
break :blk self.eaten_keycodes.add(event.keycode, .mapping);
|
break :blk self.eaten_keycodes.add(event.keycode, .mapping);
|
||||||
} else if (self.getInputMethodGrab() != null) {
|
} else if (self.getInputMethodGrab() != null) {
|
||||||
break :blk self.eaten_keycodes.add(event.keycode, .im_grab);
|
break :blk self.eaten_keycodes.add(event.keycode, .im_grab);
|
||||||
@ -158,7 +161,11 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
|
|||||||
wlr_seat.setKeyboard(self.device.wlr_device.toKeyboard());
|
wlr_seat.setKeyboard(self.device.wlr_device.toKeyboard());
|
||||||
wlr_seat.keyboardNotifyKey(event.time_msec, event.keycode, event.state);
|
wlr_seat.keyboardNotifyKey(event.time_msec, event.keycode, event.state);
|
||||||
},
|
},
|
||||||
.mapping => {},
|
.mapping => if (!released) {
|
||||||
|
// We handle release mappings separately, regardless of whether press mapping exists
|
||||||
|
const handled = self.device.seat.handleMapping(keycode, modifiers, released, xkb_state);
|
||||||
|
assert(handled);
|
||||||
|
},
|
||||||
.im_grab => if (self.getInputMethodGrab()) |keyboard_grab| {
|
.im_grab => if (self.getInputMethodGrab()) |keyboard_grab| {
|
||||||
keyboard_grab.setKeyboard(keyboard_grab.keyboard);
|
keyboard_grab.setKeyboard(keyboard_grab.keyboard);
|
||||||
keyboard_grab.sendKey(event.time_msec, event.keycode, event.state);
|
keyboard_grab.sendKey(event.time_msec, event.keycode, event.state);
|
||||||
|
@ -359,6 +359,25 @@ pub fn enterMode(self: *Self, mode_id: u32) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Is there a user-defined mapping for passed keycode, modifiers and keyboard state?
|
||||||
|
pub fn hasMapping(
|
||||||
|
self: *Self,
|
||||||
|
keycode: xkb.Keycode,
|
||||||
|
modifiers: wlr.Keyboard.ModifierMask,
|
||||||
|
released: bool,
|
||||||
|
xkb_state: *xkb.State,
|
||||||
|
) bool {
|
||||||
|
const modes = &server.config.modes;
|
||||||
|
for (modes.items[self.mode_id].mappings.items) |*mapping| {
|
||||||
|
if (mapping.match(keycode, modifiers, released, xkb_state, .no_translate) or
|
||||||
|
mapping.match(keycode, modifiers, released, xkb_state, .translate))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle any user-defined mapping for passed keycode, modifiers and keyboard state
|
/// Handle any user-defined mapping for passed keycode, modifiers and keyboard state
|
||||||
/// Returns true if a mapping was run
|
/// Returns true if a mapping was run
|
||||||
pub fn handleMapping(
|
pub fn handleMapping(
|
||||||
|
Loading…
Reference in New Issue
Block a user