From 6172275252f5f724d874163462f5394800f8d55b Mon Sep 17 00:00:00 2001 From: ChihGodlee <61595521+ChihGodlee@users.noreply.github.com> Date: Wed, 20 May 2026 20:05:38 +0800 Subject: feat(experimental): add reveal_hidden_cursor_for_cjk_ime opt-in for CJK IME tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the focused pane requests ?25l (cursor hidden) but paints its own cursor — common in TUIs like Claude Code, pi, and codex — macOS native input methods stop tracking the candidate-window position. CJK users (Chinese / Japanese / Korean) cannot see candidate windows follow as they type. Setting [experimental] reveal_hidden_cursor_for_cjk_ime = true exposes the focused pane's cursor anchor to the outer terminal regardless of the pane's hidden-cursor request, restoring IME tracking for CJK input. [experimental] cjk_ime_agents is an optional allow-list. When empty, the reveal applies to any focused pane. When non-empty (e.g. ["claude", "codex"]), the reveal only applies if the focused pane's detected agent matches one of the listed names. This lets users enable the workaround only for AI-agent TUIs that paint their own cursor, leaving plain shells and other programs untouched. Accepted names: pi, claude, codex, gemini, cursor, cline, opencode, copilot, kimi, kiro, droid, amp, grok, hermes. Unknown names are ignored. When the pane reports no cursor position (cursor_state returns None for some TUIs), the anchor falls back to the pane's top-left so a stable IME hint is always available. [experimental] cjk_ime_cursor_shape (default "steady_block") controls the DECSCUSR shape rendered for the revealed cursor; six variants are accepted: block, steady_block, underline, steady_underline, bar, steady_bar. Trade-off when enabled: a hardware cursor will be visible in the outer terminal for apps that hide the cursor without painting a replacement. Default false preserves the behavior set in 2c95071. Pair the reveal with cjk_ime_agents to scope it to specific TUIs. Manually verified on macOS 26.5 aarch64 with system Pinyin IME against Claude Code: candidate window tracks cursor with flag enabled, returns to anchored-at-start behavior with flag disabled. refs #149 --- src/app/state.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/app/state.rs') diff --git a/src/app/state.rs b/src/app/state.rs index 7ee79c4a..1566fdeb 100644 --- a/src/app/state.rs +++ b/src/app/state.rs @@ -965,6 +965,14 @@ pub struct AppState { pub confirm_close: bool, pub prompt_new_tab_name: bool, pub show_agent_labels_on_pane_borders: bool, + /// Expose the focused pane's cursor anchor to the outer terminal even when + /// the pane requested `?25l`. See `[experimental] reveal_hidden_cursor_for_cjk_ime`. + pub reveal_hidden_cursor_for_cjk_ime: bool, + /// Restrict cursor reveal to focused panes whose detected agent matches + /// one of these. Empty means apply to any focused pane. + pub cjk_ime_agents: Vec, + /// DECSCUSR shape parameter (1–6) for the IME anchor cursor. + pub cjk_ime_cursor_shape: u8, pub kitty_graphics_enabled: bool, pub default_shell: String, pub pane_scrollback_limit_bytes: usize, @@ -1224,6 +1232,9 @@ impl AppState { confirm_close: true, prompt_new_tab_name: true, show_agent_labels_on_pane_borders: false, + reveal_hidden_cursor_for_cjk_ime: false, + cjk_ime_agents: Vec::new(), + cjk_ime_cursor_shape: 2, // steady_block kitty_graphics_enabled: false, default_shell: String::new(), pane_scrollback_limit_bytes: crate::config::DEFAULT_SCROLLBACK_LIMIT_BYTES, -- cgit v1.2.3