Keyboard: eat key release event for mappings
Until now, only the event (press/release) for which a mapping was present got eaten, and the other was passed to the client. From this commit, a press mapping eats both events and a release mapping eats nothing (and a press+release combo eats both). This fixes behavior of some clients that do not make a difference between press and release (e.g. Firefox with a fullscreen video exiting fullscreen even on an Esc release event).
This commit is contained in:
parent
706dca9b1a
commit
6d6646febe
@ -24,6 +24,7 @@ const xkb = @import("xkbcommon");
|
||||
const server = &@import("main.zig").server;
|
||||
const util = @import("util.zig");
|
||||
|
||||
const KeycodeSet = @import("KeycodeSet.zig");
|
||||
const Seat = @import("Seat.zig");
|
||||
|
||||
const log = std.log.scoped(.keyboard);
|
||||
@ -31,6 +32,9 @@ const log = std.log.scoped(.keyboard);
|
||||
seat: *Seat,
|
||||
input_device: *wlr.InputDevice,
|
||||
|
||||
/// Pressed keys for which a mapping was triggered on press
|
||||
eaten_keycodes: KeycodeSet = .{},
|
||||
|
||||
key: wl.Listener(*wlr.Keyboard.event.Key) = wl.Listener(*wlr.Keyboard.event.Key).init(handleKey),
|
||||
modifiers: wl.Listener(*wlr.Keyboard) = wl.Listener(*wlr.Keyboard).init(handleModifiers),
|
||||
destroy: wl.Listener(*wlr.Keyboard) = wl.Listener(*wlr.Keyboard).init(handleDestroy),
|
||||
@ -108,12 +112,12 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
|
||||
}
|
||||
|
||||
// Handle user-defined mapping
|
||||
if (!self.seat.handleMapping(
|
||||
keycode,
|
||||
modifiers,
|
||||
released,
|
||||
xkb_state,
|
||||
)) {
|
||||
const mapped = self.seat.handleMapping(keycode, modifiers, released, xkb_state);
|
||||
if (mapped and !released) self.eaten_keycodes.add(event.keycode);
|
||||
|
||||
const eaten = if (released) self.eaten_keycodes.remove(event.keycode) else mapped;
|
||||
|
||||
if (!eaten) {
|
||||
// If key was not handled, we pass it along to the client.
|
||||
const wlr_seat = self.seat.wlr_seat;
|
||||
wlr_seat.setKeyboard(self.input_device);
|
||||
|
52
river/KeycodeSet.zig
Normal file
52
river/KeycodeSet.zig
Normal file
@ -0,0 +1,52 @@
|
||||
// This file is part of river, a dynamic tiling wayland compositor.
|
||||
//
|
||||
// Copyright 2022 The River Developers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.keyboard);
|
||||
|
||||
const wlr = @import("wlroots");
|
||||
|
||||
items: [32]u32 = undefined,
|
||||
len: usize = 0,
|
||||
|
||||
pub fn add(self: *Self, new: u32) void {
|
||||
for (self.items[0..self.len]) |item| if (new == item) return;
|
||||
|
||||
comptime assert(@typeInfo(std.meta.fieldInfo(Self, .items).field_type).Array.len ==
|
||||
@typeInfo(std.meta.fieldInfo(wlr.Keyboard, .keycodes).field_type).Array.len);
|
||||
|
||||
if (self.len == self.items.len) {
|
||||
log.err("KeycodeSet limit reached, code {d} omitted", .{new});
|
||||
return;
|
||||
}
|
||||
|
||||
self.items[self.len] = new;
|
||||
self.len += 1;
|
||||
}
|
||||
|
||||
pub fn remove(self: *Self, old: u32) bool {
|
||||
for (self.items[0..self.len]) |item, idx| if (old == item) {
|
||||
self.len -= 1;
|
||||
if (self.len > 0) self.items[idx] = self.items[self.len];
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
return false;
|
||||
}
|
Loading…
Reference in New Issue
Block a user