Skip to content

fix: route dead-key compose through IMContextSimple on Wayland#90

Open
manuacl wants to merge 1 commit into
am-will:mainfrom
manuacl:fix/issue-89-dead-key-compose-fallback
Open

fix: route dead-key compose through IMContextSimple on Wayland#90
manuacl wants to merge 1 commit into
am-will:mainfrom
manuacl:fix/issue-89-dead-key-compose-fallback

Conversation

@manuacl

@manuacl manuacl commented May 25, 2026

Copy link
Copy Markdown

Summary

  • On Plasma 6 Wayland without ibus/fcitx5, IMMulticontext's wayland slave claims AZERTY dead-key events (^, ¨, dead ~) over text-input-v3 and emits a preedit_changed with the bare glyph, but KWin never delivers the follow-up commit — 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).
  • Pair the existing IMMulticontext with a parallel GtkIMContextSimple and 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.
  • Extract the IME plumbing into a new limux-host-linux::ime module (TerminalImeState, factories, pure-logic routing helpers, 14 unit tests including 8 regression tests pinning the routing rules); terminal.rs sheds ~270 lines. Builds on PR fix: add IMContext for dead-key and compose-key support #20 / commit 536e6e9, which wired IMMulticontext but didn't cover the Wayland-default case.

Fixes #89.

Test plan

  • cargo fmt --check — green
  • cargo clippy --workspace --all-targets -- -D warnings — green
  • cargo test -p limux-host-linux — 190/190 pass, including 14 ime::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)
  • Manual: AZERTY ^ + 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)
  • Manual: AZERTY Shift+^ (¨) + eë
  • Manual: plain ASCII typing unaffected (echo hello)
  • Manual: Ctrl+C / Ctrl+F shortcuts 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)
  • Manual on a setup with ibus or fcitx5 actively typing CJK: not exercised locally — covered by the routing rule that keeps the multicontext as primary when no compose initiator is in play; reviewers with an IME daemon, please confirm

🤖 Generated with Claude Code

manuacl added a commit to manuacl/limux that referenced this pull request May 25, 2026
@manuacl manuacl force-pushed the fix/issue-89-dead-key-compose-fallback branch 2 times, most recently from 860d775 to cb86a45 Compare May 25, 2026 14:19
manuacl added a commit to manuacl/limux that referenced this pull request May 25, 2026
@manuacl manuacl force-pushed the fix/issue-89-dead-key-compose-fallback branch from cb86a45 to 2a2aca8 Compare May 25, 2026 14:56
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>
@manuacl manuacl force-pushed the fix/issue-89-dead-key-compose-fallback branch from 2a2aca8 to 730ca0a Compare May 26, 2026 08:04
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.

Dead-key compose (^/¨/dead ~) silently fails inside terminal panes on Plasma 6 Wayland

1 participant