mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
fix(input): anchor the IME candidate window at the fake caret, not the parked cursor (#275)
Cursor-hiding TUIs (Kimi CLI, Ink apps) draw their caret as a reverse-video cell and leave the real cursor wherever the frame's last write ended — for Kimi that is the input box's right border, and the IME candidate list was stranded there. When the cursor is hidden and its row holds exactly one caret-sized inverse run, snap the IME anchor (and the marked-text preview) to that run; rendering is untouched. The gpui side (bumped here) now also answers IMR_QUERYCHARPOSITION — the query the Windows 11 Microsoft Pinyin IME uses instead of CANDIDATEFORM — and re-anchors the candidate window on every WM_IME_COMPOSITION. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
l0ng-ai
co-authored by
Claude Fable 5
parent
9fd84bf555
commit
b8dc38fb98
Generated
+25
-25
@@ -1459,7 +1459,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"gpui_util",
|
||||
"indexmap",
|
||||
@@ -2023,7 +2023,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "derive_refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3182,7 +3182,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.2.2"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"anyhow",
|
||||
@@ -3373,7 +3373,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_linux"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_unix",
|
||||
@@ -3424,7 +3424,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_macos"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_macos",
|
||||
@@ -3471,7 +3471,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -3482,7 +3482,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_platform"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"gpui",
|
||||
@@ -3495,7 +3495,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_shared_string"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
@@ -3505,7 +3505,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"log",
|
||||
@@ -3514,7 +3514,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_web"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"console_error_panic_hook",
|
||||
@@ -3538,7 +3538,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_wgpu"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytemuck",
|
||||
@@ -3567,7 +3567,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_windows"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_windows",
|
||||
@@ -3886,7 +3886,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-compression",
|
||||
@@ -3911,7 +3911,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client_tls"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-platform-verifier",
|
||||
@@ -5039,7 +5039,7 @@ checksum = "7ebb8d8732c6a6df3d8f032a82911cfc747e00efb95cc46e8d0acd5b5b88570c"
|
||||
[[package]]
|
||||
name = "media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen",
|
||||
@@ -6143,7 +6143,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
[[package]]
|
||||
name = "perf"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"collections",
|
||||
"serde",
|
||||
@@ -7116,7 +7116,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"derive_refineable",
|
||||
]
|
||||
@@ -7159,7 +7159,7 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
||||
[[package]]
|
||||
name = "reqwest_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -7693,7 +7693,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "scheduler"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"backtrace",
|
||||
@@ -8506,7 +8506,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
[[package]]
|
||||
name = "sum_tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"heapless",
|
||||
"log",
|
||||
@@ -9971,7 +9971,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
[[package]]
|
||||
name = "util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs",
|
||||
@@ -10010,7 +10010,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "util_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"perf",
|
||||
"quote",
|
||||
@@ -11825,7 +11825,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "zlog"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
@@ -11870,7 +11870,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ztracing"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
@@ -11881,7 +11881,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ztracing_macro"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#3aac3ef3a1411d539c32610ed29e399ef1d3b0ae"
|
||||
source = "git+https://github.com/l0ng-ai/zed?branch=tty7#faeb8732b2ae508022740505a27222d2f61ece5f"
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
|
||||
+37
-4
@@ -716,6 +716,9 @@ fn paint_glyphs(
|
||||
struct GridCursor {
|
||||
row: usize,
|
||||
col: usize,
|
||||
// Where the IME candidate window should anchor: the fake caret drawn by
|
||||
// cursor-hiding TUIs when one is identifiable, else `col`.
|
||||
ime_col: usize,
|
||||
hidden: bool,
|
||||
style: crate::core::config::CursorStyle,
|
||||
}
|
||||
@@ -859,12 +862,36 @@ impl TerminalElement {
|
||||
history_size = term.grid().history_size();
|
||||
let selection = content.selection;
|
||||
|
||||
let cur = content.cursor;
|
||||
let cursor_row = cur.point.line.0 + display_offset;
|
||||
let cursor_hidden = matches!(cur.shape, CursorShape::Hidden);
|
||||
// TUIs that hide the hardware cursor (Kimi CLI, Ink apps) draw
|
||||
// their own caret as a reverse-video cell and park the real
|
||||
// cursor wherever the frame's last write ended, which strands
|
||||
// the IME candidate window there (#275). A lone short inverse
|
||||
// run on the cursor's row is that fake caret; collect runs so
|
||||
// the IME anchor can snap to it.
|
||||
let mut inverse_runs: Vec<(usize, usize)> = Vec::new();
|
||||
|
||||
for cell in content.display_iter {
|
||||
let row = cell.point.line.0 + display_offset;
|
||||
let col = cell.point.column.0;
|
||||
if row < 0 || row as usize >= rows || col >= cols {
|
||||
continue;
|
||||
}
|
||||
if cursor_hidden
|
||||
&& row == cursor_row
|
||||
&& cell.cell.flags.contains(Flags::INVERSE)
|
||||
&& !cell
|
||||
.cell
|
||||
.flags
|
||||
.intersects(Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER)
|
||||
{
|
||||
match inverse_runs.last_mut() {
|
||||
Some((start, len)) if *start + *len == col => *len += 1,
|
||||
_ => inverse_runs.push((col, 1)),
|
||||
}
|
||||
}
|
||||
let rc = snapshot_cell(cell.cell, cell.point, &palette, colors, selection.as_ref());
|
||||
any_selected |= rc.selected;
|
||||
buf[row as usize * cols + col] = rc;
|
||||
@@ -891,14 +918,20 @@ impl TerminalElement {
|
||||
sliver = Some(row_buf);
|
||||
}
|
||||
|
||||
let cur = content.cursor;
|
||||
let row = cur.point.line.0 + display_offset;
|
||||
let row = cursor_row;
|
||||
let col = cur.point.column.0;
|
||||
if row >= 0 && (row as usize) < rows && col < cols {
|
||||
// Snap the IME anchor to the fake caret when there is
|
||||
// exactly one caret-sized inverse run on the row.
|
||||
let ime_col = match inverse_runs.as_slice() {
|
||||
[(start, len)] if cursor_hidden && *len <= 2 => *start,
|
||||
_ => col,
|
||||
};
|
||||
cursor = Some(GridCursor {
|
||||
row: row as usize,
|
||||
col,
|
||||
hidden: matches!(cur.shape, CursorShape::Hidden),
|
||||
ime_col,
|
||||
hidden: cursor_hidden,
|
||||
style: cursor_style_from_shape(cur.shape),
|
||||
});
|
||||
}
|
||||
@@ -1238,7 +1271,7 @@ impl Element for TerminalElement {
|
||||
let cursor = snap.cursor;
|
||||
let sliver = snap.sliver.as_ref();
|
||||
|
||||
let cursor_cell = cursor.map(|c| (c.row, c.col));
|
||||
let cursor_cell = cursor.map(|c| (c.row, c.ime_col));
|
||||
let render_cursor = cursor
|
||||
.filter(|c| !c.hidden)
|
||||
.map(|c| (c.row, c.col, c.style));
|
||||
|
||||
Reference in New Issue
Block a user