command/map: layout-pinned mappings

e.g. `riverctl map -layout 0 normal Super Y spawn foot`

When this mapping is checked against a pressed key, layout 0 will be used to translate the pressed key instead of the currently active layout.

The number denotes to an index of the layouts set with
`XKB_DEFAULT_LAYOUT`.
This commit is contained in:
Peter Kaplan
2022-04-20 15:38:18 +02:00
committed by Isaac Freund
parent 8f59075bc5
commit 44aaee3a51
9 changed files with 131 additions and 56 deletions
+20 -34
View File
@@ -85,54 +85,40 @@ fn handleKey(listener: *wl.Listener(*wlr.Keyboard.event.Key), event: *wlr.Keyboa
// Translate libinput keycode -> xkbcommon
const keycode = event.keycode + 8;
// TODO: These modifiers aren't properly handled, see sway's code
const modifiers = wlr_keyboard.getModifiers();
const released = event.state == .released;
var handled = false;
const xkb_state = wlr_keyboard.xkb_state orelse return;
const keysyms = xkb_state.keyGetSyms(keycode);
var non_modifier_pressed = false;
// First check translated keysyms as xkb reports them
for (wlr_keyboard.xkb_state.?.keyGetSyms(keycode)) |sym| {
if (!released and !isModifier(sym)) non_modifier_pressed = true;
// Handle builtin mapping only when keys are pressed
if (!released and handleBuiltinMapping(sym)) {
handled = true;
break;
} else if (self.seat.handleMapping(sym, modifiers, released)) {
handled = true;
// Hide cursor when typing
for (keysyms) |sym| {
if (server.config.cursor_hide_when_typing == .enabled and
!released and
!isModifier(sym))
{
self.seat.cursor.hide();
break;
}
}
// If not yet handled, check keysyms ignoring modifiers (e.g. 1 instead of !)
// Important for mappings like Mod+Shift+1
if (!handled) {
const layout_index = wlr_keyboard.xkb_state.?.keyGetLayout(keycode);
for (wlr_keyboard.keymap.?.keyGetSymsByLevel(keycode, layout_index, 0)) |sym| {
// Handle builtin mapping only when keys are pressed
if (!released and handleBuiltinMapping(sym)) {
handled = true;
break;
} else if (self.seat.handleMapping(sym, modifiers, released)) {
handled = true;
break;
}
}
// Handle builtin mapping, only when keys are pressed
for (keysyms) |sym| {
if (!released and handleBuiltinMapping(sym)) return;
}
if (!handled) {
// Otherwise, we pass it along to the client.
// Handle user-defined mapping
if (!self.seat.handleMapping(
keycode,
modifiers,
released,
xkb_state,
)) {
// 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);
wlr_seat.keyboardNotifyKey(event.time_msec, event.keycode, event.state);
}
if (non_modifier_pressed and server.config.cursor_hide_when_typing == .enabled) {
self.seat.cursor.hide();
}
}
fn isModifier(keysym: xkb.Keysym) bool {