git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commitbb52e5f8a2fde67b34f1dceb64566991ffe1ec06
parentf51d709deb
authorIsaac Freund <[email protected]>
date2024-01-11 16:55
Keyboard: don't send enter before keymap event

It's unclear if this is technically a violation of the protocol or not,
but it makes little sense to do this and many clients in the wild crash
if wl_keyboard.enter is sent before wl_keyboard.keymap.

 river/Keyboard.zig | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/river/Keyboard.zig b/river/Keyboard.zig
index 69c34b2..6d19023 100644
--- a/river/Keyboard.zig
+++ b/river/Keyboard.zig
@@ -75,8 +75,24 @@ pub fn deinit(self: *Self) void {
     self.key.link.remove();
     self.modifiers.link.remove();
 
+    const seat = self.device.seat;
+    const wlr_keyboard = self.device.wlr_device.toKeyboard();
+
     self.device.deinit();
 
+    // If the currently active keyboard of a seat is destroyed we need to set
+    // a new active keyboard. Otherwise wlroots may send an enter event without
+    // first having sent a keymap event if Seat.keyboardNotifyEnter() is called
+    // before a new active keyboard is set.
+    if (seat.wlr_seat.getKeyboard() == wlr_keyboard) {
+        var it = server.input_manager.devices.iterator(.forward);
+        while (it.next()) |device| {
+            if (device.seat == seat and device.wlr_device.type == .keyboard) {
+                seat.wlr_seat.setKeyboard(device.wlr_device.toKeyboard());
+            }
+        }
+    }
+
     self.* = undefined;
 }