advertise presentation-time, xdg-output and viewporter globals

Clients relied on these to run at their best and fell back otherwise:
wp_presentation gives frame pacing feedback, zxdg_output_manager_v1
logical output geometry for newer toolkits, wp_viewporter lets video
clients scale buffers instead of reallocating.  All three are passive
wlroots globals.  The output layout now exists in both modes so the
nested host-window output is part of it; without that, a client's
get_xdg_output request hit wlr_xdg_output_v1.c's layout_output assert
and aborted the compositor.  wltest gains --globals-out to dump the
advertised interface list (CLI-tab stdout is /dev/null'd by kick), and
a smoke test asserts the new globals are advertised.
This commit is contained in:
Andrew Hamilton 2026-08-19 16:47:58 +10:00
parent 7db91f9d60
commit ea05f25383
3 changed files with 103 additions and 8 deletions

View file

@ -28,6 +28,12 @@ static struct xdg_surface *xdg_surface;
static struct xdg_toplevel *toplevel;
static struct wl_buffer *buffer;
static struct wl_seat *seat;
/* --globals-out <path>: write the advertised global interface names to a
file (one per line) and exit, instead of showing a toplevel. The file
escapes kick's CLI-tab stdout redirection to /dev/null, letting tests
assert which protocols the standalone compositor advertises. */
static const char *globals_out;
static struct wl_keyboard *keyboard;
static struct wl_pointer *pointer;
static struct wp_cursor_shape_manager_v1 *shape_mgr;
@ -201,6 +207,16 @@ static const struct xdg_toplevel_listener toplevel_listener = {
static void registry_global(void *data, struct wl_registry *reg, uint32_t name,
const char *interface, uint32_t version) {
(void)data;
if (globals_out) {
/* Collecting mode: just remember names; they are written out after
the first roundtrip completes. */
FILE *f = fopen(globals_out, "a");
if (f) {
fprintf(f, "%s %u\n", interface, version);
fclose(f);
}
return;
}
if (strcmp(interface, wl_compositor_interface.name) == 0) {
compositor = wl_registry_bind(reg, name, &wl_compositor_interface,
version < 4 ? version : 4);
@ -354,11 +370,13 @@ static const struct { uint32_t shape; const char *name; } SHAPES[] = {
static void print_usage(const char *argv0) {
fprintf(stderr, "usage: %s [--app-id <id>] [--extra #RRGGBB] "
"[--cursor-shape name] #RRGGBB [WIDTHxHEIGHT]\n"
"[--cursor-shape name] [--globals-out <file>] "
"#RRGGBB [WIDTHxHEIGHT]\n"
" %s shows a solid-color xdg_toplevel, e.g. #ff0000\n"
" --extra also opens a second toplevel from the same client\n"
" --cursor-shape requests that cursor-shape-v1 shape on "
"pointer enter (default|text|pointer|crosshair)\n",
"pointer enter (default|text|pointer|crosshair)\n"
" --globals-out lists advertised globals to <file> and exits\n",
argv0, argv0);
}
@ -407,10 +425,32 @@ int main(int argc, char **argv) {
return 1;
}
i += 2;
} else if (strcmp(argv[i], "--globals-out") == 0) {
if (i + 1 >= argc) {
fprintf(stderr, "wltest: --globals-out needs a path\n");
return 1;
}
globals_out = argv[i + 1];
i += 2;
} else {
break;
}
}
if (globals_out) {
/* Advertised-globals mode: the color/size args are ignored. */
display = wl_display_connect(NULL);
if (!display) {
fprintf(stderr, "wltest: cannot connect (WAYLAND_DISPLAY=%s)\n",
getenv("WAYLAND_DISPLAY") ? getenv("WAYLAND_DISPLAY") : "unset");
return 1;
}
struct wl_registry *reg = wl_display_get_registry(display);
wl_registry_add_listener(reg, &registry_listener, NULL);
wl_display_roundtrip(display);
wl_display_roundtrip(display);
wl_display_disconnect(display);
return 0;
}
if (i >= argc || argv[i][0] != '#') {
print_usage(argv[0]);
return 1;