[gtk: 83/88] gdk: Replace 'WITHDRAWN' state with async 'is-mapped' boolean




commit d2c95a1b13ee710fcfc69a592be669bcea4b26e8
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Mon Dec 7 18:18:38 2020 +0100

    gdk: Replace 'WITHDRAWN' state with async 'is-mapped' boolean
    
    It was used by all surfaces to track 'is-mapped', but still part of the
    GdkToplevelState, and is now replaced with a separate boolean in the
    GdkSurface structure.
    
    It also caused issues when a widget was unmapped, and due to that
    unmapped a popover which hid its corresponding surface. When this
    surface was hidden, it emitted a state change event, which would then go
    back into GTK and queue a resize on popover widget, which would travel
    back down to the widget that was originally unmapped, causing confusino
    when doing future allocations.
    
    To summarize, one should not hide widgets during allocation, and to
    avoid this, make this new is-mapped boolean asynchronous when hiding a
    surface, meaning the notification event for the changed mapped state
    will be emitted in an idle callback. This avoids the above described
    reentry issue.

 gdk/broadway/gdksurface-broadway.c |  4 +-
 gdk/gdksurface.c                   | 90 ++++++++++++++++++++++++++++++--------
 gdk/gdksurfaceprivate.h            | 10 ++++-
 gdk/gdktoplevel.c                  |  2 +-
 gdk/gdktoplevel.h                  | 34 +++++++-------
 gdk/macos/gdkmacossurface.c        |  2 +-
 gdk/wayland/gdksurface-wayland.c   |  2 +-
 gdk/win32/gdkevents-win32.c        |  6 +--
 gdk/win32/gdkmain-win32.c          |  5 ---
 gdk/win32/gdksurface-win32.c       |  8 ++--
 gdk/x11/gdkdisplay-x11.c           |  2 +-
 gdk/x11/gdkdrag-x11.c              |  2 +-
 gdk/x11/gdkglcontext-x11.c         |  2 +-
 gdk/x11/gdksurface-x11.c           | 12 +++--
 gtk/gtktooltipwindow.c             | 24 +++-------
 gtk/gtkwindow.c                    |  3 +-
 tests/testgtk.c                    |  2 -
 17 files changed, 122 insertions(+), 88 deletions(-)
---
diff --git a/gdk/broadway/gdksurface-broadway.c b/gdk/broadway/gdksurface-broadway.c
index 30ba9ff51b..d44b2281f0 100644
--- a/gdk/broadway/gdksurface-broadway.c
+++ b/gdk/broadway/gdksurface-broadway.c
@@ -601,7 +601,7 @@ gdk_broadway_surface_layout_popup (GdkSurface     *surface,
 static void
 show_popup (GdkSurface *surface)
 {
-  gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+  gdk_surface_set_is_mapped (surface, TRUE);
   gdk_broadway_surface_show (surface, FALSE);
   gdk_surface_invalidate_rect (surface, NULL);
 }
@@ -1521,7 +1521,7 @@ show_surface (GdkSurface *surface)
   was_mapped = GDK_SURFACE_IS_MAPPED (surface);
 
   if (!was_mapped)
-    gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+    gdk_surface_set_is_mapped (surface, TRUE);
 
   gdk_broadway_surface_show (surface, FALSE);
 
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 27b775982c..012864479a 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -114,6 +114,9 @@ static void update_cursor               (GdkDisplay *display,
 static void gdk_surface_set_frame_clock (GdkSurface      *surface,
                                          GdkFrameClock  *clock);
 
+static void gdk_surface_queue_set_is_mapped (GdkSurface *surface,
+                                             gboolean    is_mapped);
+
 
 static guint signals[LAST_SIGNAL] = { 0 };
 static GParamSpec *properties[LAST_PROP] = { NULL, };
@@ -472,7 +475,7 @@ gdk_surface_init (GdkSurface *surface)
 {
   /* 0-initialization is good for all other fields. */
 
-  surface->state = GDK_TOPLEVEL_STATE_WITHDRAWN;
+  surface->state = 0;
   surface->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
   surface->width = 1;
   surface->height = 1;
@@ -923,7 +926,10 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface,
 
   _gdk_surface_clear_update_area (surface);
 
-  surface->state |= GDK_TOPLEVEL_STATE_WITHDRAWN;
+  g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove);
+  surface->is_mapped = FALSE;
+  surface->pending_is_mapped = FALSE;
+
   surface->destroyed = TRUE;
 
   surface_remove_from_pointer_info (surface, surface->display);
@@ -1696,14 +1702,7 @@ gdk_surface_hide (GdkSurface *surface)
 
   was_mapped = GDK_SURFACE_IS_MAPPED (surface);
 
-  if (GDK_SURFACE_IS_MAPPED (surface))
-    {
-      gdk_synthesize_surface_state (surface,
-                                    surface->state & ~GDK_TOPLEVEL_STATE_WITHDRAWN,
-                                    GDK_TOPLEVEL_STATE_WITHDRAWN);
-      surface->pending_unset_flags = 0;
-      surface->pending_set_flags = 0;
-    }
+  gdk_surface_queue_set_is_mapped (surface, FALSE);
 
   if (was_mapped)
     {
@@ -2614,7 +2613,6 @@ void
 gdk_surface_set_state (GdkSurface      *surface,
                        GdkToplevelState new_state)
 {
-  gboolean was_mapped, mapped;
   gboolean was_sticky, sticky;
   g_return_if_fail (GDK_IS_SURFACE (surface));
 
@@ -2626,20 +2624,15 @@ gdk_surface_set_state (GdkSurface      *surface,
    * inconsistent state to the user.
    */
 
-  was_mapped = GDK_SURFACE_IS_MAPPED (surface);
   was_sticky = GDK_SURFACE_IS_STICKY (surface);
 
   surface->state = new_state;
 
-  mapped = GDK_SURFACE_IS_MAPPED (surface);
   sticky = GDK_SURFACE_IS_STICKY (surface);
 
   if (GDK_IS_TOPLEVEL (surface))
     g_object_notify (G_OBJECT (surface), "state");
 
-  if (was_mapped != mapped)
-    g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]);
-
   if (was_sticky != sticky)
     g_object_notify (G_OBJECT (surface), "sticky");
 }
@@ -2673,12 +2666,73 @@ gdk_surface_apply_state_change (GdkSurface *surface)
   gdk_synthesize_surface_state (surface,
                                 surface->pending_unset_flags,
                                 surface->pending_set_flags);
-  if (surface->pending_unset_flags & GDK_TOPLEVEL_STATE_WITHDRAWN)
-    gdk_surface_invalidate_rect (surface, NULL);
   surface->pending_unset_flags = 0;
   surface->pending_set_flags = 0;
 }
 
+static gboolean
+set_is_mapped_idle (gpointer user_data)
+{
+  GdkSurface *surface = GDK_SURFACE (user_data);
+
+  surface->set_is_mapped_source_id = 0;
+
+  g_return_val_if_fail (surface->pending_is_mapped != surface->is_mapped,
+                        G_SOURCE_REMOVE);
+
+  surface->is_mapped = surface->pending_is_mapped;
+  if (surface->is_mapped)
+    gdk_surface_invalidate_rect (surface, NULL);
+
+  g_object_notify (G_OBJECT (surface), "mapped");
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+gdk_surface_set_is_mapped (GdkSurface *surface,
+                           gboolean    is_mapped)
+{
+  gboolean was_mapped;
+
+  if (surface->pending_is_mapped != surface->is_mapped)
+    g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove);
+
+  surface->pending_is_mapped = is_mapped;
+
+  was_mapped = surface->is_mapped;
+  surface->is_mapped = is_mapped;
+  if (surface->is_mapped)
+    gdk_surface_invalidate_rect (surface, NULL);
+
+  if (was_mapped != is_mapped)
+    g_object_notify (G_OBJECT (surface), "mapped");
+}
+
+static void
+gdk_surface_queue_set_is_mapped (GdkSurface *surface,
+                                 gboolean    is_mapped)
+{
+  if (surface->pending_is_mapped == is_mapped)
+    return;
+
+  surface->pending_is_mapped = is_mapped;
+
+  if (surface->is_mapped == surface->pending_is_mapped)
+    {
+      g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove);
+    }
+  else
+    {
+      g_return_if_fail (!surface->set_is_mapped_source_id);
+
+      surface->set_is_mapped_source_id =
+        g_idle_add_full (G_PRIORITY_HIGH - 10,
+                         set_is_mapped_idle,
+                         surface, NULL);
+    }
+}
+
 static gboolean
 check_autohide (GdkEvent *event)
 {
diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h
index 4c879fc2cb..27a3966fe7 100644
--- a/gdk/gdksurfaceprivate.h
+++ b/gdk/gdksurfaceprivate.h
@@ -44,6 +44,10 @@ struct _GdkSurface
   GdkSurface *parent;        /* for popups */
   GList *children;           /* popups */
 
+  guint set_is_mapped_source_id;
+  gboolean pending_is_mapped;
+  gboolean is_mapped;
+
   gpointer widget;
 
   int x;
@@ -167,12 +171,14 @@ struct _GdkSurfaceClass
 
 #define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed)
 
-#define GDK_SURFACE_IS_MAPPED(surface) (((surface)->state & GDK_TOPLEVEL_STATE_WITHDRAWN) == 0)
-
+#define GDK_SURFACE_IS_MAPPED(surface) ((surface)->pending_is_mapped)
 
 void gdk_surface_set_state (GdkSurface      *surface,
                             GdkToplevelState  new_state);
 
+void gdk_surface_set_is_mapped (GdkSurface *surface,
+                                gboolean    is_mapped);
+
 GdkMonitor * gdk_surface_get_layout_monitor (GdkSurface      *surface,
                                              GdkPopupLayout  *layout,
                                              void           (*get_bounds) (GdkMonitor   *monitor,
diff --git a/gdk/gdktoplevel.c b/gdk/gdktoplevel.c
index 4cff2bb3dd..13eb38cda1 100644
--- a/gdk/gdktoplevel.c
+++ b/gdk/gdktoplevel.c
@@ -123,7 +123,7 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
       g_param_spec_flags ("state",
                           P_("State"),
                           P_("State"),
-                          GDK_TYPE_TOPLEVEL_STATE, GDK_TOPLEVEL_STATE_WITHDRAWN,
+                          GDK_TYPE_TOPLEVEL_STATE, 0,
                           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   g_object_interface_install_property (iface,
       g_param_spec_string ("title",
diff --git a/gdk/gdktoplevel.h b/gdk/gdktoplevel.h
index 28402feb10..fb29315710 100644
--- a/gdk/gdktoplevel.h
+++ b/gdk/gdktoplevel.h
@@ -71,7 +71,6 @@ typedef enum
 
 /**
  * GdkToplevelState:
- * @GDK_TOPLEVEL_STATE_WITHDRAWN: the surface is not shown
  * @GDK_TOPLEVEL_STATE_MINIMIZED: the surface is minimized
  * @GDK_TOPLEVEL_STATE_MAXIMIZED: the surface is maximized
  * @GDK_TOPLEVEL_STATE_STICKY: the surface is sticky
@@ -98,23 +97,22 @@ typedef enum
  */
 typedef enum
 {
-  GDK_TOPLEVEL_STATE_WITHDRAWN        = 1 << 0,
-  GDK_TOPLEVEL_STATE_MINIMIZED        = 1 << 1,
-  GDK_TOPLEVEL_STATE_MAXIMIZED        = 1 << 2,
-  GDK_TOPLEVEL_STATE_STICKY           = 1 << 3,
-  GDK_TOPLEVEL_STATE_FULLSCREEN       = 1 << 4,
-  GDK_TOPLEVEL_STATE_ABOVE            = 1 << 5,
-  GDK_TOPLEVEL_STATE_BELOW            = 1 << 6,
-  GDK_TOPLEVEL_STATE_FOCUSED          = 1 << 7,
-  GDK_TOPLEVEL_STATE_TILED            = 1 << 8,
-  GDK_TOPLEVEL_STATE_TOP_TILED        = 1 << 9,
-  GDK_TOPLEVEL_STATE_TOP_RESIZABLE    = 1 << 10,
-  GDK_TOPLEVEL_STATE_RIGHT_TILED      = 1 << 11,
-  GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE  = 1 << 12,
-  GDK_TOPLEVEL_STATE_BOTTOM_TILED     = 1 << 13,
-  GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE = 1 << 14,
-  GDK_TOPLEVEL_STATE_LEFT_TILED       = 1 << 15,
-  GDK_TOPLEVEL_STATE_LEFT_RESIZABLE   = 1 << 16
+  GDK_TOPLEVEL_STATE_MINIMIZED        = 1 << 0,
+  GDK_TOPLEVEL_STATE_MAXIMIZED        = 1 << 1,
+  GDK_TOPLEVEL_STATE_STICKY           = 1 << 2,
+  GDK_TOPLEVEL_STATE_FULLSCREEN       = 1 << 3,
+  GDK_TOPLEVEL_STATE_ABOVE            = 1 << 4,
+  GDK_TOPLEVEL_STATE_BELOW            = 1 << 5,
+  GDK_TOPLEVEL_STATE_FOCUSED          = 1 << 6,
+  GDK_TOPLEVEL_STATE_TILED            = 1 << 7,
+  GDK_TOPLEVEL_STATE_TOP_TILED        = 1 << 8,
+  GDK_TOPLEVEL_STATE_TOP_RESIZABLE    = 1 << 9,
+  GDK_TOPLEVEL_STATE_RIGHT_TILED      = 1 << 10,
+  GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE  = 1 << 11,
+  GDK_TOPLEVEL_STATE_BOTTOM_TILED     = 1 << 12,
+  GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE = 1 << 13,
+  GDK_TOPLEVEL_STATE_LEFT_TILED       = 1 << 14,
+  GDK_TOPLEVEL_STATE_LEFT_RESIZABLE   = 1 << 15
 } GdkToplevelState;
 
 
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index 705ae1d5ce..5e528ca8e2 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -762,7 +762,7 @@ _gdk_macos_surface_show (GdkMacosSurface *self)
   was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
 
   if (!was_mapped)
-    gdk_synthesize_surface_state (GDK_SURFACE (self), GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+    gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
 
   _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display));
 
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index 9ce5669bac..602d76b773 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -1602,7 +1602,7 @@ maybe_notify_mapped (GdkSurface *surface)
     return;
 
   if (!GDK_SURFACE_IS_MAPPED (surface))
-    gdk_surface_queue_state_change (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+    gdk_surface_set_is_mapped (surface, TRUE);
 }
 
 static void
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 1a50cdb5dd..dbdcab2c43 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -2825,11 +2825,6 @@ gdk_event_translate (MSG *msg,
          set_bits = 0;
          unset_bits = 0;
 
-         if (IsWindowVisible (msg->hwnd))
-           unset_bits |= GDK_TOPLEVEL_STATE_WITHDRAWN;
-         else
-           set_bits |= GDK_TOPLEVEL_STATE_WITHDRAWN;
-
          if (IsIconic (msg->hwnd))
            set_bits |= GDK_TOPLEVEL_STATE_MINIMIZED;
          else
@@ -2840,6 +2835,7 @@ gdk_event_translate (MSG *msg,
          else
            unset_bits |= GDK_TOPLEVEL_STATE_MAXIMIZED;
 
+         gdk_surface_set_is_mapped (window, !!IsWindowVisible (msg->hwnd));
          gdk_synthesize_surface_state (window, unset_bits, set_bits);
 
          new_state = window->state;
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index 73d0420011..6d4e44cfc7 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -274,11 +274,6 @@ _gdk_win32_surface_state_to_string (GdkToplevelState state)
   if (state & GDK_TOPLEVEL_STATE_ ## x)                        \
     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
 
-  /* For clarity, also show the complement of WITHDRAWN, i.e. "MAPPED" */
-  if (!(state & GDK_TOPLEVEL_STATE_WITHDRAWN))
-    (bufp += sprintf (bufp, "MAPPED"), s = "|");
-
-  BIT (WITHDRAWN);
   BIT (MINIMIZED);
   BIT (MAXIMIZED);
   BIT (STICKY);
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index a7b1bda775..263fcc6c60 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -1006,9 +1006,7 @@ gdk_win32_surface_hide (GdkSurface *window)
                           _gdk_win32_surface_state_to_string (window->state)));
 
   if (GDK_SURFACE_IS_MAPPED (window))
-    gdk_synthesize_surface_state (window,
-                                0,
-                                GDK_TOPLEVEL_STATE_WITHDRAWN);
+    gdk_surface_set_is_mapped (window, FALSE);
 
   _gdk_surface_clear_update_area (window);
 
@@ -1262,7 +1260,7 @@ static void
 show_popup (GdkSurface *surface)
 {
   gdk_win32_surface_raise (surface);
-  gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+  gdk_surface_set_is_mapped (surface, TRUE);
   show_window_internal (surface, FALSE, FALSE);
   gdk_surface_invalidate_rect (surface, NULL);
 }
@@ -4924,7 +4922,7 @@ show_surface (GdkSurface *surface)
   was_mapped = GDK_SURFACE_IS_MAPPED (surface);
 
   if (!was_mapped)
-    gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+    gdk_surface_set_is_mapped (surface, TRUE);
 
   gdk_win32_surface_show (surface, FALSE);
 
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 31b06ea53f..4350f2eef8 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -566,7 +566,7 @@ gdk_check_edge_constraints_changed (GdkSurface *surface)
        * messing around with shifts, just make the passed value and GDK's
        * enum values match by shifting to the first tiled state.
        */
-      toplevel->edge_constraints = constraints[0] << 9;
+      toplevel->edge_constraints = constraints[0] << 8;
 
       XFree (constraints);
     }
diff --git a/gdk/x11/gdkdrag-x11.c b/gdk/x11/gdkdrag-x11.c
index 8e40cab447..606cef0f0c 100644
--- a/gdk/x11/gdkdrag-x11.c
+++ b/gdk/x11/gdkdrag-x11.c
@@ -2036,7 +2036,7 @@ _gdk_x11_surface_drag_begin (GdkSurface         *surface,
   if (gdk_x11_surface_get_group (surface))
     gdk_x11_surface_set_group (x11_drag->ipc_surface, surface);
 
-  gdk_synthesize_surface_state (x11_drag->ipc_surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+  gdk_surface_set_is_mapped (x11_drag->ipc_surface, TRUE);
   gdk_x11_surface_show (x11_drag->ipc_surface, FALSE);
 
   x11_drag->drag_surface = create_drag_surface (display);
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index a332773493..d83ef6aaad 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -463,7 +463,7 @@ on_surface_state_changed (GdkGLContext *context)
 {
   GdkSurface *surface = gdk_gl_context_get_surface (context);
 
-  if ((surface->state & GDK_TOPLEVEL_STATE_WITHDRAWN) == 0)
+  if (GDK_SURFACE_IS_MAPPED (surface))
     return;
 
   /* If we're about to withdraw the surface, then we don't care if the frame is
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
index 6680312563..293134371e 100644
--- a/gdk/x11/gdksurface-x11.c
+++ b/gdk/x11/gdksurface-x11.c
@@ -1401,7 +1401,7 @@ update_wm_hints (GdkSurface *surface,
 
   if (!force &&
       !toplevel->is_leader &&
-      surface->state & GDK_TOPLEVEL_STATE_WITHDRAWN)
+      !GDK_SURFACE_IS_MAPPED (surface))
     return;
 
   wm_hints.flags = StateHint | InputHint;
@@ -1608,9 +1608,7 @@ gdk_x11_surface_withdraw (GdkSurface *surface)
   if (!surface->destroyed)
     {
       if (GDK_SURFACE_IS_MAPPED (surface))
-        gdk_synthesize_surface_state (surface,
-                                     0,
-                                     GDK_TOPLEVEL_STATE_WITHDRAWN);
+        gdk_surface_set_is_mapped (surface, FALSE);
 
       g_assert (!GDK_SURFACE_IS_MAPPED (surface));
       XWithdrawWindow (GDK_SURFACE_XDISPLAY (surface),
@@ -1852,7 +1850,7 @@ static void
 show_popup (GdkSurface *surface)
 {
   gdk_x11_surface_raise (surface);
-  gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+  gdk_surface_set_is_mapped (surface, TRUE);
   gdk_x11_surface_show (surface, FALSE);
   gdk_surface_invalidate_rect (surface, NULL);
 }
@@ -5116,7 +5114,7 @@ gdk_x11_toplevel_present (GdkToplevel       *toplevel,
   gdk_surface_request_layout (surface);
 
   if (!was_mapped)
-    gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+    gdk_surface_set_is_mapped (surface, TRUE);
 
   gdk_x11_surface_show (surface, was_mapped);
 
@@ -5287,7 +5285,7 @@ gdk_x11_drag_surface_present (GdkDragSurface *drag_surface,
   GdkSurface *surface = GDK_SURFACE (drag_surface);
 
   gdk_x11_surface_toplevel_resize (surface, width, height);
-  gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
+  gdk_surface_set_is_mapped (surface, TRUE);
   gdk_x11_surface_show (surface, FALSE);
   gdk_surface_invalidate_rect (surface, NULL);
 
diff --git a/gtk/gtktooltipwindow.c b/gtk/gtktooltipwindow.c
index 55c6a882d1..a3dbf83db4 100644
--- a/gtk/gtktooltipwindow.c
+++ b/gtk/gtktooltipwindow.c
@@ -47,7 +47,6 @@ struct _GtkTooltipWindow
   GdkSurface *surface;
   GskRenderer *renderer;
 
-  GdkToplevelState state;
   GtkWidget *relative_to;
   GdkRectangle rect;
   GdkGravity rect_anchor;
@@ -178,21 +177,12 @@ gtk_tooltip_window_native_init (GtkNativeInterface *iface)
 }
 
 static void
-surface_state_changed (GtkWidget *widget)
+mapped_changed (GdkSurface *surface,
+                GParamSpec *pspec,
+                GtkWidget  *widget)
 {
-  GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget);
-  GdkToplevelState new_surface_state;
-  GdkToplevelState changed_mask;
-
-  new_surface_state = gdk_toplevel_get_state (GDK_TOPLEVEL (window->surface));
-  changed_mask = new_surface_state ^ window->state;
-  window->state = new_surface_state;
-
-  if (changed_mask & GDK_TOPLEVEL_STATE_WITHDRAWN)
-    {
-      if (window->state & GDK_TOPLEVEL_STATE_WITHDRAWN)
-        gtk_widget_hide (widget);
-    }
+  if (!gdk_surface_get_mapped (surface))
+    gtk_widget_hide (widget);
 }
 
 static gboolean
@@ -224,7 +214,7 @@ gtk_tooltip_window_realize (GtkWidget *widget)
 
   gdk_surface_set_widget (window->surface, widget);
 
-  g_signal_connect_swapped (window->surface, "notify::state", G_CALLBACK (surface_state_changed), widget);
+  g_signal_connect (window->surface, "notify::mapped", G_CALLBACK (mapped_changed), widget);
   g_signal_connect (window->surface, "render", G_CALLBACK (surface_render), widget);
   g_signal_connect (window->surface, "event", G_CALLBACK (surface_event), widget);
 
@@ -247,7 +237,7 @@ gtk_tooltip_window_unrealize (GtkWidget *widget)
   gsk_renderer_unrealize (window->renderer);
   g_clear_object (&window->renderer);
 
-  g_signal_handlers_disconnect_by_func (window->surface, surface_state_changed, widget);
+  g_signal_handlers_disconnect_by_func (window->surface, mapped_changed, widget);
   g_signal_handlers_disconnect_by_func (window->surface, surface_render, widget);
   g_signal_handlers_disconnect_by_func (window->surface, surface_event, widget);
   gdk_surface_set_widget (window->surface, NULL);
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 176ae22bf5..7e22e4bcbe 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -1503,7 +1503,7 @@ gtk_window_init (GtkWindow *window)
   priv->decorated = TRUE;
   priv->display = gdk_display_get_default ();
 
-  priv->state = GDK_TOPLEVEL_STATE_WITHDRAWN;
+  priv->state = 0;
 
   priv->deletable = TRUE;
   priv->startup_id = NULL;
@@ -4165,6 +4165,7 @@ gtk_window_realize (GtkWidget *widget)
     priv->renderer = gsk_renderer_new_for_surface (surface);
 
   g_signal_connect_swapped (surface, "notify::state", G_CALLBACK (surface_state_changed), widget);
+  g_signal_connect_swapped (surface, "notify::mapped", G_CALLBACK (surface_state_changed), widget);
   g_signal_connect (surface, "render", G_CALLBACK (surface_render), widget);
   g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget);
   g_signal_connect (surface, "compute-size", G_CALLBACK (toplevel_compute_size), widget);
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 06a9f0f06a..077d16136b 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -4531,8 +4531,6 @@ surface_state_callback (GdkSurface  *window,
 
   new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (window));
   msg = g_strconcat ((const char *)g_object_get_data (G_OBJECT (label), "title"), ": ",
-                     (new_state & GDK_TOPLEVEL_STATE_WITHDRAWN) ?
-                     "withdrawn" : "not withdrawn", ", ",
                      (new_state & GDK_TOPLEVEL_STATE_MINIMIZED) ?
                      "minimized" : "not minimized", ", ",
                      (new_state & GDK_TOPLEVEL_STATE_STICKY) ?


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