Skip to content

NativeWebView renders at fixed ~200×200 surface under XWayland regardless of allocated bounds (GtkX11 adapter) #48

@Drommedhar

Description

@Drommedhar

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=falseIsVisible=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

  1. 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).
  2. Clone or extract the attached repro/ project.
  3. Run:
    cd repro
    ./run.sh
    (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.)
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions