fix: route dead-key compose through IMContextSimple on Wayland#90
Conversation
860d775 to
cb86a45
Compare
cb86a45 to
2a2aca8
Compare
GTK4's IMMulticontext defaults to the "wayland" slave on Plasma 6
Wayland sessions that don't have ibus or fcitx5 running. That slave
claims dead-key events over text-input-v3 (filter_keypress returns
true and a preedit_changed signal fires with the bare dead-key glyph),
but KWin/Plasma 6 never delivers the follow-up commit. The dead-key
glyph flashes on screen, the follow-up key is consumed too, and the
composed character never appears. AZERTY users get raw `^e` instead
of `ê`.
Pair the existing IMMulticontext with a GtkIMContextSimple fallback
that drives libxkbcommon's compose tables in-process. When the
incoming keysym is a compose initiator (XK_dead_*, Multi_key) or the
fallback is already mid-compose, bypass the multicontext entirely so
KWin can't intercept the event; otherwise the multicontext keeps
priority so ibus / fcitx5 / CJK IMEs continue to work.
The IME plumbing lives in a new limux-host-linux::ime module split
into three submodules so pure logic is testable in isolation from
the GTK wiring:
ime/state.rs TerminalImeState machine + 6 unit tests
ime/routing.rs decide_routing, is_compose_initiator,
update_latch_after_fallback_first + 8 unit tests
ime/contexts.rs PaneIme, GTK signal wiring, ghostty FFI helpers
terminal.rs sheds ~270 lines. Regression tests pin the routing rules
(initiator and in-flight compose route to fallback first; plain keys
route to the multicontext first; the latch arms / disarms / stays
put under the expected fallback responses) and include a full
state-machine trace of the `^` + `e` → `ê` sequence.
A CLAUDE.md anchor entry points at the new module and a Pitfalls
entry warns against routing dead-key events through IMMulticontext
alone on Wayland.
Builds on the partial fix from PR am-will#20 (commit 536e6e9), which wired
IMMulticontext but did not cover the Wayland-default case.
Fixes am-will#89
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2a2aca8 to
730ca0a
Compare
|
Thank you for the excellent write-up and implementation here. I landed this on The merged fix preserves your core approach: Could you please test the next Limux release on your Plasma 6 Wayland/AZERTY setup and confirm the dead-key cases are fixed? Thanks again for chasing this down. |
Summary
IMMulticontext'swaylandslave claims AZERTY dead-key events (^,¨, dead~) overtext-input-v3and emits apreedit_changedwith the bare glyph, but KWin never delivers the follow-upcommit— the dead-key glyph flashes on screen and the compose silently aborts (Dead-key compose (^/¨/dead ~) silently fails inside terminal panes on Plasma 6 Wayland #89).IMMulticontextwith a parallelGtkIMContextSimpleand bypass the multicontext entirely for compose initiators (XK_dead_*,Multi_key) and in-flight compose sequences, so libxkbcommon's compose tables run in-process and KWin can't intercept; otherwise the multicontext keeps priority so ibus / fcitx5 / CJK IMEs continue to work.limux-host-linux::imemodule (TerminalImeState, factories, pure-logic routing helpers, 14 unit tests including 8 regression tests pinning the routing rules);terminal.rssheds ~270 lines. Builds on PR fix: add IMContext for dead-key and compose-key support #20 / commit 536e6e9, which wiredIMMulticontextbut didn't cover the Wayland-default case.Fixes #89.
Test plan
cargo fmt --check— greencargo clippy --workspace --all-targets -- -D warnings— greencargo test -p limux-host-linux— 190/190 pass, including 14ime::tests::*(5 state-machine traces, 4 routing-decision regressions, 3 latch-transition regressions, 1 compose-initiator detection table, 1 full^+e→êend-to-end trace)^+e→êinside a terminal pane on Bazzite Plasma 6 Wayland (the reproducer from Dead-key compose (^/¨/dead ~) silently fails inside terminal panes on Plasma 6 Wayland #89)Shift+^(¨) +e→ëecho hello)Ctrl+C/Ctrl+Fshortcuts still reach their handlers; pressing^alone does not open the search bar (the regression PR fix: add IMContext for dead-key and compose-key support #20 fixed)🤖 Generated with Claude Code