backend-headless: Add an option to enable a fake seat

When running headless, weston will not expose a wl_seat.

This was removed with commit a1046adc ("compositor-headless: do not
create a seat").

However, some applications, namely GTK3 based, will log a warning when
there is no wl_seat:

 | gdk_seat_get_keyboard assertion GDK_IS_SEAT(seat) failed

While this is arguably a bug in GTK3 which should not complain with a
legit setup, that breaks the CI of those projects when using Weston,
while most of the other Wayland compositors will create a fake seat when
running headless, making weston the odd ball there.

This changes adds a new option "--fake-seat" that will instruct weston
to create a seat when running headless. The default remains not to
create a seat though, so backward compatibility is preserved.

This partially reverts commit a1046adc66.

See-also: https://gitlab.freedesktop.org/ofourdan/xwayland-run/-/issues/12
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
Olivier Fourdan 2025-12-08 11:33:30 +01:00
parent cb97abd4f7
commit 0126a5b4fc
3 changed files with 40 additions and 0 deletions

View file

@ -771,6 +771,7 @@ usage(int error_code)
" --use-vulkan\t\tUse the Vulkan renderer (deprecated alias for --renderer=vulkan)\n"
" --no-outputs\t\tDo not create any virtual outputs\n"
" --refresh-rate=RATE\tThe output refresh rate (in mHz)\n"
" --fake-seat\t\tUse a fake seat for compatibility\n"
"\n");
#endif
@ -4328,6 +4329,7 @@ load_headless_backend(struct weston_compositor *c,
{ WESTON_OPTION_STRING, "transform", 0, &transform },
{ WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
{ WESTON_OPTION_INTEGER, "refresh-rate", 0, &config.refresh },
{ WESTON_OPTION_BOOLEAN, "fake-seat", 0, &config.fake_seat },
};
config.refresh = -1;

View file

@ -49,6 +49,11 @@ struct weston_headless_backend_config {
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
* only on capture requests, not on damages. */
int refresh;
/** Create a fake seat, some clients may complain without a wl_seat.
* The default is not to create a wl_seat.
*/
bool fake_seat;
};
#ifdef __cplusplus

View file

@ -70,6 +70,8 @@ struct headless_backend {
int refresh;
bool repaint_only_on_capture;
bool use_fake_seat;
};
struct headless_head {
@ -598,6 +600,25 @@ headless_head_destroy(struct weston_head *base)
free(head);
}
static bool
headless_input_create(struct headless_backend *b)
{
weston_seat_init(&b->fake_seat, b->compositor, "default");
weston_seat_init_pointer(&b->fake_seat);
if (weston_seat_init_keyboard(&b->fake_seat, NULL) < 0)
return false;
return true;
}
static void
headless_input_destroy(struct headless_backend *b)
{
weston_seat_release(&b->fake_seat);
}
static void
headless_destroy(struct weston_backend *backend)
{
@ -615,6 +636,9 @@ headless_destroy(struct weston_backend *backend)
if (b->theme)
theme_destroy(b->theme);
if (b->use_fake_seat)
headless_input_destroy(b);
free(b->formats);
free(b);
@ -646,6 +670,12 @@ headless_backend_create(struct weston_compositor *compositor,
b->base.supported_presentation_clocks =
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
if (config->fake_seat) {
b->use_fake_seat = headless_input_create(b);
if (!b->use_fake_seat)
goto err_free;
}
b->base.destroy = headless_destroy;
b->base.create_output = headless_output_create;
@ -744,6 +774,8 @@ err_input:
if (b->theme)
theme_destroy(b->theme);
err_free:
if (b->use_fake_seat)
headless_input_destroy(b);
wl_list_remove(&b->base.link);
free(b);
return NULL;
@ -753,6 +785,7 @@ static void
config_init_to_defaults(struct weston_headless_backend_config *config)
{
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
config->fake_seat = FALSE;
}
WL_EXPORT int