diff options
author | Benjamin Otte <otte@redhat.com> | 2011-05-09 16:19:06 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2011-05-09 18:37:08 +0200 |
commit | 206b9f940d632dd0ed10ab8046777956872555eb (patch) | |
tree | e7e25580f882a9ba253ce18cae26a1c1b84da150 /gtk/gtkpaned.c | |
parent | b6c8671fdea3a34fa59f81ad16513f8e0fbdcd9d (diff) | |
download | gtk+-206b9f940d632dd0ed10ab8046777956872555eb.tar.gz |
paned: Create a GDK window for every child
We need the window to clip drawing. Otherwise we cannot allow
undersizing without doing underallocations.
Diffstat (limited to 'gtk/gtkpaned.c')
-rw-r--r-- | gtk/gtkpaned.c | 157 |
1 files changed, 150 insertions, 7 deletions
diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c index 62d515db7e..da770d4754 100644 --- a/gtk/gtkpaned.c +++ b/gtk/gtkpaned.c @@ -94,6 +94,8 @@ struct _GtkPanedPrivate GtkPaned *first_paned; GtkWidget *child1; GtkWidget *child2; + GdkWindow *child1_window; + GdkWindow *child2_window; GtkWidget *last_child1_focus; GtkWidget *last_child2_focus; GtkWidget *saved_focus; @@ -977,6 +979,20 @@ flip_child (GtkWidget *widget, } static void +gtk_paned_child_allocate (GtkWidget *child, + GdkWindow *child_window, /* can be NULL */ + const GtkAllocation *allocation) +{ + GtkAllocation child_allocation = { 0, 0, allocation->width, allocation->height }; + + if (child_window) + gdk_window_move_resize (child_window, + allocation->x, allocation->y, + allocation->width, allocation->height); + + gtk_widget_size_allocate (child, &child_allocation); +} +static void gtk_paned_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { @@ -1111,14 +1127,18 @@ gtk_paned_size_allocate (GtkWidget *widget, (priv->orientation == GTK_ORIENTATION_VERTICAL && priv_child1_allocation.height < child1_allocation.height))) { - gtk_widget_size_allocate (priv->child2, &child2_allocation); - gtk_widget_size_allocate (priv->child1, &child1_allocation); + gtk_paned_child_allocate (priv->child2, priv->child2_window, &child2_allocation); + gtk_paned_child_allocate (priv->child1, priv->child1_window, &child1_allocation); } else { - gtk_widget_size_allocate (priv->child1, &child1_allocation); - gtk_widget_size_allocate (priv->child2, &child2_allocation); + gtk_paned_child_allocate (priv->child1, priv->child1_window, &child1_allocation); + gtk_paned_child_allocate (priv->child2, priv->child2_window, &child2_allocation); } + if (priv->child1_window) + gdk_window_show (priv->child1_window); + if (priv->child2_window) + gdk_window_show (priv->child2_window); } else { @@ -1138,12 +1158,79 @@ gtk_paned_size_allocate (GtkWidget *widget, child_allocation.height = allocation->height; if (priv->child1 && gtk_widget_get_visible (priv->child1)) - gtk_widget_size_allocate (priv->child1, &child_allocation); + { + gtk_paned_child_allocate (priv->child1, priv->child1_window, &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)) - gtk_widget_size_allocate (priv->child2, &child_allocation); + { + gtk_paned_child_allocate (priv->child2, priv->child2_window, &child_allocation); + if (priv->child2_window) + gdk_window_show (priv->child2_window); + if (priv->child1_window) + gdk_window_hide (priv->child1_window); + } } } +static GdkWindow * +gtk_paned_create_child_window (GtkPaned *paned, + GtkWidget *child) /* may be NULL */ +{ + GtkWidget *widget = GTK_WIDGET (paned); + GtkPanedPrivate *priv = paned->priv; + GdkWindow *window; + GdkWindowAttr attributes; + gint attributes_mask; + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK; + if (child) + { + GtkAllocation allocation; + int handle_size; + + gtk_widget_style_get (widget, "handle-size", &handle_size, NULL); + + gtk_widget_get_allocation (widget, &allocation); + if (priv->orientation == GTK_ORIENTATION_HORIZONTAL && + child == priv->child2) + attributes.x = priv->handle_pos.x + handle_size; + else + attributes.x = allocation.x; + if (priv->orientation == GTK_ORIENTATION_VERTICAL && + child == priv->child2) + attributes.y = priv->handle_pos.y + handle_size; + else + attributes.y = allocation.y; + + gtk_widget_get_allocation (child, &allocation); + attributes.width = allocation.width; + attributes.height = allocation.height; + attributes_mask = GDK_WA_X | GDK_WA_Y; + } + else + { + attributes.width = 1; + attributes.height = 1; + attributes_mask = 0; + } + + window = gdk_window_new (gtk_widget_get_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (window, paned); + gtk_style_context_set_background (gtk_widget_get_style_context (widget), window); + + if (child) + gtk_widget_set_parent_window (child, window); + + return window; +} + static void gtk_paned_realize (GtkWidget *widget) { @@ -1185,6 +1272,9 @@ gtk_paned_realize (GtkWidget *widget) gdk_window_set_user_data (priv->handle, paned); if (attributes_mask & GDK_WA_CURSOR) g_object_unref (attributes.cursor); + + priv->child1_window = gtk_paned_create_child_window (paned, priv->child1); + priv->child2_window = gtk_paned_create_child_window (paned, priv->child2); } static void @@ -1193,6 +1283,18 @@ gtk_paned_unrealize (GtkWidget *widget) GtkPaned *paned = GTK_PANED (widget); GtkPanedPrivate *priv = paned->priv; + if (priv->child2) + gtk_widget_set_parent_window (priv->child2, NULL); + gdk_window_set_user_data (priv->child2_window, NULL); + gdk_window_destroy (priv->child2_window); + priv->child2_window = NULL; + + if (priv->child1) + gtk_widget_set_parent_window (priv->child1, NULL); + gdk_window_set_user_data (priv->child1_window, NULL); + gdk_window_destroy (priv->child1_window); + priv->child1_window = NULL; + if (priv->handle) { gdk_window_set_user_data (priv->handle, NULL); @@ -1218,6 +1320,11 @@ 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)) + gdk_window_show (priv->child1_window); + if (priv->child2 && gtk_widget_get_visible (priv->child2)) + gdk_window_show (priv->child2_window); + GTK_WIDGET_CLASS (gtk_paned_parent_class)->map (widget); } @@ -1228,6 +1335,9 @@ gtk_paned_unmap (GtkWidget *widget) GtkPanedPrivate *priv = paned->priv; gdk_window_hide (priv->handle); + + gdk_window_hide (priv->child1_window); + gdk_window_hide (priv->child2_window); GTK_WIDGET_CLASS (gtk_paned_parent_class)->unmap (widget); } @@ -1239,7 +1349,32 @@ gtk_paned_draw (GtkWidget *widget, GtkPaned *paned = GTK_PANED (widget); GtkPanedPrivate *priv = paned->priv; - if (priv->child1 && gtk_widget_get_visible (priv->child1) && + if (gtk_cairo_should_draw_window (cr, priv->child1_window)) + { + cairo_save (cr); + gtk_cairo_transform_to_window (cr, widget, priv->child1_window); + gtk_render_background (gtk_widget_get_style_context (widget), + cr, + 0, 0, + gdk_window_get_width (priv->child1_window), + gdk_window_get_height (priv->child1_window)); + cairo_restore (cr); + } + + if (gtk_cairo_should_draw_window (cr, priv->child2_window)) + { + cairo_save (cr); + gtk_cairo_transform_to_window (cr, widget, priv->child2_window); + gtk_render_background (gtk_widget_get_style_context (widget), + cr, + 0, 0, + gdk_window_get_width (priv->child2_window), + gdk_window_get_height (priv->child2_window)); + cairo_restore (cr); + } + + if (gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget)) && + priv->child1 && gtk_widget_get_visible (priv->child1) && priv->child2 && gtk_widget_get_visible (priv->child2)) { GtkStyleContext *context; @@ -1601,6 +1736,7 @@ gtk_paned_pack1 (GtkPaned *paned, priv->child1_resize = resize; priv->child1_shrink = shrink; + gtk_widget_set_parent_window (child, priv->child1_window); gtk_widget_set_parent (child, GTK_WIDGET (paned)); } } @@ -1633,6 +1769,7 @@ gtk_paned_pack2 (GtkPaned *paned, priv->child2_resize = resize; priv->child2_shrink = shrink; + gtk_widget_set_parent_window (child, priv->child2_window); gtk_widget_set_parent (child, GTK_WIDGET (paned)); } } @@ -1674,6 +1811,9 @@ gtk_paned_remove (GtkContainer *container, 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)); } @@ -1683,6 +1823,9 @@ gtk_paned_remove (GtkContainer *container, 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)); } |