summaryrefslogtreecommitdiff
path: root/gtk/gtkwidget.c
diff options
context:
space:
mode:
author21:04:28 Tim Janik <timj@imendio.com>2008-05-21 19:07:40 +0000
committerTim Janik <timj@src.gnome.org>2008-05-21 19:07:40 +0000
commitaa4ab3f03731f269d8c3a322cee653bc88fec3a4 (patch)
tree714d32e0ff9dbc476d652025f18dbb7d992888c2 /gtk/gtkwidget.c
parent4111cf2065e1f7edc614a936f1fa35e750f13a0f (diff)
downloadgtk+-aa4ab3f03731f269d8c3a322cee653bc88fec3a4.tar.gz
grow snapshot area from widget's allocation to cover extra widget windows
2008-05-21 21:04:28 Tim Janik <timj@imendio.com> * gtk/gtkwidget.c gtk_widget_get_snapshot(): grow snapshot area from widget's allocation to cover extra widget windows placed outside the widget allocation (spinbutton arrows are the prime example for this). svn path=/trunk/; revision=20123
Diffstat (limited to 'gtk/gtkwidget.c')
-rw-r--r--gtk/gtkwidget.c86
1 files changed, 67 insertions, 19 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 1f4f9fbd09..287c6e6d22 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -8328,34 +8328,82 @@ gtk_widget_unref (GtkWidget *widget)
GdkPixmap*
gtk_widget_get_snapshot (GtkWidget *widget)
{
+ int x, y, width, height;
+ GdkWindow *parent_window = NULL;
GdkPixmap *pixmap;
- int x, y;
+ if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
+ gtk_widget_realize (widget->parent);
if (!GTK_WIDGET_REALIZED (widget))
gtk_widget_realize (widget);
- pixmap = gdk_pixmap_new (widget->window,
- widget->allocation.width,
- widget->allocation.height,
- gdk_drawable_get_depth (widget->window));
- if (GTK_WIDGET_NO_WINDOW (widget))
+ /* figure snapshot rectangle */
+ x = widget->allocation.x;
+ y = widget->allocation.y;
+ width = widget->allocation.width;
+ height = widget->allocation.height;
+ GList *windows = NULL, *list;
+ if (widget->parent && !GTK_WIDGET_NO_WINDOW (widget))
{
- x = widget->allocation.x;
- y = widget->allocation.y;
+ parent_window = gtk_widget_get_parent_window (widget);
+ for (list = gdk_window_peek_children (parent_window); list; list = list->next)
+ {
+ GdkWindow *subwin = list->data;
+ gpointer windata;
+ int wx, wy, ww, wh;
+ gdk_window_get_user_data (subwin, &windata);
+ if (windata != widget)
+ continue;
+ windows = g_list_prepend (windows, subwin);
+ gdk_window_get_position (subwin, &wx, &wy);
+ gdk_drawable_get_size (subwin, &ww, &wh);
+ /* grow snapshot rectangle by extra widget sub window */
+ if (wx < x)
+ {
+ width += x - wx;
+ x = wx;
+ }
+ if (wy < y)
+ {
+ height += y - wy;
+ y = wy;
+ }
+ if (x + width < wx + ww)
+ width += wx + ww - (x + width);
+ if (y + height < wy + wh)
+ height += wy + wh - (y + height);
+ }
+ }
+ else if (!widget->parent)
+ x = y = 0; /* toplevel */
+
+ /* render snapshot */
+ pixmap = gdk_pixmap_new (widget->window, width, height, gdk_drawable_get_depth (widget->window));
+ for (list = windows; list; list = list->next)
+ {
+ GdkWindow *subwin = list->data;
+ int wx, wy;
+ gdk_window_get_position (subwin, &wx, &wy);
+ gdk_window_redirect_to_drawable (subwin, pixmap, MAX (0, x - wx), MAX (0, y - wy),
+ wx - x, wy - y, width, height);
+ gdk_window_invalidate_rect (subwin, NULL, TRUE);
+ }
+ if (!windows) /* NO_WINDOW || toplevel */
+ {
+ gdk_window_redirect_to_drawable (widget->window, pixmap, x, y, 0, 0, width, height);
+ gdk_window_invalidate_rect (widget->window, NULL, TRUE);
}
- else
- x = y = 0;
-
- gdk_window_redirect_to_drawable (widget->window,
- pixmap,
- x, y,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
gtk_widget_queue_draw (widget);
+ if (parent_window)
+ gdk_window_process_updates (parent_window, TRUE);
+ for (list = windows; list; list = list->next)
+ gdk_window_process_updates (list->data, TRUE);
gdk_window_process_updates (widget->window, TRUE);
- gdk_window_remove_redirection (widget->window);
-
+ for (list = windows; list; list = list->next)
+ gdk_window_remove_redirection (list->data);
+ if (!windows) /* NO_WINDOW || toplevel */
+ gdk_window_remove_redirection (widget->window);
+ g_list_free (windows);
return pixmap;
}