Keyboard: ignore multiple presses of a key
I have managed to crash river (because the relevant assertion was wrong) on this using fcitx5 (5.1.8) and anthy with the following sequence of key events on a physical keyboard (every line followed by releasing everything): super-; (my shortcut to enable anthy) shift-letter (fcitx doesn't release shift on its virtual keyboard) escape shift (fcitx sends another press event) The failure to release shift is not the only weirdness happening, but it's what eventually lead to the assertion failure.
This commit is contained in:
parent
7ceed0d093
commit
198351794b
@ -59,9 +59,15 @@ pub const Pressed = struct {
|
||||
|
||||
keys: std.BoundedArray(Key, capacity) = .{},
|
||||
|
||||
fn addAssumeCapacity(pressed: *Pressed, new: Key) void {
|
||||
for (pressed.keys.constSlice()) |item| assert(new.code != item.code);
|
||||
fn contains(pressed: *Pressed, code: u32) bool {
|
||||
for (pressed.keys.constSlice()) |item| {
|
||||
if (item.code == code) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn addAssumeCapacity(pressed: *Pressed, new: Key) void {
|
||||
assert(!pressed.contains(new.code));
|
||||
pressed.keys.appendAssumeCapacity(new);
|
||||
}
|
||||
|
||||
@ -177,6 +183,16 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
|
||||
if (!released and handleBuiltinMapping(sym)) return;
|
||||
}
|
||||
|
||||
// Some virtual_keyboard clients are buggy and press a key twice without
|
||||
// releasing it in between. There is no good way for river to handle this
|
||||
// other than to ignore any newer presses. No need to worry about pairing
|
||||
// the correct release, as the client is unlikely to send all of them
|
||||
// (and we already ignore releasing keys we don't know were pressed).
|
||||
if (!released and keyboard.pressed.contains(event.keycode)) {
|
||||
log.err("key pressed again without release, virtual-keyboard client bug?", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
// Every sent press event, to a regular client or the input method, should have
|
||||
// the corresponding release event sent to the same client.
|
||||
// Similarly, no press event means no release event.
|
||||
|
Loading…
Reference in New Issue
Block a user