Keyboard: clarify keypress routing logic
This commit is contained in:
parent
40920c7818
commit
be4dbe3fe7
@ -102,38 +102,36 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle builtin mapping, only when keys are pressed
|
|
||||||
for (keysyms) |sym| {
|
for (keysyms) |sym| {
|
||||||
if (!released and handleBuiltinMapping(sym)) return;
|
if (!released and handleBuiltinMapping(sym)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle user-defined mappings
|
// If we sent a pressed event to the client we should send the matching release event as well,
|
||||||
const mapped = self.device.seat.hasMapping(keycode, modifiers, released, xkb_state);
|
// even if the release event triggers a mapping or would otherwise be sent to an input method.
|
||||||
if (mapped) {
|
const sent_to_client = blk: {
|
||||||
|
if (released and !self.eaten_keycodes.remove(event.keycode)) {
|
||||||
|
const wlr_seat = self.device.seat.wlr_seat;
|
||||||
|
wlr_seat.setKeyboard(self.device.wlr_device.toKeyboard());
|
||||||
|
wlr_seat.keyboardNotifyKey(event.time_msec, event.keycode, event.state);
|
||||||
|
break :blk true;
|
||||||
|
} else {
|
||||||
|
break :blk false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (self.device.seat.hasMapping(keycode, modifiers, released, xkb_state)) {
|
||||||
if (!released) self.eaten_keycodes.add(event.keycode);
|
if (!released) self.eaten_keycodes.add(event.keycode);
|
||||||
|
|
||||||
const handled = self.device.seat.handleMapping(keycode, modifiers, released, xkb_state);
|
const handled = self.device.seat.handleMapping(keycode, modifiers, released, xkb_state);
|
||||||
assert(handled);
|
assert(handled);
|
||||||
|
} else if (self.getInputMethodGrab()) |keyboard_grab| {
|
||||||
|
if (!released) self.eaten_keycodes.add(event.keycode);
|
||||||
|
|
||||||
|
if (!sent_to_client) {
|
||||||
|
keyboard_grab.setKeyboard(keyboard_grab.keyboard);
|
||||||
|
keyboard_grab.sendKey(event.time_msec, event.keycode, event.state);
|
||||||
}
|
}
|
||||||
|
} else if (!sent_to_client) {
|
||||||
// Handle IM grab
|
|
||||||
const keyboard_grab = self.getInputMethodGrab();
|
|
||||||
const grabbed = !mapped and (keyboard_grab != null);
|
|
||||||
if (grabbed) ungrab: {
|
|
||||||
if (!released) {
|
|
||||||
self.eaten_keycodes.add(event.keycode);
|
|
||||||
} else if (!self.eaten_keycodes.present(event.keycode)) {
|
|
||||||
break :ungrab;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboard_grab.?.setKeyboard(keyboard_grab.?.keyboard);
|
|
||||||
keyboard_grab.?.sendKey(event.time_msec, event.keycode, event.state);
|
|
||||||
}
|
|
||||||
|
|
||||||
const eaten = if (released) self.eaten_keycodes.remove(event.keycode) else (mapped or grabbed);
|
|
||||||
|
|
||||||
if (!eaten) {
|
|
||||||
// If key was not handled, we pass it along to the client.
|
|
||||||
const wlr_seat = self.device.seat.wlr_seat;
|
const wlr_seat = self.device.seat.wlr_seat;
|
||||||
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);
|
||||||
@ -179,15 +177,18 @@ fn handleBuiltinMapping(keysym: xkb.Keysym) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns null if the keyboard is not grabbed by an input method,
|
/// Returns null if the keyboard is not grabbed by an input method,
|
||||||
/// or if event is from virtual keyboard of the same client as grab.
|
/// or if event is from a virtual keyboard of the same client as the grab.
|
||||||
/// TODO: see https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2322
|
/// TODO: see https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/2322
|
||||||
fn getInputMethodGrab(self: Self) ?*wlr.InputMethodV2.KeyboardGrab {
|
fn getInputMethodGrab(self: Self) ?*wlr.InputMethodV2.KeyboardGrab {
|
||||||
const input_method = self.device.seat.relay.input_method;
|
if (self.device.seat.relay.input_method) |input_method| {
|
||||||
const virtual_keyboard = self.device.wlr_device.getVirtualKeyboard();
|
if (input_method.keyboard_grab) |keyboard_grab| {
|
||||||
if (input_method == null or input_method.?.keyboard_grab == null or
|
if (self.device.wlr_device.getVirtualKeyboard()) |virtual_keyboard| {
|
||||||
(virtual_keyboard != null and
|
if (virtual_keyboard.resource.getClient() == keyboard_grab.resource.getClient()) {
|
||||||
virtual_keyboard.?.resource.getClient() == input_method.?.keyboard_grab.?.resource.getClient()))
|
return null;
|
||||||
{
|
}
|
||||||
|
}
|
||||||
|
return keyboard_grab;
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
} else return input_method.?.keyboard_grab;
|
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,6 @@ pub fn add(self: *Self, new: u32) void {
|
|||||||
self.len += 1;
|
self.len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn present(self: *Self, value: u32) bool {
|
|
||||||
for (self.items[0..self.len]) |item| if (value == item) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remove(self: *Self, old: u32) bool {
|
pub fn remove(self: *Self, old: u32) bool {
|
||||||
for (self.items[0..self.len], 0..) |item, idx| if (old == item) {
|
for (self.items[0..self.len], 0..) |item, idx| if (old == item) {
|
||||||
self.len -= 1;
|
self.len -= 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user