Skip to content

Fix GTK focus echo and offscreen frame lag (follow-up to #85) - #93

Merged
maxkatz6 merged 2 commits into
mainfrom
fixes/gtk-focus-echo-and-frame-lag
Oct 12, 2026
Merged

maxkatz6 merged 2 commits into
mainfrom
fixes/gtk-focus-echo-and-frame-lag

Conversation

@maxkatz6

Copy link
Copy Markdown
Member

Follow-up to #85.

Don't report host-driven GTK focus changes back to the host

Since #85, Focus()/ResignFocus() activate and deactivate the GTK toplevel, so GTK raises focus-in/focus-out on the web view for them. Those events were sent back to the host asynchronously:

  • Avalonia: with fast Tab navigation, the late GotFocus arrived after focus had already moved on, and WithFocusOnGotFocus pulled focus back into the web view.
  • WPF/XPF: GotFocus/LostFocus were raised twice (WithFocusOnLostFocus doesn't check _ignoreFocusChanges).

GTK raises these events synchronously inside the call, so a flag set around host-driven focus changes now drops them. The X11 click handler uses a new FocusFromWebView(), which still reports the change, because there the host doesn't know about it yet.

Show the newest offscreen frame instead of the one before it

FrameChainBase consumer picked the oldest unconsumed slot, and the slots the producer had never written count as unconsumed. The first NextFrame() took an empty slot, and after that every draw showed the previous frame. That is the "sparse update sits until the next one" symptom from #85. The consumer now takes the newest published frame and drops older ones. This replaces the InvalidateVisual() workaround in NativeWebViewCompositorHost, which added a UI render pass for every web frame.

Testing

  • Two new BitmapFrameChainTests cases. Both fail on main and pass with this change.
  • Full test suite passes locally on Windows.
  • Not yet tested on Linux/GTK.

🤖 Generated with Claude Code

maxkatz6 and others added 2 commits October 11, 2026 22:40
Focus() and ResignFocus() now activate and deactivate the GTK toplevel, so GTK
raises focus-in/focus-out on the web view for them. Reporting those back
re-entered the host's focus handling asynchronously: fast Tab navigation in
Avalonia could pull focus back into the web view, and WPF raised GotFocus and
LostFocus twice. The X11 click path still reports, since there the host
doesn't know about the change yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The frame chain consumer picked the oldest unconsumed slot, and the slots the
producer had never written count as unconsumed. So the first NextFrame took an
empty slot, and from then on every draw showed the previous frame. Take the
newest published frame and drop older ones. This replaces the InvalidateVisual
workaround in NativeWebViewCompositorHost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@maxkatz6
maxkatz6 merged commit d6701c7 into main Oct 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant