Skip to content

ghostel-mode: bind clipboard media keys (XF86Paste/Copy/Cut)#134

Merged
dakra merged 1 commit intodakra:mainfrom
Cianidos:fix/xf86-clipboard-keys
Apr 18, 2026
Merged

ghostel-mode: bind clipboard media keys (XF86Paste/Copy/Cut)#134
dakra merged 1 commit intodakra:mainfrom
Cianidos:fix/xf86-clipboard-keys

Conversation

@Cianidos
Copy link
Copy Markdown
Contributor

Problem

Linux keyboards with dedicated clipboard keys emit <XF86Paste>,
<XF86Copy>, and <XF86Cut>. Without explicit bindings on
ghostel-mode-map, they fall through to the global map and run the
vanilla Emacs commands — which gives the wrong result inside a live
terminal:

  • yank inserts into the Emacs buffer; the next libghostty redraw
    overpaints the viewport, so the paste silently disappears.
  • kill-region deletes text that the next redraw re-paints anyway,
    so cut looks like a no-op — while populating the kill ring with
    text the user didn't actually want to remove.

By contrast, keyboards with Cmd-based clipboard keys already work
because the darwin block binds s-vghostel-yank.

Reproduction

On a Linux session with a keyboard that emits XF86 media keys, focus a
ghostel buffer, put something in the kill ring, and press the hardware
Paste key. Nothing reaches the shell; a brief flicker of the pasted
text may appear in the Emacs buffer before the next redraw.

Fix

Bind the three XF86 clipboard keys explicitly on ghostel-mode-map:

  • <XF86Paste>ghostel-yank (mirrors C-y and darwin s-v).
  • <XF86Copy>kill-ring-save (region from the buffer to kill ring).
  • <XF86Cut>kill-ring-save (live terminal output can't really
    be cut; degenerating to copy matches native ghostty).

@dakra
Copy link
Copy Markdown
Owner

dakra commented Apr 18, 2026

Thanks.
I want to think about this for a bit.
Maybe we find another solution that "just works"?
Also maybe for cut we could hack something together like in evil mode aka yank the text and then send X-times (where X is length of the selection). or something like this.

(Maybe it's all not worth it and I'll merge this anyway.. but just leaving it open for a bit)

@Cianidos
Copy link
Copy Markdown
Contributor Author

Thanks for taking the time to think it through. A few notes on the
design trade-offs, in case they help:

vterm vs ghostel keymap model. vterm forwards-by-default: anything
not captured by Emacs reaches the PTY, so XF86Paste "just works"
incidentally. Ghostel's ghostel-mode-map is the opposite — every
forwarded key is explicitly bound, with ghostel-keymap-exceptions
as an opt-in channel for Emacs-native keys. That's what lets evil,
kitty-protocol dispatch, copy-mode, and s-v/C-y all integrate
cleanly. A catch-all "unknown key → PTY" fallback would be a
regression of that design contract (collisions with user-rebound
Emacs keys, future keycodes silently swallowed, etc.), so I suspect
it's not the direction you want either.

Given that, the natural "just works" path is the darwin pattern
already in the keymap (s-vghostel-yank) — extending it to the
Linux-equivalent XF86 keys. That's what this PR does.

On cut. The evil-ghostel--around-delete trick (yank text, send
N backspaces) works because an evil visual selection always
corresponds to the current terminal input-line. A generic
<XF86Cut> in ghostel-mode has no such guarantee — the region can
span scrollback, past prompts, tool output — and backspaces can't
"undo" that on the shell side. Native terminals (ghostty, iTerm2,
Alacritty) all degenerate cut to copy for the same reason, which is
why I went with that. If you'd rather leave <XF86Cut> unbound and
ship only Paste + Copy, I'm happy to drop it — let me know.

Route <XF86Paste> through ghostel-yank (mirroring C-y and darwin s-v)
and map <XF86Copy> to kill-ring-save. Without explicit
bindings these fall through to the global yank/kill-region, which
write to the Emacs buffer and get overpainted by the next redraw.
@dakra dakra force-pushed the fix/xf86-clipboard-keys branch from 28b8c8b to 65932e6 Compare April 18, 2026 22:34
@dakra dakra merged commit 65932e6 into dakra:main Apr 18, 2026
14 checks passed
@dakra
Copy link
Copy Markdown
Owner

dakra commented Apr 18, 2026

I just removed the cut for now like you suggested.
Think this is the most pragmatic approach now. We can always change if we find some other solution.
Thanks.

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.

2 participants