Add --renderer for displays with no usable GPU; gate the header reading

GTK4 defaults to Vulkan, and an X11-forwarded display has no device to make a
swapchain from; the plot is a GtkGLArea, so it then asks for a GL context that
is not there either. --renderer cairo is the software preset for that display:
it exports GSK_RENDERER=cairo and LIBGL_ALWAYS_SOFTWARE=1 in main() before
gtk_init()/adw_init(), because both are read when the renderer and the context
are created. --renderer gl is the faster choice when indirect GL works, and
--renderer vulkan makes the default explicit. Nothing is exported, and GTK's
own choice stands, when the option is absent.

The once-a-second header line is now behind UDPSCOPE_PROBE_HEADER, following
the [notrace] rule: its widths are still sampled for the exit dump, but the
line is detail behind that reading rather than output every run prints.
UDPSCOPE_PROBE_RENDERER prints the exported pair before GTK starts and the
GskRenderer GTK actually built.

README, the manual's overview and docs/claude record the two symptoms and the
cure.
This commit is contained in:
Martino Ferrari committed 2026-10-28 16:03:05 +01:00
1 parent ac054a30c9
commit fcf268d249
9 files changed
+151 -7

No files matched your search

+16 -2
View File
@@ -450,11 +450,25 @@ Two lines of the self-check output are assertions in disguise:
floor are the two refusals, and because the probe emits `::clicked` straight at the
widget it reaches the handler even when the button is insensitive, so `add above 0` there
must leave `rows=` and `traces=` untouched rather than growing a ninth row.
- `header: window_button_w=W bar_w=B` (stderr, once a second) — **`W` must be
- `[udpscope] header: window_button_w=W bar_w=B` (stderr, once a second, **only when
`UDPSCOPE_PROBE_HEADER` is set**) — **`W` must be
a small constant and must not track `B`**: the window control is a header-bar child,
and an expanding one is measured into the title's centre box, so it stretched from the
label to the title (516 px at a 1270 px bar before the fix, 121 px after). A `W` that
grows with the window width is that bug back.
grows with the window width is that bug back. The widths are still sampled every second
in every run, because the exit dump's `header:` line reads them; only the line is behind
the variable, since a reading printed on every run is a log flood (the `[notrace]` rule).
An unallocated window reads `0` for both, which is the reading for "the toplevel never
got a size", not for a layout drift.
- `[renderer] option=NAME GSK_RENDERER=V LIBGL_ALWAYS_SOFTWARE=V` (stderr, at startup,
before GTK initialises; only when `UDPSCOPE_PROBE_RENDERER` is set) — what `--renderer`
exported, printed from `main()` so the reading is of the environment a pre-init GTK will
see. `option=(unset)` with both variables `(unset)` is the default and the assertion that
the flag changes nothing unless asked.
- `[renderer] realized=TYPE` (stderr, once, from the first tick that finds a window renderer;
same probe) — the class GTK actually built (`GskCairoRenderer` for `--renderer cairo`),
which is the half of the claim the export alone cannot make. It is null until the window is
realized, so a tick that finds none tries again rather than printing a false reading.
- `toolbar icons: trigger=NAME(ok) events=... pause=... cursors=... sidebar=... menu=...` (in the
exit dump, beside `panel controls:`) — the icon name every toolbar button
carries, with `gtk_icon_theme_has_icon()`'s verdict. **Every entry must read `(ok)`.** Three