force a relayout/repaint on tab switches (white tab until F5)

F5 fixing the blank tab shows the page is loaded but WebKitGTK never
re-composites a freshly shown webview under accelerated compositing.
queue resize+draw for the active view and its container on every switch,
plus one more pass on idle, so a restored or switched-to tab lands on a
live frame instead of a stale white surface.
This commit is contained in:
Martin Dvořák 2026-10-11 19:47:28 +02:00
commit beb7c5776c

View file

@ -17,9 +17,9 @@ use tao::event_loop::{ControlFlow, EventLoop, EventLoopBuilder, EventLoopProxy};
#[cfg(target_os = "linux")]
use tao::platform::unix::WindowExtUnix;
use tao::window::{Icon, Window, WindowBuilder};
#[cfg(target_os = "linux")]
use wry::WebViewBuilderExtUnix;
use wry::{PageLoadEvent, Rect, WebContext, WebView, WebViewBuilder};
#[cfg(target_os = "linux")]
use wry::{WebViewBuilderExtUnix, WebViewExtUnix};
const DEFAULT_HOME: &str = "https://duckduckgo.com";
const NEW_TAB_URL: &str = "https://duckduckgo.com";
@ -2311,6 +2311,34 @@ fn apply_visibility(state: &BrowserState) {
let _ = webview.set_visible(i == state.active);
}
}
#[cfg(target_os = "linux")]
nudge_active_repaint(state);
}
/// WebKitGTK with accelerated compositing can leave a freshly shown webview
/// unpainted (blank page until something forces a redraw). Re-queue layout
/// and drawing on the active view so every tab switch lands on a live frame.
#[cfg(target_os = "linux")]
fn nudge_active_repaint(state: &BrowserState) {
let Some(tab) = state.tabs.get(state.active) else {
return;
};
let Some(webview) = tab.webview.as_ref() else {
return;
};
if let Some(container) = state.gtk_content_container.as_ref() {
container.queue_resize();
}
let widget = webview.webview();
widget.queue_resize();
widget.queue_draw();
let widget = widget.clone();
gtk::glib::idle_add_local_once(move || {
if widget.is_realized() {
widget.queue_resize();
widget.queue_draw();
}
});
}
fn push_tabs(state: &BrowserState) {