linux: send focus changes to the GTK toplevel - #85
Open
sduguay-devolutions wants to merge 6 commits into
Open
sduguay-devolutions wants to merge 6 commits into
sduguay-devolutions wants to merge 6 commits into
Conversation
The toplevel focus change only ran on the offscreen adapter, and GtkX11WebViewAdapter is a sibling of it rather than a subclass, so X11 never got it and still drew no caret. Move ToplevelHandle, the focus change and EventSendState up into GtkWebViewAdapter so both adapters share them, and drop the ExperimentalOffscreen guard: the condition was never offscreen-ness but a toplevel that no window manager owns, which both adapters have. That alone is not enough on X11. Reparenting the toplevel into the host window leaves it without a window manager and without an XEmbed handshake, so nothing ever hands it the X input focus: clicking the page raises no GTK focus-in at all and Focus() was never called. Take the button press as the focus gesture instead and drive the same path from there, returning false so WebKit still handles the click. GTK then emits its own focus-in, which pulls the host's focus across too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An offscreen GdkWindow has no X window behind it. Activating one on the x11 backend makes GTK and WebKit query the pointer against it, and XIQueryPointer on a window that does not exist fails with a BadWindow that takes the whole process down. Reproducible without any pointer input: focusing the web view is enough. Leave the toplevel alone in that combination and log once to say why there is no caret. Wayland is unaffected, since offscreen windows there never reach XInput, and so is the native x11 adapter, whose toplevel is a real X window. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sduguay-devolutions
marked this pull request as ready for review
September 23, 2026 21:52
|
I'm using Avalonia.Controls.WebView Version 12.1.0 and i can confirm the issue. |
This branch has not been deployed
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.
Issue
I've been facing those issues under Wayland with the GTK backend when ExperimentalOffscreen was turned on.
The cause is that an offscreen toplevel is never activated by a window manager. NativeWebView.OnGotFocus does call adapter.Focus(), but the base GTK implementation only does
gtk_widget_grab_focuson the web view widget. Nothing tells the toplevel it became active. Therefore the page was considered to belong to an inactive window which is why I was facing those two issues.The same thing happens with ExperimentalOffscreen disabled with X11. Its toplevel has the same problem for a different reason: it is reparented into the host window, which takes it away from the window manager. On top of that there is no XEmbed handshake, so nothing ever hands it the X input focus. Clicking the page raises no focus-in at all.
Fix
GtkWebViewAdapternow synthesizes the focus change GDK would normally deliver, sendingGDK_FOCUS_CHANGEto the host window viagtk_widget_send_focus_changeon focus and on resign. This lives in the base class so both adapters share it, each exposing its own toplevel throughToplevelHandle.For X11 that is not enough on its own, since nothing calls Focus() to begin with. GtkX11WebViewAdapter now takes the button press as the focus gesture the window manager would otherwise have produced, and drives the same path from there. It returns false, so it still handles the click as usual. GTK then emits its own focus-in, which pulls the host's focus across too.
Before:

After:

I found that, once the text caret was showing up, it blinked inconsistently like it was skipping frames. The handler's own Invalidate() marks the custom visual dirty without getting the compositor to schedule a frame, so an update was drawn only once something else caused one. Continuous animation hides this, while sparse updates such as a caret blink held each phase for a few milliseconds instead of half a second. Which is why I added an
InvalidateVisual()inNativeWebViewCompositorHost