gdk/wayland: Defer processing of globals closures

... until all globals have been received.

The dependency tracking introduced in 4e9be39518 only allows to
specify required globals and processes the closures as soon as
the requirements have been met. There are, however, also optional
dependencies - most notably the primary_selection protocol.
Currently we rely on the fact that compositors like Mutter announce
it before `wl_seat`, even though the order is not specified in
the spec.

Process globals closures only after all globals have been announced,
so optional dependencies can be accommodated.

Closes https://gitlab.gnome.org/GNOME/gtk/-/issues/3791
This commit is contained in:
Robert Mader 2021-03-27 15:48:00 +01:00
parent b77e05ce37
commit 56d37ceed0

View File

@ -488,26 +488,19 @@ gdk_registry_handle_global (void *data,
} }
else if (strcmp (interface, "wl_seat") == 0) else if (strcmp (interface, "wl_seat") == 0)
{ {
SeatAddedClosure *closure;
static const char *required_device_manager_globals[] = { static const char *required_device_manager_globals[] = {
"wl_compositor", "wl_compositor",
"wl_data_device_manager", "wl_data_device_manager",
NULL NULL
}; };
if (has_required_globals (display_wayland, closure = g_new0 (SeatAddedClosure, 1);
required_device_manager_globals)) closure->base.handler = seat_added_closure_run;
_gdk_wayland_display_add_seat (display_wayland, id, version); closure->base.required_globals = required_device_manager_globals;
else closure->id = id;
{ closure->version = version;
SeatAddedClosure *closure; postpone_on_globals_closure (display_wayland, &closure->base);
closure = g_new0 (SeatAddedClosure, 1);
closure->base.handler = seat_added_closure_run;
closure->base.required_globals = required_device_manager_globals;
closure->id = id;
closure->version = version;
postpone_on_globals_closure (display_wayland, &closure->base);
}
} }
else if (strcmp (interface, "wl_data_device_manager") == 0) else if (strcmp (interface, "wl_data_device_manager") == 0)
{ {
@ -586,8 +579,6 @@ gdk_registry_handle_global (void *data,
g_hash_table_insert (display_wayland->known_globals, g_hash_table_insert (display_wayland->known_globals,
GUINT_TO_POINTER (id), g_strdup (interface)); GUINT_TO_POINTER (id), g_strdup (interface));
process_on_globals_closures (display_wayland);
} }
static void static void
@ -679,8 +670,13 @@ _gdk_wayland_display_open (const char *display_name)
display_wayland->wl_registry = wl_display_get_registry (display_wayland->wl_display); display_wayland->wl_registry = wl_display_get_registry (display_wayland->wl_display);
wl_registry_add_listener (display_wayland->wl_registry, &registry_listener, display_wayland); wl_registry_add_listener (display_wayland->wl_registry, &registry_listener, display_wayland);
if (wl_display_roundtrip (display_wayland->wl_display) < 0)
{
g_object_unref (display);
return NULL;
}
_gdk_wayland_display_async_roundtrip (display_wayland); process_on_globals_closures (display_wayland);
/* Wait for initializing to complete. This means waiting for all /* Wait for initializing to complete. This means waiting for all
* asynchronous roundtrips that were triggered during initial roundtrip. */ * asynchronous roundtrips that were triggered during initial roundtrip. */