Skip to content

fix: respect xkb keysym remaps for editing keys#15

Open
raviboth wants to merge 1 commit into
no1msd:mainfrom
raviboth:fix/caps-remap-keycode
Open

fix: respect xkb keysym remaps for editing keys#15
raviboth wants to merge 1 commit into
no1msd:mainfrom
raviboth:fix/caps-remap-keycode

Conversation

@raviboth
Copy link
Copy Markdown

Why I'm filing this

I use the Colemak keyboard layout and have Caps Lock remapped to Backspace at the xkb level — this is a very common ergonomic setup (Caps Lock is unused real estate, Backspace gets used constantly, the remap puts it under a home-row finger). Every other app on my system honours the remap. In Seance the remapped key does nothing, which makes the terminal effectively unusable for me without reaching across the keyboard for the real Backspace key.

This patch makes Seance honour the remap.

Summary

xkb-level keysym remaps (e.g. KDE's Caps Lock behaves as Backspace) are silently dropped inside Seance. The remapped key sends nothing to the terminal even though wev confirms the Wayland compositor delivers the remapped keysym.

Root cause

GDK delivers a (keyval, hardware_keycode) pair where the keyval reflects the xkb remap but the hardware keycode still identifies the original physical key. handleKeyEvent in src/pane.zig forwards the raw keycode to ghostty_surface_key. libghostty's input handling is keycode-driven (ghostty/src/apprt/embedded.zig looks up the physical key in input/keycodes.zig by entry.native == keycode), so it sees the original physical key and ignores the remap.

For Caps Lock to Backspace on Linux: GDK reports keyval = BackSpace, keycode = 66 (Caps physical). libghostty sees keycode 66, identifies it as Caps Lock, and treats the event as a modifier press rather than producing Backspace input.

Fix

canonicalKeycode(keyval, keycode) returns the Linux evdev+8 keycode that natively produces the given keyval for a small set of named editing/navigation keys. handleKeyEvent uses the canonical keycode when it differs and strips GHOSTTY_MODS_CAPS in that case so the remap source's Lock state doesn't leak into the event.

Repro

  1. KDE System Settings → Keyboard → Layouts → Advanced → "Caps Lock behaviour" → Make Caps Lock an additional Backspace (or any xkb option that remaps Caps to BackSpace).
  2. In Seance: pressing Caps Lock does nothing; real Backspace works.
  3. wev confirms sym: BackSpace, utf8: '\b' for the Caps press.
  4. With this patch: Caps acts as Backspace inside Seance.

Notes / questions for review

  • Scope. Limited to the named keys most likely to be remap targets (BackSpace, Tab, Return, KP_Enter, Escape, Delete, Insert, Home, End, PgUp/PgDn, arrows). I deliberately did not expand beyond what was needed to fix the reported case; happy to add F-keys etc. if you'd prefer.
  • Hardcoded keycodes. gdk_display_map_keyval would query GDK for keycodes that produce a given keyval and avoid the hardcoded table. I went with the table because it allocates nothing on a hot input path, the editing-key set is small and stable on Linux, and Seance is already Linux-only per build.zig. Open to switching if you'd prefer.
  • Alternative location. The same issue could be fixed inside libghostty (use keysym, not keycode, for non-modifier keys). The Seance-side fix is pragmatic; let me know if you'd rather see this upstream in your ghostty fork.
  • Tested manually with a release build under KDE Plasma 6 / Wayland on Bazzite. No automated tests touched.

Test plan

  • zig build succeeds
  • Caps Lock → Backspace works in patched Seance under KDE Wayland (Colemak layout)
  • Real Backspace still works
  • No regressions observed in regular typing, arrow keys, or modifier-letter shortcuts

GDK delivers (keyval, keycode) pairs where the keyval may have been
remapped via xkb (e.g. Caps Lock to BackSpace) while the keycode still
identifies the original physical key. libghostty's input handling is
keycode-driven, so the original physical key wins and the remap is
silently dropped.

Translate the keyval to the canonical evdev+8 keycode for known editing
keys before handing the event to libghostty, and clear the Lock-derived
CAPS modifier when the keycode is rewritten so the remap source does
not leak its lock state into the synthesized event.

Repro: bind Caps Lock to BackSpace in KDE; in Seance, Caps does nothing
even though wev reports `sym: BackSpace`. With this patch, Caps acts as
Backspace as expected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant