Ask the Linux WebView for the one mode it can draw in this window
ci / build and test (push) Successful in 1m12s
ci / android head (push) Failing after 5s
ci / api image (push) Successful in 22s

The terminal renders nothing on Linux, and does it in the most misleading way available: the
page loads, the scripts run, the renderer connects, InvokeScript answers. Everything works
except the pixels, so it reads as a broken terminal rather than as a host with nowhere to
paint.

Measured on Fedora 44 with Avalonia.Controls.WebView 12.0.1, by a spike that hosts a
NativeWebView and reads AdapterInfo. The backend is WebKitGTK 2.52.5 — not the WPE one this
repository's platform notes predicted, and Fedora packages no WPE WebKit at all, so that path
was never going to be the answer here. In its default mode the adapter reports
SupportedScenarios = NativeDialog: a window of its own, and nothing that can be hosted in
place. Identical under X11 and Wayland, so it is the adapter's answer rather than a session
problem.

Setting ExperimentalOffscreen on the GTK environment arguments changes the same adapter's
answer to OffscreenRenderer — the compositor-drawn mode, which is what the
NativeWebViewCompositorHost mentioned in those same notes exists to host. MainWindow now sets
it as the environment is settled. Windows and macOS are untouched by construction rather than
by an OS check: the argument is a GTK type there and the handler does nothing.

The platform notes carried this as "unproven, and still the largest risk in the plan". They
carry the measurement now, including the part that is still unproven and the reason the spike
could not settle it.

What is NOT verified is that it now paints. An XWayland root capture is black under a Wayland
compositor and RenderTargetBitmap does not capture a compositor surface, so both ways of
looking at it from here failed. It needs eyes on a running client, and if the terminal is
still blank the next question is whether it takes input at all — that separates "not drawing"
from "not hosted".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-01 22:35:19 +02:00
co-authored by Claude Opus 5
parent a0d53b0c9d
commit 52596aac76
2 changed files with 59 additions and 11 deletions
@@ -1,6 +1,7 @@
using System.ComponentModel;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Threading;
using DodoSSH.Client.Shell.ViewModels;
@@ -38,6 +39,9 @@ internal sealed partial class MainWindow : Window
DataContextChanged += (_, _) => Attach(DataContext as MainWindowViewModel);
// Before anything navigates: the environment is settled once, when the adapter is built.
Terminal.EnvironmentRequested += OnTerminalEnvironmentRequested;
Terminal.WebMessageReceived += (_, e) =>
{
// Compared against a constant rather than parsed: the page sends exactly one message and
@@ -50,6 +54,38 @@ internal sealed partial class MainWindow : Window
};
}
/// <summary>
/// Asks the Linux backend for the one mode it can actually draw inside this window.
/// </summary>
/// <remarks>
/// <para>
/// <b>Without this the terminal is blank on Linux</b>, and blank in the most confusing way available:
/// the page loads, scripts run, the renderer connects — everything except pixels. Measured on Fedora 44
/// with Avalonia.Controls.WebView 12.0.1, where the backend is WebKitGTK 2.52.5 (WPE, the backend the
/// package's Linux notes describe, is not packaged for Fedora at all). In its default mode that adapter
/// reports <c>SupportedScenarios = NativeDialog</c> — it can open a window of its own and nothing else,
/// so a control asked to host it in place has nothing to show. Setting <c>ExperimentalOffscreen</c>
/// changes the same adapter's answer to <c>OffscreenRenderer</c>, which is the mode Avalonia's
/// compositor can draw.
/// </para>
/// <para>
/// Windows and macOS are untouched, and by construction rather than by an OS check: the argument is a
/// GTK type there and this method does nothing. WebView2 and WKWebView both host in place already.
/// </para>
/// <para>
/// <em>Experimental</em> is the vendor's word and worth repeating. If a future release makes the GTK
/// adapter host in place properly, this becomes unnecessary rather than wrong — and if the flag is
/// withdrawn, the terminal goes back to being blank on Linux, which is the thing to check first.
/// </para>
/// </remarks>
private static void OnTerminalEnvironmentRequested(object? sender, EventArgs e)
{
if (e is GtkWebViewEnvironmentRequestedEventArgs gtk)
{
gtk.ExperimentalOffscreen = true;
}
}
/// <summary>
/// Where the keyboard belongs when the terminal is not holding it.
/// </summary>