Describe the bug
When NativeWebView is hosted inside any Avalonia container on a Wayland desktop session that uses XWayland for X11 client support, the embedded WebKitGTK widget gets its initial allocation of approximately 200×200 pixels and never resizes — regardless of the actual layout bounds Avalonia gives it. The Avalonia-side Bounds, Width, and Height all report the correct values, and NavigationCompleted fires with IsSuccess=true. JavaScript probes inside the page initially report window.innerWidth=200, window.innerHeight=200. Page content past that region is rendered (the DOM has the right size after applying the workarounds below) but the render surface itself is clipped to ~200×200, so most of the WebView area appears blank against the host background.
Setting webView.Width/webView.Height directly has no effect on the embedded GTK widget. Calling gtk_widget_set_size_request + gtk_widget_size_allocate walked up every ancestor of IGtkWebViewPlatformHandle.WebKitWebView makes JS see the new viewport size (window.innerWidth/Height update correctly) but the actual pixels still come from the original ~200×200 cairo surface until something forces GTK to re-establish the XEmbed surface.
The only reliable way to make WebKit allocate a render buffer of the correct size is a IsVisible=false → IsVisible=true toggle posted after AdapterCreated, which tears down and re-establishes the embedded surface.
A pure X11 session (GDK_BACKEND=x11 on a real X11 display, not XWayland) does not exhibit the bug — the initial allocation is correct and resizes propagate.
Environment:
- Avalonia: 12.0.3 (also reproduces on 12.0.1)
- Avalonia.Controls.WebView: 12.0.1
- OS: Linux (reproduced on Arch / CachyOS, kernel 7.0.6)
- Desktop session: Wayland with XWayland
GDK_BACKEND=x11 is set so the GtkX11WebViewAdapter is used (the only Linux adapter shipped)
- webkit2gtk-4.1 2.52.x (host package)
- .NET 8.0.x, x64
What the workaround in our repro does (and which combination is actually required vs. cosmetic):
| Step |
Required? |
gtk_widget_set_size_request on the WebKitWebView and all ancestors |
partial — fixes layout numbers but not pixels |
gtk_widget_size_allocate on every ancestor |
partial — same as above |
gtk_widget_queue_resize / queue_draw |
no observable effect alone |
window.dispatchEvent(new Event('resize')) from JS |
no observable effect alone |
IsVisible = false; IsVisible = true; posted from AdapterCreated |
yes — this is what actually fixes the rendered pixels |
Re-apply size on host SizeChanged so window resize works |
yes — without this the WebView freezes at its initial size after the first paint |
All of this should be the adapter's responsibility, not the application's. The IGtkWebViewPlatformHandle accessor isn't even available before AdapterCreated (host SizeChanged events that fire earlier see a null handle), so userspace can't reliably hit it from the natural lifecycle hooks either.
To Reproduce
- On a Linux Wayland session with XWayland enabled, install webkit2gtk-4.1 (Ubuntu 24.04+:
libwebkit2gtk-4.1-0; Fedora 40+: webkit2gtk4.1; Arch: webkit2gtk-4.1; Debian 13+: libwebkit2gtk-4.1-0).
- Clone or extract the attached
repro/ project.
- Run:
(
run.sh just sets GDK_BACKEND=x11, WEBKIT_DISABLE_DMABUF_RENDERER=1, and WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1 before dotnet run. Setting GDK_BACKEND from inside Program.Main via Environment.SetEnvironmentVariable races GTK's static init on some launch paths and produces Unable to initialize GTK at the first WebView attach — pre-setting it in the shell avoids that, which is unrelated to the sizing bug.)
- Observe the window. The grey panel in the centre should be a full-sized WebView rendering a coloured page with overlay text showing
window.innerWidth × window.innerHeight.
Actual result: the WebView pane is mostly the grey container colour. Only a ~200×200 region in the top-left of the WebView area shows the rendered coloured page. The overlay text inside that region reads 200 × 200.
To confirm the workaround fixes it, click the "Apply hide+show fix" button in the repro. The full WebView area paints correctly and the overlay text updates to the actual size (e.g. 800 × 600).
Note: the repro disables WebKit's bubblewrap sandbox (WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1) and the DMA-BUF renderer (WEBKIT_DISABLE_DMABUF_RENDERER=1). Those are separate issues we hit packaging the WebView in an AppImage with file:// HTML; they are set on the repro to keep the focus on the sizing bug. Removing them does not change the sizing behaviour, only adds unrelated failures.
Expected behavior
NativeWebView's embedded GTK widget should be allocated at the size Avalonia's layout system gives the control, on both initial layout and subsequent SizeChanged events. This is what happens on Windows (WebView2), macOS (WKWebView), and on a pure X11 session — only the Wayland/XWayland path is broken.
Equivalently: the application code in the attached repro should not need any of the workaround calls in WebViewSizeFix.cs to get a correctly-sized render surface. <NativeWebView Source="..." /> inside a Grid should "just work".
Avalonia WebView version
12.0.1
Avalonia version
12.0.2
OS
Linux
Additional context
avalonia-webview-xwayland-sizing-bug.zip
Describe the bug
When
NativeWebViewis hosted inside any Avalonia container on a Wayland desktop session that uses XWayland for X11 client support, the embedded WebKitGTK widget gets its initial allocation of approximately 200×200 pixels and never resizes — regardless of the actual layout bounds Avalonia gives it. The Avalonia-sideBounds,Width, andHeightall report the correct values, andNavigationCompletedfires withIsSuccess=true. JavaScript probes inside the page initially reportwindow.innerWidth=200, window.innerHeight=200. Page content past that region is rendered (the DOM has the right size after applying the workarounds below) but the render surface itself is clipped to ~200×200, so most of the WebView area appears blank against the host background.Setting
webView.Width/webView.Heightdirectly has no effect on the embedded GTK widget. Callinggtk_widget_set_size_request+gtk_widget_size_allocatewalked up every ancestor ofIGtkWebViewPlatformHandle.WebKitWebViewmakes JS see the new viewport size (window.innerWidth/Heightupdate correctly) but the actual pixels still come from the original ~200×200 cairo surface until something forces GTK to re-establish the XEmbed surface.The only reliable way to make WebKit allocate a render buffer of the correct size is a
IsVisible=false→IsVisible=truetoggle posted afterAdapterCreated, which tears down and re-establishes the embedded surface.A pure X11 session (
GDK_BACKEND=x11on a real X11 display, not XWayland) does not exhibit the bug — the initial allocation is correct and resizes propagate.Environment:
GDK_BACKEND=x11is set so the GtkX11WebViewAdapter is used (the only Linux adapter shipped)What the workaround in our repro does (and which combination is actually required vs. cosmetic):
gtk_widget_set_size_requeston the WebKitWebView and all ancestorsgtk_widget_size_allocateon every ancestorgtk_widget_queue_resize/queue_drawwindow.dispatchEvent(new Event('resize'))from JSIsVisible = false; IsVisible = true;posted fromAdapterCreatedSizeChangedso window resize worksAll of this should be the adapter's responsibility, not the application's. The
IGtkWebViewPlatformHandleaccessor isn't even available beforeAdapterCreated(hostSizeChangedevents that fire earlier see a null handle), so userspace can't reliably hit it from the natural lifecycle hooks either.To Reproduce
libwebkit2gtk-4.1-0; Fedora 40+:webkit2gtk4.1; Arch:webkit2gtk-4.1; Debian 13+:libwebkit2gtk-4.1-0).repro/project.cd repro ./run.shrun.shjust setsGDK_BACKEND=x11,WEBKIT_DISABLE_DMABUF_RENDERER=1, andWEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1beforedotnet run. SettingGDK_BACKENDfrom insideProgram.MainviaEnvironment.SetEnvironmentVariableraces GTK's static init on some launch paths and producesUnable to initialize GTKat the first WebView attach — pre-setting it in the shell avoids that, which is unrelated to the sizing bug.)window.innerWidth × window.innerHeight.Actual result: the WebView pane is mostly the grey container colour. Only a ~200×200 region in the top-left of the WebView area shows the rendered coloured page. The overlay text inside that region reads
200 × 200.To confirm the workaround fixes it, click the "Apply hide+show fix" button in the repro. The full WebView area paints correctly and the overlay text updates to the actual size (e.g.
800 × 600).Note: the repro disables WebKit's bubblewrap sandbox (
WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1) and the DMA-BUF renderer (WEBKIT_DISABLE_DMABUF_RENDERER=1). Those are separate issues we hit packaging the WebView in an AppImage with file:// HTML; they are set on the repro to keep the focus on the sizing bug. Removing them does not change the sizing behaviour, only adds unrelated failures.Expected behavior
NativeWebView's embedded GTK widget should be allocated at the size Avalonia's layout system gives the control, on both initial layout and subsequentSizeChangedevents. This is what happens on Windows (WebView2), macOS (WKWebView), and on a pure X11 session — only the Wayland/XWayland path is broken.Equivalently: the application code in the attached repro should not need any of the workaround calls in
WebViewSizeFix.csto get a correctly-sized render surface.<NativeWebView Source="..." />inside aGridshould "just work".Avalonia WebView version
12.0.1
Avalonia version
12.0.2
OS
Linux
Additional context
avalonia-webview-xwayland-sizing-bug.zip