wayland: Don't destroy the wl_surface on hide()
authorBenjamin Otte <otte@redhat.com>
Thu, 13 Apr 2023 01:33:59 +0000 (03:33 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 13 Apr 2023 02:23:35 +0000 (04:23 +0200)
We want to keep the wl_surface around, because surfaces create their
resources on construct and keep them until destroyed. See the HWND ond
Windows and the XWindow on X11.

This is relevant for graphics resources, where we want to have access
to the VkSurface and eglSurface while the GdkSurface is hidden.
We also want these surfaces to be permanent and not change during the
lifetime of the GdkSurface.

What we can - and must - destroy however are the xdg surfaces, because
those handle visibility on screen.
And we also need to ensure no buffer is attached, so that during the
next creation of the xdg surface we don't get a protocol error.

gdk/wayland/gdkdragsurface-wayland.c
gdk/wayland/gdkpopup-wayland.c
gdk/wayland/gdksurface-wayland-private.h
gdk/wayland/gdksurface-wayland.c
gdk/wayland/gdktoplevel-wayland.c

index a52b7e614823aac06b4e4d8807925253af12ba6c..ed130271fcd682b0839c5a65018f993770dfad3a 100644 (file)
@@ -127,9 +127,6 @@ gdk_wayland_drag_surface_present (GdkDragSurface *drag_surface,
   GdkSurface *surface = GDK_SURFACE (drag_surface);
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
 
-  if (!impl->display_server.wl_surface)
-    gdk_wayland_surface_create_wl_surface (surface);
-
   impl->next_layout.configured_width = width;
   impl->next_layout.configured_height = height;
   impl->next_layout.surface_geometry_dirty = TRUE;
index 4b150d1d309de6c3fb4b5324e21f1b32b8199199..c062c8e3e561df4b19cc810d62ff638941098785 100644 (file)
@@ -1289,11 +1289,6 @@ show_popup (GdkWaylandPopup *wayland_popup,
             int              height,
             GdkPopupLayout  *layout)
 {
-  GdkWaylandSurface *wayland_surface = GDK_WAYLAND_SURFACE (wayland_popup);
-
-  if (!wayland_surface->display_server.wl_surface)
-    gdk_wayland_surface_create_wl_surface (GDK_SURFACE (wayland_popup));
-
   if (wayland_popup->thaw_upon_show)
     {
       wayland_popup->thaw_upon_show = FALSE;
index 1d87cc4b0984e54a007feaff0e4f23602ef24439..614b56bec4f7740e936bfe7dbf9d720f07c6648a 100644 (file)
@@ -104,7 +104,6 @@ struct _GdkWaylandSurfaceClass
 
 #define GDK_WAYLAND_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SURFACE, GdkWaylandSurfaceClass))
 
-void gdk_wayland_surface_create_wl_surface (GdkSurface               *surface);
 void gdk_wayland_surface_update_size       (GdkSurface               *surface,
                                             int32_t                   width,
                                             int32_t                   height,
index 22dede3cf424cb1323741b23eaf551f19e7987db..7e970f4a733145591b380497a8ae1601702bd335 100644 (file)
@@ -481,102 +481,6 @@ gdk_wayland_surface_update_scale (GdkSurface *surface)
                                    &GDK_FRACTIONAL_SCALE_INIT_INT (scale));
 }
 
-GdkSurface *
-_gdk_wayland_display_create_surface (GdkDisplay     *display,
-                                     GdkSurfaceType  surface_type,
-                                     GdkSurface     *parent,
-                                     int             x,
-                                     int             y,
-                                     int             width,
-                                     int             height)
-{
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-  GdkSurface *surface;
-  GdkFrameClock *frame_clock;
-
-  if (parent)
-    frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
-  else
-    frame_clock = _gdk_frame_clock_idle_new ();
-
-  switch (surface_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-      g_warn_if_fail (parent == NULL);
-      surface = g_object_new (GDK_TYPE_WAYLAND_TOPLEVEL,
-                              "display", display,
-                              "frame-clock", frame_clock,
-                              "title", get_default_title (),
-                              NULL);
-      display_wayland->toplevels = g_list_prepend (display_wayland->toplevels, surface);
-      break;
-    case GDK_SURFACE_POPUP:
-      g_warn_if_fail (parent != NULL);
-      surface = g_object_new (GDK_TYPE_WAYLAND_POPUP,
-                              "parent", parent,
-                              "display", display,
-                              "frame-clock", frame_clock,
-                              NULL);
-      break;
-    case GDK_SURFACE_DRAG:
-      g_warn_if_fail (parent == NULL);
-      surface = g_object_new (GDK_TYPE_WAYLAND_DRAG_SURFACE,
-                              "display", display,
-                              "frame-clock", frame_clock,
-                              NULL);
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  if (width > 65535)
-    {
-      g_warning ("Native Surfaces wider than 65535 pixels are not supported");
-      width = 65535;
-    }
-  if (height > 65535)
-    {
-      g_warning ("Native Surfaces taller than 65535 pixels are not supported");
-      height = 65535;
-    }
-
-  surface->x = x;
-  surface->y = y;
-  surface->width = width;
-  surface->height = height;
-
-  g_object_ref (surface);
-
-  /* More likely to be right than just assuming 1 */
-  if (wl_compositor_get_version (display_wayland->compositor) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
-    {
-      GdkMonitor *monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
-      if (monitor)
-        {
-          GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
-          guint32 monitor_scale = gdk_monitor_get_scale_factor (monitor);
-
-          if (monitor_scale != 1)
-            {
-              impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (monitor_scale);
-              impl->buffer_scale_dirty = TRUE;
-            }
-
-          g_object_unref (monitor);
-        }
-    }
-
-  gdk_wayland_surface_create_wl_surface (surface);
-
-  g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), surface);
-  g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), surface);
-
-  g_object_unref (frame_clock);
-
-  return surface;
-}
-
 void
 gdk_wayland_surface_attach_image (GdkSurface           *surface,
                                   cairo_surface_t      *cairo_surface,
@@ -883,7 +787,7 @@ static const struct wl_surface_listener surface_listener = {
   surface_leave
 };
 
-void
+static void
 gdk_wayland_surface_create_wl_surface (GdkSurface *surface)
 {
   GdkWaylandSurface *self = GDK_WAYLAND_SURFACE (surface);
@@ -921,6 +825,102 @@ gdk_wayland_surface_destroy_wl_surface (GdkWaylandSurface *self)
   g_clear_pointer (&self->display_server.outputs, g_slist_free);
 }
 
+GdkSurface *
+_gdk_wayland_display_create_surface (GdkDisplay     *display,
+                                     GdkSurfaceType  surface_type,
+                                     GdkSurface     *parent,
+                                     int             x,
+                                     int             y,
+                                     int             width,
+                                     int             height)
+{
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+  GdkSurface *surface;
+  GdkFrameClock *frame_clock;
+
+  if (parent)
+    frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
+  else
+    frame_clock = _gdk_frame_clock_idle_new ();
+
+  switch (surface_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+      g_warn_if_fail (parent == NULL);
+      surface = g_object_new (GDK_TYPE_WAYLAND_TOPLEVEL,
+                              "display", display,
+                              "frame-clock", frame_clock,
+                              "title", get_default_title (),
+                              NULL);
+      display_wayland->toplevels = g_list_prepend (display_wayland->toplevels, surface);
+      break;
+    case GDK_SURFACE_POPUP:
+      g_warn_if_fail (parent != NULL);
+      surface = g_object_new (GDK_TYPE_WAYLAND_POPUP,
+                              "parent", parent,
+                              "display", display,
+                              "frame-clock", frame_clock,
+                              NULL);
+      break;
+    case GDK_SURFACE_DRAG:
+      g_warn_if_fail (parent == NULL);
+      surface = g_object_new (GDK_TYPE_WAYLAND_DRAG_SURFACE,
+                              "display", display,
+                              "frame-clock", frame_clock,
+                              NULL);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  if (width > 65535)
+    {
+      g_warning ("Native Surfaces wider than 65535 pixels are not supported");
+      width = 65535;
+    }
+  if (height > 65535)
+    {
+      g_warning ("Native Surfaces taller than 65535 pixels are not supported");
+      height = 65535;
+    }
+
+  surface->x = x;
+  surface->y = y;
+  surface->width = width;
+  surface->height = height;
+
+  g_object_ref (surface);
+
+  /* More likely to be right than just assuming 1 */
+  if (wl_compositor_get_version (display_wayland->compositor) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
+    {
+      GdkMonitor *monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
+      if (monitor)
+        {
+          GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+          guint32 monitor_scale = gdk_monitor_get_scale_factor (monitor);
+
+          if (monitor_scale != 1)
+            {
+              impl->scale = GDK_FRACTIONAL_SCALE_INIT_INT (monitor_scale);
+              impl->buffer_scale_dirty = TRUE;
+            }
+
+          g_object_unref (monitor);
+        }
+    }
+
+  gdk_wayland_surface_create_wl_surface (surface);
+
+  g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), surface);
+  g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), surface);
+
+  g_object_unref (frame_clock);
+
+  return surface;
+}
+
 static void
 maybe_notify_mapped (GdkSurface *surface)
 {
@@ -1048,53 +1048,49 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
 {
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
 
+  if (!impl->mapped)
+    return;
+
   unmap_popups_for_surface (surface);
 
-  if (impl->display_server.wl_surface)
+  if (impl->display_server.egl_window)
     {
-      if (impl->display_server.egl_window)
-        {
-          gdk_surface_set_egl_native_window (surface, NULL);
-          wl_egl_window_destroy (impl->display_server.egl_window);
-          impl->display_server.egl_window = NULL;
-        }
+      gdk_surface_set_egl_native_window (surface, NULL);
+      wl_egl_window_destroy (impl->display_server.egl_window);
+      impl->display_server.egl_window = NULL;
+    }
 
-      impl->awaiting_frame = FALSE;
-      if (impl->awaiting_frame_frozen)
-        {
-          impl->awaiting_frame_frozen = FALSE;
-          gdk_surface_thaw_updates (surface);
-        }
+  impl->awaiting_frame = FALSE;
+  if (impl->awaiting_frame_frozen)
+    {
+      impl->awaiting_frame_frozen = FALSE;
+      gdk_surface_thaw_updates (surface);
+    }
 
-      GDK_WAYLAND_SURFACE_GET_CLASS (impl)->hide_surface (impl);
+  GDK_WAYLAND_SURFACE_GET_CLASS (impl)->hide_surface (impl);
 
-      if (impl->display_server.xdg_surface)
-        {
-          xdg_surface_destroy (impl->display_server.xdg_surface);
-          impl->display_server.xdg_surface = NULL;
-          if (!impl->initial_configure_received)
-            gdk_surface_thaw_updates (surface);
-          else
-            impl->initial_configure_received = FALSE;
-        }
-      if (impl->display_server.zxdg_surface_v6)
-        {
-          g_clear_pointer (&impl->display_server.zxdg_surface_v6, zxdg_surface_v6_destroy);
-          if (!impl->initial_configure_received)
-            gdk_surface_thaw_updates (surface);
-          else
-            impl->initial_configure_received = FALSE;
-        }
-
-      gdk_wayland_surface_destroy_wl_surface (impl);
+  if (impl->display_server.xdg_surface)
+    {
+      xdg_surface_destroy (impl->display_server.xdg_surface);
+      impl->display_server.xdg_surface = NULL;
+      if (!impl->initial_configure_received)
+        gdk_surface_thaw_updates (surface);
+      else
+        impl->initial_configure_received = FALSE;
+    }
+  if (impl->display_server.zxdg_surface_v6)
+    {
+      g_clear_pointer (&impl->display_server.zxdg_surface_v6, zxdg_surface_v6_destroy);
+      if (!impl->initial_configure_received)
+        gdk_surface_thaw_updates (surface);
+      else
+        impl->initial_configure_received = FALSE;
     }
 
+  wl_surface_attach (impl->display_server.wl_surface, NULL, 0, 0);
+  wl_surface_commit (impl->display_server.wl_surface);
+
   impl->has_uncommitted_ack_configure = FALSE;
-  impl->input_region_dirty = TRUE;
-  impl->opaque_region_dirty = TRUE;
-  impl->viewport_dirty = TRUE;
-  if (!gdk_fractional_scale_equal (&impl->scale, &GDK_FRACTIONAL_SCALE_INIT_INT (1)))
-    impl->buffer_scale_dirty = TRUE;
 
   impl->last_sent_window_geometry = (GdkRectangle) { 0 };
   impl->mapped = FALSE;
@@ -1235,6 +1231,8 @@ gdk_wayland_surface_destroy (GdkSurface *surface,
 
   gdk_wayland_surface_hide_surface (surface);
 
+  gdk_wayland_surface_destroy_wl_surface (GDK_WAYLAND_SURFACE(surface));
+
   frame_clock = gdk_surface_get_frame_clock (surface);
   g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_before_paint, surface);
   g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_after_paint, surface);
index 6954795f0e7cf8e7018bcc3544f2b107396e6a46..416aab4840766b391b084496008ba9e24779c66d 100644 (file)
@@ -1526,9 +1526,6 @@ gdk_wayland_toplevel_show (GdkWaylandToplevel *toplevel)
 {
   GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (toplevel);
 
-  if (!impl->display_server.wl_surface)
-    gdk_wayland_surface_create_wl_surface (GDK_SURFACE (impl));
-
   if (impl->mapped)
     return;