fix(ui): anchor the host cursor to modal name inputs - #2569
Conversation
IMEs draw their composition preview at the host terminal cursor. The rename and new-worktree dialogs drew a block glyph instead of setting one, so the frame carried no cursor and the client kept the position the focused pane last reported. Japanese composition appeared behind the dialog and only reached the field on Enter. Set the cursor to the caret column instead, counting wide characters as two cells. refs herdrdev#1755
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe change adds shared cursor-aware rendering for name inputs. Rename and linked-worktree overlays use the renderer. Tests cover cursor placement, display widths, bounds clamping, and cursor propagation. ChangesName input cursor rendering
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
A name that fills the field left the clamped caret sitting on the last rendered glyph. A terminal inverts the cell under its cursor and an IME composes there, so the glyph was hidden and composition overlapped it. Render the text one column short of the field. The field is still cleared in full, so the clamped caret always lands on a blank cell. refs herdrdev#1755
Greptile SummaryThe PR replaces block-glyph carets in rename and new-worktree name fields with an explicit host-terminal cursor, positioning it by display width and clamping it within the field.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/ui/dialogs.rs | Centralizes modal name-field rendering and anchors the host cursor to the width-aware, bounded input caret with focused regression tests. |
Reviews (4): Last reviewed commit: "Merge branch 'master' into fix/ime-ancho..." | Re-trigger Greptile
|
This is exactly the fix Chinese/Japanese users are waiting for — on Linux with herdr 0.8.0 stable, typing with an IME in the tab/workspace rename dialog shows no composition preview and no cursor, so CJK users type blind. Our team hit this immediately. Would love to see this merged and shipped. Happy to test the fix once it lands in a release (or on a preview build). |
|
ty! |
|
thanks for the quick merge! |
Problem
With a rename dialog or the new-worktree dialog open, typing Japanese with an
IME shows the composition preview behind the dialog, at the cursor the focused
pane last reported. The text still lands in the field on Enter, so only the
composition phase is affected — CJK users type blind.
Cause
render_rename_overlayandrender_new_linked_worktree_overlaypainted thecaret as a
█glyph and never calledframe.set_cursor_position. The focusedpane does not supply one either —
tab_surface_cursorreturnsNoneoutsideMode::Terminal— so the frame left the server with no cursor at all(
Terminal::drawhides the cursor in that case, which clears the trackingbackend's
rendered_cursor).resolve_host_cursor_statethen falls back tolast_visible_cursorand emits CUP to where the pane last had it withvisible: false: the position still moves, so the IME composes behind thedialog.
Fix
render_name_input_field, shared by both dialogscolumn is
input_rect.x + 1 + display_width_u16(&name_input), so widecharacters advance it two cells
inside it
The
█goes away because the dialog now shows the host terminal's own cursor.A terminal draws that cursor by inverting the cell under it, so leaving a full
block there would flatten it into a solid cell. One consequence worth naming:
the emitted
CursorStatecarriesshape: 0, which resets DECSCUSR, so thecaret takes the terminal's default shape, blink and colour instead of the old
steady
palette.textblock. Clients that paint the cursor into frame cells(
draw_host_cursor, the Windows default) still get a steady block throughframe_with_drawn_cursor.The issue names the rename and new-tab dialogs. The new-worktree dialog reads
the same
name_inputthrough the same missing call, so it gets the same fix.Same approach as #2468, arrived at independently; that one kept the
█anddid not cover the new-worktree dialog.
One edge is left alone:
render_stream.rsprefers a visible popup pane's cursorover the frame cursor, so a modal rendered over a popup would still lose its
caret. That state is currently unreachable — opening a popup forces
Mode::Terminal, and while it is open every key and mouse event is routed tothe popup.
Not fixed here, and visible to the same users: for halfwidth voiced kana
(
ガ,ギ) the field text itself renders wrong.Paragraphpacks the graphemeinto one cell while
cell_widthtreats it as two, sowrite_all_cellsskipsthe following cell. That predates this change and no caret arithmetic can line
up while it stands.
Docs
No public docs change needed; no documented command, config key, or keybinding
changes.
Verification
IME: with the rename dialog open, composition now appears at the input caret
instead of behind the dialog
characters, the clamp boundary at 51 / 53 / 200 columns, the cell under the
caret being blank, all three rename modes, and the resolved
CursorStatetheserver would send. All six fail when the
set_cursor_positioncall is removedjust lint(cargo fmt --check,cargo clippy --all-targets --locked -- -D warnings)cargo nextest run --locked --no-fail-fast -E 'all()': 3,188 run, 3,185passed, 3 failed —
pane_spawn_cwd_fallback_in_server,live_handoff_keeps_unmanaged_agent_name_bound_to_saved_session, andmulti_client_client_crash_sigkill_does_not_affect_serverfail identically ona clean master checkout on this machine
just integration-assets-test(4 pass) andjust plugin-marketplace-test(31 pass)
refs #1755