fix(tao): follow the caret with the Windows IME candidate window - #573
Draft
kdroidFilter wants to merge 1 commit into
Draft
fix(tao): follow the caret with the Windows IME candidate window#573kdroidFilter wants to merge 1 commit into
kdroidFilter wants to merge 1 commit into
Conversation
`PlatformContext.startInputMethod` was implemented only on the macOS Tao host. Compose's default is `awaitCancellation()` with no IME spot, so on Windows the candidate list, and the OS-drawn composition string, stayed wherever the native window default put them — typically the client area's top-left corner — instead of following the focused field. `WindowsTaoPlatformContext` now keeps an input session for the focused `BasicTextField` and pushes `focusedRectInRoot()` to IMM32 through the new `nativeSetImeRect`. Tao's own `set_ime_position` only sets a `COMPOSITIONFORM`, which positions the inline composition window; the candidate list is placed from the `CANDIDATEFORM`, so we set both — the caret box becomes a `CFS_EXCLUDE` area so the candidate list never covers the text being edited. The caret rect is clamped to `textClippingRectInRoot()`: it is root-relative and goes negative once the field scrolls out of the viewport, which would fling the candidate window off the window. A clamp rather than `Rect.intersect`, because a caret rect can legitimately be zero-width and no overlap test accepts a degenerate rect. `nativeCancelImeComposition` drops any in-flight composition when the session ends, so a pending candidate window does not linger over unfocused content nor commit into whatever gains focus next. No coordinate conversion is needed: the scene covers the whole client area — the custom title bar is drawn inside it and reports no platform inset — so scene-root physical pixels are already client pixels. Linux is unchanged; #558 stays open for the GTK / Wayland text-input side. Also refreshes two example API baselines that had drifted (Compose lambda name hashes in rect-stress-demo, plus a first dump for widget-demo).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Windows half of #558. Linux is untouched — the issue stays open for the GTK / Wayland text-input side.
Summary
WindowsTaoPlatformContextnow overridesstartInputMethodthe way the macOS host does: it keeps an input session for the focusedBasicTextFieldand pushesfocusedRectInRoot()to IMM32. Compose's default isawaitCancellation()with no IME spot, which is why the candidate list — and the OS-drawn composition string — sat at the client area's top-left instead of on the caret.platform/windows/ime.rsexposesnativeSetImeRect, setting both IMM32 forms. Tao's ownset_ime_positiononly sets aCOMPOSITIONFORM, which positions the inline composition window; the candidate list is placed from theCANDIDATEFORM. The caret box is passed as aCFS_EXCLUDEarea so the candidate list never covers the text being edited, and both forms anchor at the caret's top-left (same as winit and as Tao'sset_ime_position_physical) so the composition string stays on the caret's line.nativeCancelImeCompositiondrops any in-flight composition when the input session ends, so a pending candidate window does not linger over unfocused content nor commit into whatever gains focus next.textClippingRectInRoot(). It is root-relative and goes negative once the field scrolls out of the viewport, which would fling the candidate window off the window. A clamp rather thanRect.intersect+overlaps, because a caret rect can legitimately be zero-width and no overlap test accepts a degenerate rect.Win32_UI_Input_Imefeature to thewindowscrate.No coordinate conversion is needed: the scene covers the whole client area — the custom title bar is drawn inside it and reports no platform inset — so scene-root physical pixels are already client pixels. Both new externs are Java→native only, so no GraalVM reachability metadata is required.
Also refreshes two example API baselines that had drifted (Compose lambda name hashes in
rect-stress-demo, plus a first dump forwidget-demo). Unrelated to the fix, carried along from anapiDump.Test plan
cargo build --release --target x86_64-pc-windows-msvcclean, no new warningsbuild.batproduces win32-x64 + win32-aarch64 DLLs; both JNI symbols exportedcompileKotlin,ktlintCheck,detekt,apiCheckpassUnsatisfiedLinkErrorBasicTextFieldin tao-demo, typenihao/konnichiha— the candidate window sits under the caret and follows it when the window moves or resizesMarked draft: the IMM32 behaviour above still needs a run on a machine with a CJK IME installed.