Skip to content

feat(terminal): enable IME input for CJK and composed text#73

Open
Anothers wants to merge 3 commits into
otty-shell:mainfrom
Anothers:feat/terminal-ime-input
Open

feat(terminal): enable IME input for CJK and composed text#73
Anothers wants to merge 3 commits into
otty-shell:mainfrom
Anothers:feat/terminal-ime-input

Conversation

@Anothers

Copy link
Copy Markdown

Problem

On Wayland, the terminal widget binds zwp_text_input_manager_v3 and creates a
zwp_text_input_v3 object, but it never enables it. Because the input method
is never enabled and the cursor area is never reported, the compositor never
routes composition events to the terminal. The practical effect is that any
composing input method — Chinese, Japanese, Korean, and other multi-keystroke
IMEs — cannot type into the terminal at all.

WAYLAND_DEBUG=1 on main shows the object being created but never enabled:

-> zwp_text_input_manager_v3@15.get_text_input(new id zwp_text_input_v3@19, wl_seat@8)
# ...no .enable(), no .set_cursor_rectangle() ever follow

Change

Enable the input method while the terminal is focused and handle the resulting
InputMethod events, entirely within otty-ui/terminal/src/view.rs:

  • Enable IME: request InputMethod::Enabled on every focused update,
    anchoring the candidate window to the terminal caret through the cursor
    Rectangle. It is re-requested each cycle because iced resets the input
    method state per cycle (same approach as iced's own text_input).
  • Commit: on InputMethod::Event::Commit, write the committed text to the
    PTY, reusing the existing Event::Write keyboard path.
  • Preedit: track the current preedit in TerminalViewState and surface it
    back via InputMethod::Enabled { preedit }, so the runtime renders the
    composition as an over-the-spot overlay.

Verification

On GNOME / Wayland with ibus, WAYLAND_DEBUG=1 now shows the previously-absent
calls, and Chinese text can be composed and typed into the terminal:

-> zwp_text_input_v3@19.enable()
-> zwp_text_input_v3@19.set_cursor_rectangle(...)
-> zwp_text_input_v3@19.commit()

Notes

The change is confined to input-method wiring in the terminal widget's
update/event handling; it adds no new business logic or dependencies. Happy to
adjust the preedit/cursor-rectangle handling or add coverage if you'd prefer a
different approach.

🤖 Generated with Claude Code

Anothers and others added 3 commits July 23, 2026 14:04
The terminal widget created a Wayland text-input object but never enabled
it, so the compositor never routed input method events to the terminal.
As a result, composing input methods (Chinese/Japanese/Korean and any other
multi-keystroke IME) could not type into the terminal at all on Wayland.

Enable the input method while the terminal is focused and handle the
resulting `InputMethod` events:

- Request `InputMethod::Enabled` on every focused update, anchoring the
  candidate window to the terminal caret via the cursor rectangle. It is
  re-requested each cycle because iced resets the input method state.
- Handle `InputMethod::Commit` by writing the committed text to the PTY,
  reusing the existing keyboard write path.

The composition string is shown by the platform IME's own candidate window
(`preedit: None`) rather than requesting an over-the-spot overlay, keeping
the change small and self-contained.

Verified on GNOME/Wayland with ibus: WAYLAND_DEBUG now shows
`zwp_text_input_v3.enable` and `set_cursor_rectangle`, which were entirely
absent before, and Chinese text can be typed into the terminal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Newer clippy flags the `&buf` argument to `debug!` as a redundant reference
(`-D warnings` then fails CI). Use inline formatting instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
crossbeam-epoch 0.9.18 (pulled in transitively via crossbeam-deque) is
affected by RUSTSEC-2026-0204. 0.9.20 is a patch-level bump that resolves
the advisory and restores `cargo deny check`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Anothers
Anothers force-pushed the feat/terminal-ime-input branch from b63f17c to b85de71 Compare July 23, 2026 06:04
@Anothers

Copy link
Copy Markdown
Author

Pushed an update (force-push, 3 commits):

1. feat(terminal) — the IME change, now also fixes a panic. The first revision requested an over-the-spot preedit overlay, which fed multi-byte (CJK) preedit ranges into the runtime's overlay renderer and panicked (iced_winit window.rs, reversed byte-range slice) while composing. It now leaves the composition string to the platform IME's own candidate window (preedit: None), which is smaller and sidesteps that path. Re-verified typing Chinese into the terminal on GNOME/Wayland + ibus.

2. fix(escape) + chore(deps) — the two red checks were pre-existing and unrelated to this change (both also fail on main). Included minimal fixes so CI can go green:

  • Lint: newer clippy flags a redundant & in otty-escape/src/osc.rs's debug! call.
  • cargo-deny: crossbeam-epoch 0.9.18 (transitive via crossbeam-deque) is hit by RUSTSEC-2026-0204; bumped to 0.9.20 (patch-level).

Happy to split those two into a separate PR if you'd rather keep this one focused on the terminal.

Verified locally: cargo clippy --workspace --all-targets --all-features -- -D warnings, cargo deny check, and cargo +nightly fmt --check all pass; the existing macOS/Ubuntu test jobs were already green.

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