1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! IME state registry + per-element composition state.
//!
//! The registry mirrors the [`FocusRegistry`](crate::focus::FocusRegistry)
//! lifecycle: cleared at the start of every prepaint, re-registered per
//! ime-capable element during the prepaint walk, then `prune_missing`
//! collapses any state belonging to unmounted elements.
//!
//! # Cache-then-query
//!
//! The platform `WindowImeDelegate` query channel does NOT traverse the
//! registry directly. Instead, `AppState` republishes a snapshot
//! ([`CachedImeQuery`]) at deterministic points (end of `dispatch_ime_preedit`,
//! end of every paint), and the delegate methods read that cache only. The
//! registry is the source of truth; the cache is the safe read path.
//!
//! # Per-element state
//!
//! Each ime-capable element owns one [`ImeState`] held inside an `Rc<RefCell<_>>`
//! so per-element handlers can mutate it without re-borrowing the registry
//! while the dispatch loop holds a registry-level borrow.
pub use ;
pub use ImeRegistry;
pub use ;
// ---------------------------------------------------------------------------
// Display caret affinity + byte helpers (shared by TextField + TextArea)
// ---------------------------------------------------------------------------
/// Caret affinity to use when resolving the display caret-x.
///
/// During an active IME composition the caret must bind [`Affinity::Downstream`]
/// regardless of the stored seam affinity: a preedit splices new text at the
/// caret, so the pre-composition Upstream/Downstream choice belongs to the
/// committed caret, not the preedit-shifted display caret. Re-applying the stale
/// value double-shifts the caret across an LTR↔RTL boundary. Outside composition
/// the stored affinity (set by visual ←/→ motion as it crosses a seam) is
/// authoritative.
///
/// Shared by the TextField and TextArea paint paths so the invariant lives in
/// one place — see [`crate::elements::text_field`] and
/// [`crate::elements::text_area`].
///
/// [`Affinity::Downstream`]: slate_text::Affinity::Downstream
pub
/// Byte index the caret is painted at, given the display caret (the committed
/// caret, or the preedit's start byte during composition) and the active
/// preedit.
///
/// During composition the visible caret binds to the IME cursor *inside* the
/// preedit — where the next keystroke lands — not to the start of the composed
/// run. Without this the caret stays pinned at the composition start for the
/// whole session and only jumps once it commits, so it never visibly advances
/// as you type (most visible with multi-glyph CJK/Vietnamese composition). The
/// offset is clamped into the preedit text so a misreporting backend can't push
/// the caret past the composed run. Outside composition this is just the
/// display caret.
///
/// Shared by the TextField and TextArea paint paths so the invariant lives in
/// one place — see [`crate::elements::text_field`] and
/// [`crate::elements::text_area`].
pub