diff options
author | 21:04:28 Tim Janik <timj@imendio.com> | 2008-05-21 19:07:40 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 2008-05-21 19:07:40 +0000 |
commit | aa4ab3f03731f269d8c3a322cee653bc88fec3a4 (patch) | |
tree | 714d32e0ff9dbc476d652025f18dbb7d992888c2 /gtk/gtkwidget.c | |
parent | 4111cf2065e1f7edc614a936f1fa35e750f13a0f (diff) | |
download | gtk+-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.c | 86 |
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; } |