diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index cc942ebe0d..aa696369fa 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -1106,6 +1106,7 @@ seat_handle_capabilities(void *data, struct wl_seat *seat, GdkWaylandDeviceData *device = data; GdkWaylandDeviceManager *device_manager = GDK_WAYLAND_DEVICE_MANAGER(device->device_manager); + GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (device->display); if ((caps & WL_SEAT_CAPABILITY_POINTER) && !device->wl_pointer) { @@ -1178,6 +1179,10 @@ seat_handle_capabilities(void *data, struct wl_seat *seat, _gdk_device_set_associated_device (device->pointer, device->keyboard); _gdk_device_set_associated_device (device->keyboard, device->pointer); } + + /* Once we have the capabilities event we know we have all events + * from the wl_seat and need no further init roundtrips. */ + display->init_ref_count--; } static const struct wl_seat_listener seat_listener = { diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 5061f07a16..99707524b3 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -100,6 +100,7 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id if (strcmp(interface, "wl_compositor") == 0) { display_wayland->compositor = wl_registry_bind(display_wayland->wl_registry, id, &wl_compositor_interface, 1); + display_wayland->init_ref_count--; } else if (strcmp(interface, "wl_shm") == 0) { display_wayland->shm = wl_registry_bind(display_wayland->wl_registry, id, &wl_shm_interface, 1); @@ -113,10 +114,18 @@ gdk_registry_handle_global(void *data, struct wl_registry *registry, uint32_t id output = wl_registry_bind(display_wayland->wl_registry, id, &wl_output_interface, 1); _gdk_wayland_screen_add_output(display_wayland->screen, output); + /* We need to roundtrip until we've received the modes and + * geometry events for the output, which gives us the physical + * properties and available modes on the output. */ + display_wayland->init_ref_count++; } else if (strcmp(interface, "wl_seat") == 0) { seat = wl_registry_bind(display_wayland->wl_registry, id, &wl_seat_interface, 1); _gdk_wayland_device_manager_add_device (gdk_display->device_manager, seat); + /* We need to roundtrip until we've received the wl_seat + * capabilities event which informs us of available input devices + * on this seat. */ + display_wayland->init_ref_count++; } else if (strcmp(interface, "wl_data_device_manager") == 0) { display_wayland->data_device_manager = wl_registry_bind(display_wayland->wl_registry, id, @@ -164,7 +173,11 @@ _gdk_wayland_display_open (const gchar *display_name) display_wayland->wl_registry = wl_display_get_registry(display_wayland->wl_display); wl_registry_add_listener(display_wayland->wl_registry, ®istry_listener, display_wayland); - wl_display_dispatch(display_wayland->wl_display); + /* We use init_ref_count to track whether some part of our + * initialization still needs a roundtrip to complete. */ + display_wayland->init_ref_count = 1; + while (display_wayland->init_ref_count > 0) + wl_display_roundtrip(display_wayland->wl_display); display_wayland->event_source = _gdk_wayland_display_event_source_new (display); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 269d447bbf..35eac41a3d 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -66,6 +66,8 @@ struct _GdkWaylandDisplay GSource *event_source; + int init_ref_count; + struct xkb_context *xkb_context; }; diff --git a/gdk/wayland/gdkscreen-wayland.c b/gdk/wayland/gdkscreen-wayland.c index 7f209b59d9..be1a0f5417 100644 --- a/gdk/wayland/gdkscreen-wayland.c +++ b/gdk/wayland/gdkscreen-wayland.c @@ -79,6 +79,7 @@ struct _GdkWaylandScreenClass struct _GdkWaylandMonitor { + GdkWaylandScreen *screen; struct wl_output *output; GdkRectangle geometry; int width_mm; @@ -859,6 +860,7 @@ output_handle_geometry(void *data, int32_t transform) { GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data; + GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (monitor->screen->display); monitor->geometry.x = x; monitor->geometry.y = y; @@ -868,6 +870,10 @@ output_handle_geometry(void *data, monitor->manufacturer = g_strdup (make); monitor->output_name = g_strdup (model); + + /* Once we have the geometry event we know we have all events + * from the wl_output and need no further init roundtrips. */ + display->init_ref_count--; } static void @@ -901,6 +907,7 @@ _gdk_wayland_screen_add_output (GdkScreen *screen, GdkWaylandMonitor *monitor = g_new0(GdkWaylandMonitor, 1); monitor->output = output; + monitor->screen = screen_wayland; g_ptr_array_add(screen_wayland->monitors, monitor); wl_output_add_listener(output, &output_listener, monitor);