Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
KeyboardGroup: don't eat modifiers due to ensure_next_key_eaten
protocol/river-xkb-bindings-v1.xml | 13 +++++----
river/KeyboardGroup.zig | 60 ++++++++++++++++++++++++++++++++++++--
2 files changed, 65 insertions(+), 8 deletions(-)
diff --git a/protocol/river-xkb-bindings-v1.xml b/protocol/river-xkb-bindings-v1.xml
index bc41dea..041b1bd 100644
--- a/protocol/river-xkb-bindings-v1.xml
+++ b/protocol/river-xkb-bindings-v1.xml
@@ -219,14 +219,15 @@
<request name="ensure_next_key_eaten" since="2">
<description summary="ensure the next key press event is eaten">
- Ensure that the next key press and corresponding release events for this
- seat are not sent to the currently focused surface.
+ Ensure that the next non-modifier key press and corresponding release
+ events for this seat are not sent to the currently focused surface.
- If the next key press triggers a binding, the pressed/released events are
- sent to the river_xkb_binding_v1 object as usual.
+ If the next non-modifier key press triggers a binding, the
+ pressed/released events are sent to the river_xkb_binding_v1 object as
+ usual.
- If the next key press does not trigger a binding, the ate_unbound_key
- event is sent instead.
+ If the next non-modifier key press does not trigger a binding, the
+ ate_unbound_key event is sent instead.
Rationale: the window manager may wish to implement "chorded"
keybindings where triggering a binding activates a "submap" with a
diff --git a/river/KeyboardGroup.zig b/river/KeyboardGroup.zig
index f079ebc..4972f3a 100644
--- a/river/KeyboardGroup.zig
+++ b/river/KeyboardGroup.zig
@@ -214,8 +214,20 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
};
}
if (group.seat.xkb_bindings_seat.ensure_next_key_eaten) {
- group.seat.xkb_bindings_seat.ensure_next_key_eaten = false;
- break :blk .ensure_eaten;
+ // This approach for filtering out modifiers feels like a hack.
+ // Open questions:
+ // - Are there keycodes that should be considered a modifier which
+ // are not yet checked by keysymIsModifier()?
+ // - Is it possible to test whether keysymIsModifier() is complete?
+ // - Is there a way to test the effect the keycode would have on
+ // the active modifiers of the xkb_state?
+ // - Could we add a function to libxkbcommon to make that possible?
+ for (xkb_state.keyGetSyms(xkb_keycode)) |sym| {
+ if (!keysymIsModifier(sym)) {
+ group.seat.xkb_bindings_seat.ensure_next_key_eaten = false;
+ break :blk .ensure_eaten;
+ }
+ }
}
if (group.getInputMethodGrab() != null) {
break :blk .im_grab;
@@ -256,6 +268,50 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
}
}
+fn keysymIsModifier(keysym: xkb.Keysym) bool {
+ switch (@intFromEnum(keysym)) {
+ xkb.Keysym.Shift_L,
+ xkb.Keysym.Shift_R,
+ xkb.Keysym.Control_L,
+ xkb.Keysym.Control_R,
+ xkb.Keysym.Caps_Lock,
+ xkb.Keysym.Shift_Lock,
+
+ xkb.Keysym.Meta_L,
+ xkb.Keysym.Meta_R,
+ xkb.Keysym.Alt_L,
+ xkb.Keysym.Alt_R,
+ xkb.Keysym.Super_L,
+ xkb.Keysym.Super_R,
+ xkb.Keysym.Hyper_L,
+ xkb.Keysym.Hyper_R,
+
+ xkb.Keysym.Num_Lock,
+
+ xkb.Keysym.ISO_Lock,
+ xkb.Keysym.ISO_Level2_Latch,
+ xkb.Keysym.ISO_Level3_Shift,
+ xkb.Keysym.ISO_Level3_Latch,
+ xkb.Keysym.ISO_Level3_Lock,
+ xkb.Keysym.ISO_Level5_Shift,
+ xkb.Keysym.ISO_Level5_Latch,
+ xkb.Keysym.ISO_Level5_Lock,
+ xkb.Keysym.ISO_Group_Shift,
+ xkb.Keysym.ISO_Group_Latch,
+ xkb.Keysym.ISO_Group_Lock,
+ xkb.Keysym.ISO_Next_Group,
+ xkb.Keysym.ISO_Next_Group_Lock,
+ xkb.Keysym.ISO_Prev_Group,
+ xkb.Keysym.ISO_Prev_Group_Lock,
+ xkb.Keysym.ISO_First_Group,
+ xkb.Keysym.ISO_First_Group_Lock,
+ xkb.Keysym.ISO_Last_Group,
+ xkb.Keysym.ISO_Last_Group_Lock,
+ => return true,
+ else => return false,
+ }
+}
+
pub fn processModifiers(group: *KeyboardGroup, modifiers: wlr.Keyboard.Modifiers) void {
group.state.notifyModifiers(modifiers);
}