MicrosoftEdge / MicrosoftEdge/WebView2Feedback
[Problem/Bug]: IME composition window jumps to the top-left of the screen after the host window is resized
Nobody has claimed this yet.
- Dominant language
- PowerShell
- Stars
- 526
- Forks
- 67
- PR merge metrics
- No merged PRs in 30d
Description
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_RenderWidgetHostHWNDpicks up the new
geometry 28ms after the parent resize. (Intermediate D3D Windowtakes ~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:
- #1611 is about an already-open candidate window not following when the window is moved. Mine is
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. - #2241 is the same family from WinUI3, but there's no trigger or repro on it.
- #5570 is IME candidate position in composition mode over RDP.
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
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce with the stock Tauri app, replacing src/index.html with the minimal input page and following the Korean IME resize steps. Start by tracing Chromium’s InputMethodWinTSF::OnCaretBoundsChanged through TSFBridge::OnTextLayoutChanged, TSFTextStore::SendOnLayoutChange, and ITextStoreACPSink::OnLayoutChange. Done means a composition started after resizing is positioned at the caret without moving the window or changing focus.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, tauri
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100