Fix for Focus related issues at start up - #4501
Conversation
Fixes the potential of losing focus from actions like ALT-Tab, Clicking the Titlebar, opening and closing dialogs.
Fixes the focus error when application starts up. When an input has autofocus, the user should instantly be able to type.
WalkthroughAdds programmatic focus moves into WebView2 in two places on Windows: after navigation completes (if the window is visible and not minimized) and when the window is activated (WM_ACTIVATE). Both call the Chromium controller’s MoveFocus with PROGRAMMATIC when a controller exists. No public API changes. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant WinWindow as Windows Window
participant WebView as WebView2 Controller
User->>WinWindow: Activate window (WM_ACTIVATE)
alt Window becomes active and controller exists
WinWindow->>WebView: MoveFocus(PROGRAMMATIC)
end
sequenceDiagram
participant App
participant WinWindow as Windows Window
participant WebView as WebView2 Controller
App->>WinWindow: Navigation completes
alt StartHidden == false && WindowStartState != Minimized && controller exists
WinWindow->>WebView: MoveFocus(PROGRAMMATIC)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-10-17T23:16:11.570ZApplied to files:
🧬 Code graph analysis (1)v2/internal/frontend/desktop/windows/frontend.go (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
v2/internal/frontend/desktop/windows/frontend.go (1)
945-952: DRY the focus-transfer logic (shared with window.go).The same MoveFocus sequence is implemented here and in window.go. Centralize it in a small helper to keep behavior consistent and simplify future changes.
Example helper (place in a shared file in this package):
func focusWebView(chromium *edge.Chromium) { if chromium == nil { return } if ctrl := chromium.GetController(); ctrl != nil { if err := ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); err != nil { _ = ctrl.MoveFocus(0) chromium.Focus() } } }Then call:
- In navigationCompleted: focusWebView(f.chromium)
- In WM_ACTIVATE: focusWebView(w.chromium)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
v2/internal/frontend/desktop/windows/frontend.go(1 hunks)v2/internal/frontend/desktop/windows/window.go(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
v2/internal/frontend/desktop/windows/frontend.go (1)
v2/pkg/options/options.go (2)
WindowStartState(22-22)Minimised(27-27)
🔇 Additional comments (2)
v2/internal/frontend/desktop/windows/frontend.go (1)
945-952: Request validation across startup states and Windows versions.Please validate these scenarios to ensure no regressions:
- StartHidden=true (no focus push)
- WindowStartState=Minimised (no focus push)
- Maximised, Fullscreen, Frameless with/without decorations
- Activation via Alt+Tab and mouse click
- Older WebView2 runtimes/bindings (fallbacks exercised)
v2/internal/frontend/desktop/windows/window.go (1)
240-247: Confirm no focus churn or loops with OnSetFocus handler.Since OnSetFocus already calls chromium.Focus(), adding MoveFocus here might duplicate the effect. It should be harmless, but please verify no flicker or focus-loop occurs on activation.
| // Ensure initial keyboard focus goes into the WebView so typing works without a click. | ||
| if !f.frontendOptions.StartHidden && f.frontendOptions.WindowStartState != options.Minimised { | ||
| if ctrl := f.chromium.GetController(); ctrl != nil { | ||
| _ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) | ||
| // _ = ctrl.MoveFocus(0) | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add fallback and minimal error handling for MoveFocus to increase compatibility.
Some WebView2 versions/bindings may not support the PROGRAMMATIC constant or may return an error. Fall back to 0 (PROGRAMMATIC in the enum) and finally to Chromium.Focus() so initial typing reliably works.
- if ctrl := f.chromium.GetController(); ctrl != nil {
- _ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
- // _ = ctrl.MoveFocus(0)
- }
+ if ctrl := f.chromium.GetController(); ctrl != nil {
+ if err := ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); err != nil {
+ _ = ctrl.MoveFocus(0) // fallback: enum 0 is PROGRAMMATIC
+ f.chromium.Focus() // last-resort fallback
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Ensure initial keyboard focus goes into the WebView so typing works without a click. | |
| if !f.frontendOptions.StartHidden && f.frontendOptions.WindowStartState != options.Minimised { | |
| if ctrl := f.chromium.GetController(); ctrl != nil { | |
| _ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) | |
| // _ = ctrl.MoveFocus(0) | |
| } | |
| } | |
| // Ensure initial keyboard focus goes into the WebView so typing works without a click. | |
| if !f.frontendOptions.StartHidden && f.frontendOptions.WindowStartState != options.Minimised { | |
| if ctrl := f.chromium.GetController(); ctrl != nil { | |
| if err := ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); err != nil { | |
| _ = ctrl.MoveFocus(0) // fallback: enum 0 is PROGRAMMATIC | |
| f.chromium.Focus() // last-resort fallback | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In v2/internal/frontend/desktop/windows/frontend.go around lines 945 to 952,
replace the single MoveFocus call with a small fallback sequence: attempt
ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) and if it
returns an error (or is unsupported) retry with ctrl.MoveFocus(0); if that also
errors, call f.chromium.Focus() as a last resort; capture any returned errors
and log a minimal debug/warn message (or ignore if logger not available) but do
not panic — this increases compatibility across WebView2 versions and bindings.
There was a problem hiding this comment.
@creamy-corn - what do you make of the committable suggestion?
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
|
Thanks 🙏 Please could you add an entry to the changelog located at |
|
@creamy-corn - Any chance you could review the Rabbit's comments and add an entry to the changelog? Thanks 🙏 |
|
|
@creamy-corn ping 😄 |
|
|
Thanks for this focused fix. The remaining request was to review the comments and add the changelog entry, but there has been no recent update. I’m closing the PR for now to keep the queue current. Please reopen or reapply the change on the current branch if the issue is still present. |



Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
Type of change
Please select the option that is relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration using
wails doctor.If you checked Linux, please specify the distro and version.
Test Configuration
Please paste the output of
wails doctor. If you are unable to run this command, please describe your environment in as much detail as possible.Checklist:
website/src/pages/changelog.mdxwith details of this PRSummary by CodeRabbit