summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2011-05-11 00:46:08 +0200
committerBenjamin Otte <otte@redhat.com>2011-05-11 00:47:23 +0200
commitf96777ea02e58ec4641d55a68e8b136ff4e79bae (patch)
tree3c0d3b193b7d3cd7059157af33b228d6d14228d4
parent1ab425b1326ce09604d5570bb48465210f19e501 (diff)
downloadgtk+-f96777ea02e58ec4641d55a68e8b136ff4e79bae.tar.gz
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.
-rw-r--r--gtk/gtkpaned.c91
1 files changed, 65 insertions, 26 deletions
diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c
index 62c66bbfa6..0fe290e7cc 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)