[gtk+] paned: Be careful about showing windows



commit f96777ea02e58ec4641d55a68e8b136ff4e79bae
Author: Benjamin Otte <otte redhat com>
Date:   Wed May 11 00:46:08 2011 +0200

    paned: Be careful about showing windows
    
    The previous code failed to account for all child visibility and paned
    mapedness invariants which could cause stray GDK windows to appear.
    Not good.
    
    Credit goes to Xan for triggering it.

 gtk/gtkpaned.c |   91 ++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 65 insertions(+), 26 deletions(-)
---
diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c
index 62c66bb..0fe290e 100644
--- a/gtk/gtkpaned.c
+++ b/gtk/gtkpaned.c
@@ -89,6 +89,11 @@
  * </example>
  */
 
+enum {
+  CHILD1,
+  CHILD2
+};
+
 struct _GtkPanedPrivate
 {
   GtkPaned       *first_paned;
@@ -978,6 +983,50 @@ flip_child (GtkWidget     *widget,
   child_pos->x = 2 * x + width - child_pos->x - child_pos->width;
 }
 
+static gboolean
+gtk_paned_get_child_visible (GtkPaned  *paned,
+                             guint      id)
+{
+  GtkPanedPrivate *priv = paned->priv;
+  GtkWidget *child;
+
+  child = id == CHILD1 ? priv->child1 : priv->child2;
+
+  return (child != NULL && gtk_widget_get_child_visible (child));
+}
+
+static void
+gtk_paned_set_child_visible (GtkPaned  *paned,
+                             guint      id,
+                             gboolean   visible)
+{
+  GtkPanedPrivate *priv = paned->priv;
+  GtkWidget *child;
+  gboolean was_visible;
+
+  was_visible = gtk_paned_get_child_visible (paned, id);
+
+  child = id == CHILD1 ? priv->child1 : priv->child2;
+
+  if (child == NULL)
+    return;
+
+  if (was_visible == visible)
+    return;
+
+  gtk_widget_set_child_visible (child, visible);
+
+  if (gtk_widget_get_mapped (GTK_WIDGET (paned)))
+    {
+      GdkWindow *window = id == CHILD1 ? priv->child1_window : priv->child2_window;
+
+      if (visible)
+        gdk_window_show (window);
+      else
+        gdk_window_hide (window);
+    }
+}
+
 static void
 gtk_paned_child_allocate (GtkWidget           *child,
                           GdkWindow           *child_window, /* can be NULL */
@@ -1182,10 +1231,6 @@ gtk_paned_size_allocate (GtkWidget     *widget,
                                     &window2_allocation,
                                     &child2_allocation);
 	}
-      if (priv->child1_window)
-        gdk_window_show (priv->child1_window);
-      if (priv->child2_window)
-        gdk_window_show (priv->child2_window);
     }
   else
     {
@@ -1195,9 +1240,9 @@ gtk_paned_size_allocate (GtkWidget     *widget,
 	gdk_window_hide (priv->handle);
 
       if (priv->child1)
-	gtk_widget_set_child_visible (priv->child1, TRUE);
+        gtk_paned_set_child_visible (paned, 0, TRUE);
       if (priv->child2)
-	gtk_widget_set_child_visible (priv->child2, TRUE);
+        gtk_paned_set_child_visible (paned, 1, TRUE);
 
       window_allocation.x = allocation->x;
       window_allocation.y = allocation->y;
@@ -1213,10 +1258,6 @@ gtk_paned_size_allocate (GtkWidget     *widget,
                                     priv->child1_window,
                                     &window_allocation,
                                     &child_allocation);
-          if (priv->child1_window)
-            gdk_window_show (priv->child1_window);
-          if (priv->child2_window)
-            gdk_window_hide (priv->child2_window);
         }
       else if (priv->child2 && gtk_widget_get_visible (priv->child2))
         {
@@ -1224,10 +1265,6 @@ gtk_paned_size_allocate (GtkWidget     *widget,
                                     priv->child2_window,
                                     &window_allocation,
                                     &child_allocation);
-          if (priv->child2_window)
-            gdk_window_show (priv->child2_window);
-          if (priv->child1_window)
-            gdk_window_hide (priv->child1_window);
         }
     }
 }
@@ -1376,9 +1413,9 @@ gtk_paned_map (GtkWidget *widget)
       priv->child2 && gtk_widget_get_visible (priv->child2))
     gdk_window_show (priv->handle);
 
-  if (priv->child1 && gtk_widget_get_visible (priv->child1))
+  if (priv->child1 && gtk_widget_get_visible (priv->child1) && gtk_widget_get_child_visible (priv->child1))
     gdk_window_show (priv->child1_window);
-  if (priv->child2 && gtk_widget_get_visible (priv->child2))
+  if (priv->child2 && gtk_widget_get_visible (priv->child2) && gtk_widget_get_child_visible (priv->child2))
     gdk_window_show (priv->child2_window);
 
   GTK_WIDGET_CLASS (gtk_paned_parent_class)->map (widget);
@@ -1392,8 +1429,10 @@ gtk_paned_unmap (GtkWidget *widget)
 
   gdk_window_hide (priv->handle);
   
-  gdk_window_hide (priv->child1_window);
-  gdk_window_hide (priv->child2_window);
+  if (gdk_window_is_visible (priv->child1_window))
+    gdk_window_hide (priv->child1_window);
+  if (gdk_window_is_visible (priv->child2_window))
+    gdk_window_hide (priv->child2_window);
 
   GTK_WIDGET_CLASS (gtk_paned_parent_class)->unmap (widget);
 }
@@ -1863,25 +1902,25 @@ gtk_paned_remove (GtkContainer *container,
 
   if (priv->child1 == widget)
     {
+      if (priv->child1_window && gdk_window_is_visible (priv->child1_window))
+        gdk_window_hide (priv->child1_window);
+
       gtk_widget_unparent (widget);
 
       priv->child1 = NULL;
 
-      if (priv->child1_window)
-        gdk_window_hide (priv->child1_window);
-
       if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
 	gtk_widget_queue_resize_no_redraw (GTK_WIDGET (container));
     }
   else if (priv->child2 == widget)
     {
+      if (priv->child2_window && gdk_window_is_visible (priv->child2_window))
+        gdk_window_hide (priv->child2_window);
+
       gtk_widget_unparent (widget);
 
       priv->child2 = NULL;
 
-      if (priv->child2_window)
-        gdk_window_hide (priv->child2_window);
-
       if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
 	gtk_widget_queue_resize_no_redraw (GTK_WIDGET (container));
     }
@@ -2068,10 +2107,10 @@ gtk_paned_calc_position (GtkPaned *paned,
 			      priv->max_position);
 
   if (priv->child1)
-    gtk_widget_set_child_visible (priv->child1, priv->child1_size != 0);
+    gtk_paned_set_child_visible (paned, 0, priv->child1_size != 0);
   
   if (priv->child2)
-    gtk_widget_set_child_visible (priv->child2, priv->child1_size != allocation); 
+    gtk_paned_set_child_visible (paned, 1, priv->child1_size != allocation); 
 
   g_object_freeze_notify (G_OBJECT (paned));
   if (priv->child1_size != old_position)



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