[gtk+] Add invariant that a child is unmapped if parent is unmapped



commit b67c5af55bf611c013b2c43e6878281abd773530
Author: Havoc Pennington <hp pobox com>
Date:   Mon Dec 20 12:58:04 2010 -0500

    Add invariant that a child is unmapped if parent is unmapped
    
    Requires fixes to GtkContainer and GtkWindow to unmap their
    children, rather than just withdrawing or hiding the container
    window.
    
    Requires fix to GtkHandleBox to chain up to GtkContainer unmap.
    
    Historically we avoided these unmaps for efficiency reasons,
    but these days it's a bigger problem that there's no way
    for child widgets to know that one of their ancestors has
    become unmapped.

 docs/widget_system.txt |    2 +-
 gtk/gtkcontainer.c     |   13 +++++++++----
 gtk/gtkhandlebox.c     |    2 ++
 gtk/gtkwidget.c        |   12 ++++++++++++
 gtk/gtkwindow.c        |    5 +++++
 5 files changed, 29 insertions(+), 5 deletions(-)
---
diff --git a/docs/widget_system.txt b/docs/widget_system.txt
index 1c2867c..9463f10 100644
--- a/docs/widget_system.txt
+++ b/docs/widget_system.txt
@@ -255,7 +255,7 @@ In the following
 
    widget->parent && GTK_WIDGET_MAPPED (widget->parent) && 
      GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_CHILD_VISIBLE 
-       => GTK_WIDGET_MAPPED (widget)
+       <=> GTK_WIDGET_MAPPED (widget)
 
 Note:, the definition
 
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index a512037..0ae0827 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -3110,12 +3110,17 @@ gtk_container_unmap (GtkWidget *widget)
 {
   gtk_widget_set_mapped (widget, FALSE);
 
+  /* hide our window first so user doesn't see all the child windows
+   * vanishing one by one.  (only matters these days if one of the
+   * children has an actual native window instead of client-side
+   * window, e.g. a GtkSocket would)
+   */
   if (gtk_widget_get_has_window (widget))
     gdk_window_hide (gtk_widget_get_window (widget));
-  else
-    gtk_container_forall (GTK_CONTAINER (widget),
-			  (GtkCallback)gtk_widget_unmap,
-			  NULL);
+
+  gtk_container_forall (GTK_CONTAINER (widget),
+                        (GtkCallback)gtk_widget_unmap,
+                        NULL);
 }
 
 /**
diff --git a/gtk/gtkhandlebox.c b/gtk/gtkhandlebox.c
index 1e02e84..2b1f906 100644
--- a/gtk/gtkhandlebox.c
+++ b/gtk/gtkhandlebox.c
@@ -397,6 +397,8 @@ gtk_handle_box_unmap (GtkWidget *widget)
       gdk_window_hide (priv->float_window);
       priv->float_window_mapped = FALSE;
     }
+
+  GTK_WIDGET_CLASS (gtk_handle_box_parent_class)->unmap (widget);
 }
 
 static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index d3ff2b8..92e4278 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8722,6 +8722,18 @@ gtk_widget_verify_invariants (GtkWidget *widget)
                        G_OBJECT_TYPE_NAME (parent), parent,
                        G_OBJECT_TYPE_NAME (widget), widget);
         }
+      else if (!widget->priv->toplevel)
+        {
+          /* No parent or parent not mapped on non-toplevel implies... */
+
+          if (widget->priv->mapped && !widget->priv->in_reparent)
+            g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
+                       G_OBJECT_TYPE_NAME (widget), widget,
+                       widget->priv->visible,
+                       widget->priv->child_visible,
+                       parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
+                       parent ? parent->priv->mapped : FALSE);
+        }
     }
 
   if (!widget->priv->realized)
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 6a782ce..1a77b1f 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -4828,6 +4828,7 @@ gtk_window_unmap (GtkWidget *widget)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = window->priv;
+  GtkWidget *child;
   GtkWindowGeometryInfo *info;
   GdkWindow *gdk_window;
   GdkWindowState state;
@@ -4862,6 +4863,10 @@ gtk_window_unmap (GtkWidget *widget)
   priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0;
   priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0;
   priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0;
+
+  child = gtk_bin_get_child (&(window->bin));
+  if (child)
+    gtk_widget_unmap (child);
 }
 
 static void



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