fix(windows): restore keyboard focus for child webviews on window (re)activation#1755
Open
zendy00 wants to merge 1 commit into
Open
fix(windows): restore keyboard focus for child webviews on window (re)activation#1755zendy00 wants to merge 1 commit into
zendy00 wants to merge 1 commit into
Conversation
Contributor
Package Changes Through 2caef22There are 1 changes which include wry with minor Planned Package VersionsThe following package releases are the planned based on the context of changes in this pull request.
Add another change file through the GitHub UI by following this link. Read about change files or the docs at github.com/jbolda/covector |
…)activation After the host window loses and regains activation on Windows (Alt+Tab, clicking another window or the taskbar), keyboard input no longer reached WebView2 content until the user clicked inside the page — for webviews created with `build_as_child` (`is_child=true`), which is how Tauri's `unstable` multi-webview feature hosts even the main webview. Two compounding causes: 1. The focus-restoration subclass (`parent_subclass_proc` -> `MoveFocus`) was attached only `if !is_child`, so child webviews got no focus restoration at all. 2. On Alt+Tab-back, Windows routes focus directly to the WebView2 child window (`Chrome_WidgetWin_1`), so the top-level `WM_SETFOCUS` never fires and the existing `MoveFocus` remedy never runs. Fix: - Attach the subclass for the first webview per parent (`GetWindowSubclass` guard), regardless of `is_child`. Later children (e.g. browser tabs) don't overwrite it, and standard single-webview behavior is unchanged. - Add a `WM_ACTIVATE` arm that defers `MoveFocus` via a self-posted message (an immediate call is overridden by Windows' subsequent focus routing to the child). - Gate the `Drop`-time detach so only the installing webview removes the subclass, and re-seed focus when a non-owning child webview closes. Refs #1754 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
80d400d to
2caef22
Compare
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.
Addresses the
is_child=true/ multi-webview case of tauri-apps/tauri#15624.Problem
On Windows, after the host window loses and regains activation (Alt+Tab, clicking another window or the taskbar), keyboard input no longer reaches WebView2 content until the user clicks inside the page — for webviews created with
build_as_child(is_child=true), which is how Tauri'sunstablemulti-webview feature hosts even the main webview.Two compounding causes:
parent_subclass_proc→MoveFocus(PROGRAMMATIC)) is attached onlyif !is_child, so child webviews get no focus restoration at all.Chrome_WidgetWin_1), so the top-level'sWM_SETFOCUSnever fires and even the existingMoveFocusremedy never runs (the failure-mode-B path described in Windows accessibility regression: WebView2 content becomes unreadable and keyboard-unfocusable after the host window loses and regains activation tauri#15624).Fix
Single file (
src/webview2/mod.rs):GetWindowSubclassguard), regardless ofis_child. The main webview gets the handler; later children (e.g. additionalbuild_as_childwebviews / browser tabs) don't overwrite it; a standard single webview (!is_child) is also the first attach, so its behavior is unchanged.WM_ACTIVATEarm that defersMoveFocusvia a self-posted message. CallingMoveFocusimmediately inWM_ACTIVATEis overridden by Windows' subsequent focus routing to the child; deferring it until the message is dispatched re-seeds focus correctly. (App-side attempts to do this loop at ~140–200 Hz, as noted in Windows accessibility regression: WebView2 content becomes unreadable and keyboard-unfocusable after the host window loses and regains activation tauri#15624 — doing it natively in the subclass avoids that.)Drop-time detach so only the webview that installed the subclass removes it, and re-seed focus when a non-owning child webview closes (so closing abuild_as_childwebview / browser tab no longer tears down the main webview's focus handler or leaves focus unseeded).Verification
Manually verified on a Tauri 2.x app (wry 0.55.1, applied via
[patch.crates-io]) that uses theunstablemulti-webview feature — a terminal main webview plusbuild_as_childbrowser-tab webviews:Notes
reparent()detach/attach path is leftif !self.is_child(unchanged, out of scope here).WM_ACTIVATE'sLOWORD == WA_INACTIVE (0)is skipped, so this only re-seeds on activation.