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.
This commit is contained in:
Benjamin Otte 2011-05-11 00:46:08 +02:00
parent 1ab425b132
commit f96777ea02

View File

@ -89,6 +89,11 @@
* </example> * </example>
*/ */
enum {
CHILD1,
CHILD2
};
struct _GtkPanedPrivate struct _GtkPanedPrivate
{ {
GtkPaned *first_paned; GtkPaned *first_paned;
@ -978,6 +983,50 @@ flip_child (GtkWidget *widget,
child_pos->x = 2 * x + width - child_pos->x - child_pos->width; 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 static void
gtk_paned_child_allocate (GtkWidget *child, gtk_paned_child_allocate (GtkWidget *child,
GdkWindow *child_window, /* can be NULL */ GdkWindow *child_window, /* can be NULL */
@ -1182,10 +1231,6 @@ gtk_paned_size_allocate (GtkWidget *widget,
&window2_allocation, &window2_allocation,
&child2_allocation); &child2_allocation);
} }
if (priv->child1_window)
gdk_window_show (priv->child1_window);
if (priv->child2_window)
gdk_window_show (priv->child2_window);
} }
else else
{ {
@ -1195,9 +1240,9 @@ gtk_paned_size_allocate (GtkWidget *widget,
gdk_window_hide (priv->handle); gdk_window_hide (priv->handle);
if (priv->child1) if (priv->child1)
gtk_widget_set_child_visible (priv->child1, TRUE); gtk_paned_set_child_visible (paned, 0, TRUE);
if (priv->child2) 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.x = allocation->x;
window_allocation.y = allocation->y; window_allocation.y = allocation->y;
@ -1213,10 +1258,6 @@ gtk_paned_size_allocate (GtkWidget *widget,
priv->child1_window, priv->child1_window,
&window_allocation, &window_allocation,
&child_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)) else if (priv->child2 && gtk_widget_get_visible (priv->child2))
{ {
@ -1224,10 +1265,6 @@ gtk_paned_size_allocate (GtkWidget *widget,
priv->child2_window, priv->child2_window,
&window_allocation, &window_allocation,
&child_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)) priv->child2 && gtk_widget_get_visible (priv->child2))
gdk_window_show (priv->handle); 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); 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); gdk_window_show (priv->child2_window);
GTK_WIDGET_CLASS (gtk_paned_parent_class)->map (widget); 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->handle);
gdk_window_hide (priv->child1_window); if (gdk_window_is_visible (priv->child1_window))
gdk_window_hide (priv->child2_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); 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 == widget)
{ {
if (priv->child1_window && gdk_window_is_visible (priv->child1_window))
gdk_window_hide (priv->child1_window);
gtk_widget_unparent (widget); gtk_widget_unparent (widget);
priv->child1 = NULL; priv->child1 = NULL;
if (priv->child1_window)
gdk_window_hide (priv->child1_window);
if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (container)); gtk_widget_queue_resize_no_redraw (GTK_WIDGET (container));
} }
else if (priv->child2 == widget) 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); gtk_widget_unparent (widget);
priv->child2 = NULL; priv->child2 = NULL;
if (priv->child2_window)
gdk_window_hide (priv->child2_window);
if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container)))
gtk_widget_queue_resize_no_redraw (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); priv->max_position);
if (priv->child1) 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) 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)); g_object_freeze_notify (G_OBJECT (paned));
if (priv->child1_size != old_position) if (priv->child1_size != old_position)