-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Fix for Focus related issues at start up #4501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
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.
WalkthroughImplements programmatic focus transfer into the WebView2 after navigation completion and upon window activation on Windows. Uses the Chromium controller’s MoveFocus with PROGRAMMATIC reason when available, guarded by nil checks. 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
WinWindow->>WebView: MoveFocus(PROGRAMMATIC)
end
sequenceDiagram
participant App
participant WinWindow as Windows Window
participant WebView as WebView2 Controller
App->>WinWindow: Navigation completes
alt Window visible and not minimized
WinWindow->>WebView: MoveFocus(PROGRAMMATIC)
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.2.2)Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/product/migration-guide for migration instructions ✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@creamy-corn - what do you make of the committable suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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!
if w.isActive && w.chromium != nil { | ||
if ctrl := w.chromium.GetController(); ctrl != nil { | ||
// Push keyboard focus into WebView2 when activated | ||
_ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) | ||
// _ = ctrl.MoveFocus(0) // fallback if your bindings lack the constant | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Harden focus transfer on activation with fallbacks.
Don’t ignore errors from MoveFocus. Add a fallback to enum 0 and finally Chromium.Focus() to maximize compatibility and ensure keyboard input works immediately after activation.
- if ctrl := w.chromium.GetController(); ctrl != nil {
- // Push keyboard focus into WebView2 when activated
- _ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC)
- // _ = ctrl.MoveFocus(0) // fallback if your bindings lack the constant
- }
+ if ctrl := w.chromium.GetController(); ctrl != nil {
+ // Push keyboard focus into WebView2 when activated
+ if err := ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); err != nil {
+ _ = ctrl.MoveFocus(0) // fallback: enum 0 is PROGRAMMATIC
+ w.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.
if w.isActive && w.chromium != nil { | |
if ctrl := w.chromium.GetController(); ctrl != nil { | |
// Push keyboard focus into WebView2 when activated | |
_ = ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) | |
// _ = ctrl.MoveFocus(0) // fallback if your bindings lack the constant | |
} | |
} | |
if w.isActive && w.chromium != nil { | |
if ctrl := w.chromium.GetController(); ctrl != nil { | |
// Push keyboard focus into WebView2 when activated | |
if err := ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC); err != nil { | |
_ = ctrl.MoveFocus(0) // fallback: enum 0 is PROGRAMMATIC | |
w.chromium.Focus() // last-resort fallback | |
} | |
} | |
} |
🤖 Prompt for AI Agents
In v2/internal/frontend/desktop/windows/window.go around lines 240 to 247,
harden the focus transfer: do not ignore MoveFocus errors — call
ctrl.MoveFocus(edge.COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC) and if it
returns an error, retry with ctrl.MoveFocus(0) as a fallback; if that also
fails, call w.chromium.Focus() (or its safe equivalent) as a final fallback.
Ensure nil checks for w.chromium and ctrl remain and propagate or log any errors
as appropriate while still attempting the subsequent fallback steps.
Thanks 🙏 Please could you add an entry to the changelog located at |
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.mdx
with details of this PRSummary by CodeRabbit