From ea65d090ea251313868107b24f71672ff11baa47 Mon Sep 17 00:00:00 2001 From: Filipe Azevedo Date: Tue, 11 Nov 2025 09:16:49 +0000 Subject: [PATCH] fix key translation --- config.in | 2 +- include/sway/commands.h | 10 ++++++++++ sway/commands/bind.c | 14 ++------------ sway/input/keyboard.c | 28 ++++++++++++++++++++-------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/config.in b/config.in index 8ab636d7f..a27e10522 100644 --- a/config.in +++ b/config.in @@ -253,7 +253,7 @@ remap Super-q C-q # Quit # Tab navigation remap Super-Shift-bracketleft C-Page_Up -remap Super-Shift-bracketleft C-Page_Down +remap Super-Shift-bracketright C-Page_Down # Terminal-specific diff --git a/include/sway/commands.h b/include/sway/commands.h index d668b8f3c..e8b6688ab 100644 --- a/include/sway/commands.h +++ b/include/sway/commands.h @@ -98,6 +98,16 @@ void container_resize_tiled(struct sway_container *parent, uint32_t axis, struct sway_container *container_find_resize_parent(struct sway_container *con, uint32_t edge); +// Keysym to keycode translation (used by bind.c and keyboard.c) +struct keycode_matches { + xkb_keysym_t keysym; + xkb_keycode_t keycode; + int count; +}; + +void find_keycode(struct xkb_keymap *keymap, xkb_keycode_t keycode, void *data); +struct keycode_matches get_keycode_for_keysym(xkb_keysym_t keysym); + /** * Handlers shared by exec and exec_always. */ diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 15373d5a8..9b14bf857 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -647,21 +647,11 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding) transaction_commit_dirty(); } -/** - * The last found keycode associated with the keysym - * and the total count of matches. - */ -struct keycode_matches { - xkb_keysym_t keysym; - xkb_keycode_t keycode; - int count; -}; - /** * Iterate through keycodes in the keymap to find ones matching * the specified keysym. */ -static void find_keycode(struct xkb_keymap *keymap, +void find_keycode(struct xkb_keymap *keymap, xkb_keycode_t keycode, void *data) { xkb_keysym_t keysym = xkb_state_key_get_one_sym( config->keysym_translation_state, keycode); @@ -680,7 +670,7 @@ static void find_keycode(struct xkb_keymap *keymap, /** * Return the keycode for the specified keysym. */ -static struct keycode_matches get_keycode_for_keysym(xkb_keysym_t keysym) { +struct keycode_matches get_keycode_for_keysym(xkb_keysym_t keysym) { struct keycode_matches matches = { .keysym = keysym, .keycode = XKB_KEYCODE_INVALID, diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index 8179af276..c0cf481e6 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -411,6 +411,7 @@ static void update_keyboard_state(struct sway_keyboard *keyboard, } } + static void send_key_with_remap_check(struct sway_keyboard *keyboard, struct sway_seat *seat, struct wlr_seat *wlr_seat, uint32_t time_msec, uint32_t keycode, uint32_t state, const xkb_keysym_t *keysyms, size_t keysyms_len, uint32_t modifiers) { @@ -445,18 +446,29 @@ static void send_key_with_remap_check(struct sway_keyboard *keyboard, struct swa remap->to_modifiers, remap->to_keysym, remap->app_id ? " (app:" : "", remap->app_id ? remap->app_id : ""); + // Build remapped modifiers struct wlr_keyboard_modifiers new_mods = keyboard->wlr->modifiers; - - // Remove "from" modifiers and add "to" modifiers uint32_t new_mod_mask = modifiers; new_mod_mask &= ~remap->from_modifiers; // Remove source mods new_mod_mask |= remap->to_modifiers; // Add target mods new_mods.depressed = new_mod_mask; - // Send with remapped modifiers + // Find the keycode for the target keysym using existing bind.c logic + struct keycode_matches matches = get_keycode_for_keysym(remap->to_keysym); + + if (matches.count != 1) { + sway_log(SWAY_ERROR, "Failed to find unique keycode for remapped keysym 0x%x (found %d matches)", + remap->to_keysym, matches.count); + return; + } + + // XKB keycodes are offset by 8 from evdev keycodes + uint32_t target_keycode = matches.keycode - 8; + + // Send with remapped modifiers AND keycode wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); wlr_seat_keyboard_notify_modifiers(wlr_seat, &new_mods); - wlr_seat_keyboard_notify_key(wlr_seat, time_msec, keycode, state); + wlr_seat_keyboard_notify_key(wlr_seat, time_msec, target_keycode, state); return; } } @@ -611,8 +623,8 @@ static void handle_key_event(struct sway_keyboard *keyboard, event->state, keyinfo.keycode, 0); if (pressed_sent && seat->wlr_seat->keyboard_state.focused_surface) { send_key_with_remap_check(keyboard, seat, wlr_seat, event->time_msec, - event->keycode, event->state, keyinfo.translated_keysyms, - keyinfo.translated_keysyms_len, keyinfo.translated_modifiers); + event->keycode, event->state, keyinfo.raw_keysyms, + keyinfo.raw_keysyms_len, keyinfo.raw_modifiers); handled = true; } } @@ -636,8 +648,8 @@ static void handle_key_event(struct sway_keyboard *keyboard, keyinfo.keycode, 0); send_key_with_remap_check(keyboard, seat, wlr_seat, event->time_msec, - event->keycode, event->state, keyinfo.translated_keysyms, - keyinfo.translated_keysyms_len, keyinfo.translated_modifiers); + event->keycode, event->state, keyinfo.raw_keysyms, + keyinfo.raw_keysyms_len, keyinfo.raw_modifiers); } free(device_identifier);