[gtk: 6/16] wayland/surface: Add per surface configuration event queues



commit 7fafa5133b5328c72cf206399647d2ee5dbabb27
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Tue Jan 7 17:13:22 2020 +0100

    wayland/surface: Add per surface configuration event queues
    
    Add event queues specifically for surface configuration events
    (xdg_surface.configure, xdg_toplevel.configure, xdg_popup.configure etc)
    so that a configuration can be completed without having side effects on
    other surfaces. This will be used to synchronously configure specific
    GdkSurfaces, as is needed by the Gtk layout mechanisms.

 gdk/wayland/gdkdisplay-wayland.h |  2 ++
 gdk/wayland/gdkeventsource.c     | 32 ++++++++++++++++++++++
 gdk/wayland/gdksurface-wayland.c | 58 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 90 insertions(+), 2 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 19d4bd5aac..1da3e36fe8 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -121,6 +121,8 @@ struct _GdkWaylandDisplay
   GHashTable *known_globals;
   GList *on_has_globals_closures;
 
+  GList *event_queues;
+
   /* Keep a list of orphaned dialogs (i.e. without parent) */
   GList *orphan_dialogs;
 
diff --git a/gdk/wayland/gdkeventsource.c b/gdk/wayland/gdkeventsource.c
index 86c3f86484..be31fb56de 100644
--- a/gdk/wayland/gdkeventsource.c
+++ b/gdk/wayland/gdkeventsource.c
@@ -37,6 +37,7 @@ gdk_event_source_prepare (GSource *base,
 {
   GdkWaylandEventSource *source = (GdkWaylandEventSource *) base;
   GdkWaylandDisplay *display = (GdkWaylandDisplay *) source->display;
+  GList *l;
 
   *timeout = -1;
 
@@ -60,6 +61,24 @@ gdk_event_source_prepare (GSource *base,
   /* if prepare_read() returns non-zero, there are events to be dispatched */
   if (wl_display_prepare_read (display->wl_display) != 0)
     return TRUE;
+
+  /* We need to check whether there are pending events on the surface queues as well,
+   * but we also need to make sure to only have one active "read" in the end,
+   * or none if we immediately return TRUE, as multiple reads expect reads from
+   * as many threads.
+   */
+  for (l = display->event_queues; l; l = l->next)
+    {
+      struct wl_event_queue *queue = l->data;
+
+      if (wl_display_prepare_read_queue (display->wl_display, queue) != 0)
+        {
+          wl_display_cancel_read (display->wl_display);
+          return TRUE;
+        }
+      wl_display_cancel_read (display->wl_display);
+    }
+
   source->reading = TRUE;
 
   if (wl_display_flush (display->wl_display) < 0)
@@ -193,6 +212,7 @@ _gdk_wayland_display_queue_events (GdkDisplay *display)
 {
   GdkWaylandDisplay *display_wayland;
   GdkWaylandEventSource *source;
+  GList *l;
 
   display_wayland = GDK_WAYLAND_DISPLAY (display);
   source = (GdkWaylandEventSource *) display_wayland->event_source;
@@ -204,6 +224,18 @@ _gdk_wayland_display_queue_events (GdkDisplay *display)
       _exit (1);
     }
 
+  for (l = display_wayland->event_queues; l; l = l->next)
+    {
+      struct wl_event_queue *queue = l->data;
+
+      if (wl_display_dispatch_queue_pending (display_wayland->wl_display, queue) < 0)
+        {
+          g_message ("Error %d (%s) dispatching to Wayland display.",
+                     errno, g_strerror (errno));
+          _exit (1);
+        }
+    }
+
   if (source->pfd.revents & (G_IO_ERR | G_IO_HUP))
     {
       g_message ("Lost connection to Wayland compositor.");
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 02409da4e7..55134b1409 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -78,6 +78,8 @@ struct _GdkWaylandSurface
     struct org_kde_kwin_server_decoration *server_decoration;
   } display_server;
 
+  struct wl_event_queue *event_queue;
+
   EGLSurface egl_surface;
   EGLSurface dummy_egl_surface;
 
@@ -450,6 +452,7 @@ gdk_wayland_surface_request_frame (GdkSurface *surface)
   clock = gdk_surface_get_frame_clock (surface);
 
   callback = wl_surface_frame (impl->display_server.wl_surface);
+  wl_proxy_set_queue ((struct wl_proxy *) callback, NULL);
   wl_callback_add_listener (callback, &frame_listener, surface);
   impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
   impl->awaiting_frame = TRUE;
@@ -643,6 +646,44 @@ gdk_wayland_surface_beep (GdkSurface *surface)
   return TRUE;
 }
 
+static void
+gdk_wayland_surface_constructed (GObject *object)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+  GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+  GdkWaylandDisplay *display_wayland =
+    GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+
+  G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->constructed (object);
+
+  impl->event_queue = wl_display_create_queue (display_wayland->wl_display);
+  display_wayland->event_queues = g_list_prepend (display_wayland->event_queues,
+                                                  impl->event_queue);
+}
+
+static void
+gdk_wayland_surface_dispose (GObject *object)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+  GdkWaylandSurface *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_SURFACE (surface));
+
+  impl = GDK_WAYLAND_SURFACE (surface);
+
+  if (impl->event_queue)
+    {
+      GdkWaylandDisplay *display_wayland =
+        GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+
+      display_wayland->event_queues =
+        g_list_remove (display_wayland->event_queues, surface);
+      g_clear_pointer (&impl->event_queue, wl_event_queue_destroy);
+    }
+
+  G_OBJECT_CLASS (gdk_wayland_surface_parent_class)->dispose (object);
+}
+
 static void
 gdk_wayland_surface_finalize (GObject *object)
 {
@@ -1057,9 +1098,13 @@ gdk_wayland_surface_create_surface (GdkSurface *surface)
 {
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+  struct wl_surface *wl_surface;
+
+  wl_surface = wl_compositor_create_surface (display_wayland->compositor);
+  wl_proxy_set_queue ((struct wl_proxy *) wl_surface, impl->event_queue);
+  wl_surface_add_listener (wl_surface, &surface_listener, surface);
 
-  impl->display_server.wl_surface = wl_compositor_create_surface (display_wayland->compositor);
-  wl_surface_add_listener (impl->display_server.wl_surface, &surface_listener, surface);
+  impl->display_server.wl_surface = wl_surface;
 }
 
 static void
@@ -1334,6 +1379,8 @@ create_xdg_toplevel_resources (GdkSurface *surface)
   impl->display_server.xdg_surface =
     xdg_wm_base_get_xdg_surface (display_wayland->xdg_wm_base,
                                  impl->display_server.wl_surface);
+  wl_proxy_set_queue ((struct wl_proxy *) impl->display_server.xdg_surface,
+                      impl->event_queue);
   xdg_surface_add_listener (impl->display_server.xdg_surface,
                             &xdg_surface_listener,
                             surface);
@@ -2183,6 +2230,9 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface     *surface,
       impl->display_server.xdg_surface =
         xdg_wm_base_get_xdg_surface (display->xdg_wm_base,
                                      impl->display_server.wl_surface);
+
+      wl_proxy_set_queue ((struct wl_proxy *) impl->display_server.xdg_surface,
+                          impl->event_queue);
       xdg_surface_add_listener (impl->display_server.xdg_surface,
                                 &xdg_surface_listener,
                                 surface);
@@ -2987,6 +3037,8 @@ gdk_wayland_surface_init_gtk_surface (GdkSurface *surface)
   impl->display_server.gtk_surface =
     gtk_shell1_get_gtk_surface (display->gtk_shell,
                                 impl->display_server.wl_surface);
+  wl_proxy_set_queue ((struct wl_proxy *) impl->display_server.gtk_surface,
+                      impl->event_queue);
   gdk_surface_set_geometry_hints (surface,
                                  &impl->geometry_hints,
                                  impl->geometry_mask);
@@ -3752,6 +3804,8 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GdkSurfaceClass *impl_class = GDK_SURFACE_CLASS (klass);
 
+  object_class->constructed = gdk_wayland_surface_constructed;
+  object_class->dispose = gdk_wayland_surface_dispose;
   object_class->finalize = gdk_wayland_surface_finalize;
 
   impl_class->show = gdk_wayland_surface_show;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]