gtk+ r20124 - in trunk: . gtk tests
- From: timj svn gnome org
- To: svn-commits-list gnome org
- Subject: gtk+ r20124 - in trunk: . gtk tests
- Date: Wed, 21 May 2008 19:15:12 +0000 (UTC)
Author: timj
Date: Wed May 21 19:15:12 2008
New Revision: 20124
URL: http://svn.gnome.org/viewvc/gtk+?rev=20124&view=rev
Log:
2008-05-21 21:10:15 Tim Janik <timj imendio com>
* gtk/gtkwidget.h: added GdkRectangle *clip_rect to gtk_widget_get_snapshot().
* gtk/gtkwidget.c: clip the returned snapshot pixmap to clip_rect.
return snapshot pixmap coordinates widget relative in *clip_rect.
* tests/testgtk.c: fixed bogus NULL pointer unref.
Modified:
trunk/ChangeLog
trunk/gtk/gtkwidget.c
trunk/gtk/gtkwidget.h
trunk/tests/testgtk.c
Modified: trunk/gtk/gtkwidget.c
==============================================================================
--- trunk/gtk/gtkwidget.c (original)
+++ trunk/gtk/gtkwidget.c Wed May 21 19:15:12 2008
@@ -8313,31 +8313,50 @@
/**
* gtk_widget_get_snapshot:
- * @widget: a #GtkWidget
+ * @widget: a #GtkWidget
+ * @clip_rect: a #GdkRectangle or %NULL
*
- * Creates a #GdkPixmap of the contents of the widget and its
- * children. Works even if the widget is obscured.
- * Note that the depth and visual of the resulting pixmap is dependent
- * on the widget being snapshot and likely differs from those of a target
- * widget displaying the pixmap. Use gdk_pixbuf_get_from_drawable()
- * to convert the pixmap to a visual independant representation.
+ * Create a #GdkPixmap of the contents of the widget and its children.
+ * Works even if the widget is obscured. The depth and visual of the
+ * resulting pixmap is dependent on the widget being snapshot and likely
+ * differs from those of a target widget displaying the pixmap.
+ * The function gdk_pixbuf_get_from_drawable() can be used to convert
+ * the pixmap to a visual independant representation.
+ * The snapshot area used by this function is the @widget's allocation plus
+ * any extra space occupied by additional windows belonging to this widget
+ * (such as the arrows of a spin button).
+ * Thus, the resulting snapshot pixmap is possibly larger than the allocation.
+ * If @clip_rect is non NULL, the resulting pixmap is shrunken to
+ * match the specified clip_rect. The (x,y) coordinates of @clip_rect are
+ * interpreted widget relative. If width or height of @clip_rect are 0 or
+ * negative, the width or height of the resulting pixmap will be shrunken
+ * by the respective amount.
+ * For instance a @clip_rect <literal>{ +5, +5, -10, -10 }</literal> will
+ * chop off 5 pixel at each side of the snapshot pixmap.
+ * If non-%NULL, clip_rect will contain the exact widget relative snapshot
+ * coordinates upon return. A @clip_rect of <literal>{ -1, -1, 0, 0 }</literal>
+ * can be used to preserve the auto-grown snapshot area and use @clip_rect
+ * as a pure output parameter.
+ * The returned pixmap can be %NULL, if the resulting clip_area was empty.
*
- * Return value: #GdkPixmap of the widget
+ * Return value: #GdkPixmap snapshot of the widget
* Since: 2.16
**/
GdkPixmap*
-gtk_widget_get_snapshot (GtkWidget *widget)
+gtk_widget_get_snapshot (GtkWidget *widget,
+ GdkRectangle *clip_rect)
{
int x, y, width, height;
GdkWindow *parent_window = NULL;
GdkPixmap *pixmap;
+ /* the widget (and parent_window) must be realized to be drawable */
if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
gtk_widget_realize (widget->parent);
if (!GTK_WIDGET_REALIZED (widget))
gtk_widget_realize (widget);
- /* figure snapshot rectangle */
+ /* determine snapshot rectangle */
x = widget->allocation.x;
y = widget->allocation.y;
width = widget->allocation.width;
@@ -8345,6 +8364,7 @@
GList *windows = NULL, *list;
if (widget->parent && !GTK_WIDGET_NO_WINDOW (widget))
{
+ /* grow snapshot rectangle to cover all widget windows */
parent_window = gtk_widget_get_parent_window (widget);
for (list = gdk_window_peek_children (parent_window); list; list = list->next)
{
@@ -8377,18 +8397,50 @@
else if (!widget->parent)
x = y = 0; /* toplevel */
+ /* at this point, (x,y,width,height) is the parent_window relative
+ * snapshot area covering all of widget's windows.
+ */
+
+ /* shrink snapshot size by clip_rectangle */
+ if (clip_rect)
+ {
+ GdkRectangle snap = { x, y, width, height }, clip = *clip_rect;
+ clip.x = clip.x < 0 ? x : clip.x;
+ clip.y = clip.y < 0 ? y : clip.y;
+ clip.width = clip.width <= 0 ? MAX (0, width + clip.width) : clip.width;
+ clip.height = clip.height <= 0 ? MAX (0, height + clip.height) : clip.height;
+ if (widget->parent)
+ {
+ /* offset clip_rect, so it's parent_window relative */
+ if (clip_rect->x >= 0)
+ clip.x += widget->allocation.x;
+ if (clip_rect->y >= 0)
+ clip.y += widget->allocation.y;
+ }
+ if (!gdk_rectangle_intersect (&snap, &clip, &snap))
+ {
+ g_list_free (windows);
+ clip_rect->width = clip_rect->height = 0;
+ return NULL; /* empty snapshot area */
+ }
+ x = snap.x;
+ y = snap.y;
+ width = snap.width;
+ height = snap.height;
+ }
+
/* render snapshot */
pixmap = gdk_pixmap_new (widget->window, width, height, gdk_drawable_get_depth (widget->window));
- for (list = windows; list; list = list->next)
+ for (list = windows; list; list = list->next) /* !NO_WINDOW widgets */
{
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);
+ MAX (0, wx - x), MAX (0, wy - y), width, height);
gdk_window_invalidate_rect (subwin, NULL, TRUE);
}
- if (!windows) /* NO_WINDOW || toplevel */
+ if (!windows) /* NO_WINDOW || toplevel => parent_window == NULL || parent_window == widget->window */
{
gdk_window_redirect_to_drawable (widget->window, pixmap, x, y, 0, 0, width, height);
gdk_window_invalidate_rect (widget->window, NULL, TRUE);
@@ -8404,6 +8456,25 @@
if (!windows) /* NO_WINDOW || toplevel */
gdk_window_remove_redirection (widget->window);
g_list_free (windows);
+
+ /* return pixmap and snapshot rectangle coordinates */
+ if (clip_rect)
+ {
+ clip_rect->x = x;
+ clip_rect->y = y;
+ clip_rect->width = width;
+ clip_rect->height = height;
+ if (widget->parent)
+ {
+ /* offset clip_rect from parent_window so it's widget relative */
+ clip_rect->x -= widget->allocation.x;
+ clip_rect->y -= widget->allocation.y;
+ }
+ if (0)
+ g_printerr ("gtk_widget_get_snapshot: %s (%d,%d, %dx%d)\n",
+ G_OBJECT_TYPE_NAME (widget),
+ clip_rect->x, clip_rect->y, clip_rect->width, clip_rect->height);
+ }
return pixmap;
}
Modified: trunk/gtk/gtkwidget.h
==============================================================================
--- trunk/gtk/gtkwidget.h (original)
+++ trunk/gtk/gtkwidget.h Wed May 21 19:15:12 2008
@@ -614,7 +614,8 @@
GtkSettings* gtk_widget_get_settings (GtkWidget *widget);
GtkClipboard *gtk_widget_get_clipboard (GtkWidget *widget,
GdkAtom selection);
-GdkPixmap * gtk_widget_get_snapshot (GtkWidget *widget);
+GdkPixmap * gtk_widget_get_snapshot (GtkWidget *widget,
+ GdkRectangle *clip_rect);
#ifndef GTK_DISABLE_DEPRECATED
#define gtk_widget_set_visual(widget,visual) ((void) 0)
Modified: trunk/tests/testgtk.c
==============================================================================
--- trunk/tests/testgtk.c (original)
+++ trunk/tests/testgtk.c Wed May 21 19:15:12 2008
@@ -12259,16 +12259,16 @@
if (res_widget)
{
GdkPixmap *pixmap;
- GdkPixbuf *pixbuf = NULL;
GtkWidget *window, *image;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- pixmap = gtk_widget_get_snapshot (res_widget);
+ pixmap = gtk_widget_get_snapshot (res_widget, NULL);
gtk_widget_realize (window);
if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
{
/* this branch is needed to convert ARGB -> RGB */
int width, height;
+ GdkPixbuf *pixbuf;
gdk_drawable_get_size (pixmap, &width, &height);
pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
gtk_widget_get_colormap (res_widget),
@@ -12276,10 +12276,10 @@
0, 0,
width, height);
image = gtk_image_new_from_pixbuf (pixbuf);
+ g_object_unref (pixbuf);
}
else
image = gtk_image_new_from_pixmap (pixmap, NULL);
- g_object_unref (pixbuf);
gtk_container_add (GTK_CONTAINER (window), image);
g_object_unref (pixmap);
gtk_widget_show_all (window);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]