fix key translation

This commit is contained in:
Filipe Azevedo 2025-11-11 09:16:49 +00:00
parent 6e983f6943
commit ea65d090ea
No known key found for this signature in database
4 changed files with 33 additions and 21 deletions

View file

@ -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

View file

@ -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.
*/

View file

@ -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,

View file

@ -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);