What happened?
What happened?
Resize the host window, then start typing with a Korean IME. The in-progress composition is drawn in
a floating window at the top-left corner of the screen instead of at the caret. The committed text
still goes into the input correctly, it's only the composition that's displaced.
It doesn't sort itself out. It stays wrong until you move the window with the mouse, or click away to
another window and come back. Then the next resize does it again.
The input is a plain <input>. No canvas editor, no EditContext, nothing custom.
Edge and Chrome don't do this. Only WebView2.
Things I checked that turned out not to be it
Posting these so nobody has to redo them:
- The child windows keeping up with the parent.
Chrome_RenderWidgetHostHWND picks up the new
geometry 28ms after the parent resize. (Intermediate D3D Window takes ~1.2s, but that one has no
caret in it.)
- My app blocking the main thread and delaying a caret update. Longest frame gap over the two
seconds after a resize was 0ms.
- The page-side caret being in the wrong place. I logged the focused element's rect across resizes,
it tracks the caret and stays inside the window every time.
MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) after the resize. No effect.
NotifyParentWindowPositionChanged() after the resize. I called it ten times spread over
0-1100ms so the timing couldn't be the reason it missed. Still no effect.
It isn't specific to one UI framework either. The stock Tauri repro above keeps the default window
decorations, and #2241 reports the same thing from WinUI3. And since the browser doesn't do it but
WebView2 does, my guess is it sits in the hosting layer rather than the Chromium IME code they share.
I can't see inside the runtime to confirm that though.
If it helps as a starting point: in Chromium the caret position reaches TSF through
InputMethodWinTSF::OnCaretBoundsChanged -> TSFBridge::OnTextLayoutChanged ->
TSFTextStore::SendOnLayoutChange -> ITextStoreACPSink::OnLayoutChange. If that doesn't fire after
a host resize, GetTextExt would go on returning a stale rect or TS_E_NOLAYOUT, and a floating
composition window at the screen origin is what you'd expect to see. That's a guess, I haven't been
able to verify it.
Related
Checked the open bug list first. Closest ones, and why I filed separately:
If you think these are all one defect, feel free to fold this in. The repro and the checks above
should still be useful.
Importance
Moderate. My app's user experience is affected, but still usable.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
151.0.4129.86
SDK Version
webview2-com 0.38.2 (Rust bindings via Tauri 2.11.5 / wry 0.55.1)
Framework
Win32
Operating System
Windows 11
OS Version
10.0.26200
Repro steps
I hit this in my own app but it reproduces in a stock Tauri project, so there's no custom code involved:
pnpm create tauri-app imetest --template vanilla --manager pnpm --yes
cd imetest && pnpm install
pnpm tauri dev
Replace src/index.html with this, that's the whole page:
<!doctype html>
<html><head><meta charset="UTF-8" /></head>
<body style="padding:24px;font-family:system-ui">
<input style="width:90%;font-size:20px;padding:12px" />
</body></html>
Steps:
- Set the OS input method to a composition IME. I used the Korean Microsoft IME (0412).
- Click the input, type a syllable so a composition happens.
- Resize the window.
- Type again straight away. Don't press anything else first and don't move the mouse.
Expected: the composition appears at the caret.
Actual: it appears at the top-left corner of the screen, outside the window.
One thing worth knowing if you try to reproduce it: moving the mouse or clicking anywhere in the
window clears it. So if you do either between steps 3 and 4 you won't see it, and it looks like it
fixes itself after a moment. It doesn't. Hands off the keyboard and mouse, it stays wrong
indefinitely.
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
Don't know
Last working version (if regression)
n/a
No response
What happened?
What happened?
Resize the host window, then start typing with a Korean IME. The in-progress composition is drawn in
a floating window at the top-left corner of the screen instead of at the caret. The committed text
still goes into the input correctly, it's only the composition that's displaced.
It doesn't sort itself out. It stays wrong until you move the window with the mouse, or click away to
another window and come back. Then the next resize does it again.
The input is a plain
<input>. No canvas editor, no EditContext, nothing custom.Edge and Chrome don't do this. Only WebView2.
Things I checked that turned out not to be it
Posting these so nobody has to redo them:
Chrome_RenderWidgetHostHWNDpicks up the newgeometry 28ms after the parent resize. (
Intermediate D3D Windowtakes ~1.2s, but that one has nocaret in it.)
seconds after a resize was 0ms.
it tracks the caret and stays inside the window every time.
MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)after the resize. No effect.NotifyParentWindowPositionChanged()after the resize. I called it ten times spread over0-1100ms so the timing couldn't be the reason it missed. Still no effect.
It isn't specific to one UI framework either. The stock Tauri repro above keeps the default window
decorations, and #2241 reports the same thing from WinUI3. And since the browser doesn't do it but
WebView2 does, my guess is it sits in the hosting layer rather than the Chromium IME code they share.
I can't see inside the runtime to confirm that though.
If it helps as a starting point: in Chromium the caret position reaches TSF through
InputMethodWinTSF::OnCaretBoundsChanged->TSFBridge::OnTextLayoutChanged->TSFTextStore::SendOnLayoutChange->ITextStoreACPSink::OnLayoutChange. If that doesn't fire aftera host resize,
GetTextExtwould go on returning a stale rect orTS_E_NOLAYOUT, and a floatingcomposition window at the screen origin is what you'd expect to see. That's a guess, I haven't been
able to verify it.
Related
Checked the open bug list first. Closest ones, and why I filed separately:
a resize, it affects a composition that starts afterwards, and it lands at the screen origin rather
than staying where it was. Moving the window is one of the things that fixes mine.
If you think these are all one defect, feel free to fold this in. The repro and the checks above
should still be useful.
Importance
Moderate. My app's user experience is affected, but still usable.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
151.0.4129.86
SDK Version
webview2-com 0.38.2 (Rust bindings via Tauri 2.11.5 / wry 0.55.1)
Framework
Win32
Operating System
Windows 11
OS Version
10.0.26200
Repro steps
I hit this in my own app but it reproduces in a stock Tauri project, so there's no custom code involved:
Replace
src/index.htmlwith this, that's the whole page:Steps:
Expected: the composition appears at the caret.
Actual: it appears at the top-left corner of the screen, outside the window.
One thing worth knowing if you try to reproduce it: moving the mouse or clicking anywhere in the
window clears it. So if you do either between steps 3 and 4 you won't see it, and it looks like it
fixes itself after a moment. It doesn't. Hands off the keyboard and mouse, it stays wrong
indefinitely.
Repros in Edge Browser
No, issue does not reproduce in the corresponding Edge version
Regression
Don't know
Last working version (if regression)
n/a
No response