forked from AuroraMiddleware/gtk
added GdkRectangle *clip_rect to gtk_widget_get_snapshot().
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. svn path=/trunk/; revision=20124
This commit is contained in:
parent
aa4ab3f037
commit
b3d160ced5
@ -1,3 +1,12 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
2008-05-21 21:04:28 Tim Janik <timj@imendio.com>
|
2008-05-21 21:04:28 Tim Janik <timj@imendio.com>
|
||||||
|
|
||||||
* gtk/gtkwidget.c gtk_widget_get_snapshot(): grow snapshot area from
|
* gtk/gtkwidget.c gtk_widget_get_snapshot(): grow snapshot area from
|
||||||
|
@ -8314,30 +8314,49 @@ gtk_widget_unref (GtkWidget *widget)
|
|||||||
/**
|
/**
|
||||||
* gtk_widget_get_snapshot:
|
* 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
|
* Create a #GdkPixmap of the contents of the widget and its children.
|
||||||
* children. Works even if the widget is obscured.
|
* Works even if the widget is obscured. The depth and visual of the
|
||||||
* Note that the depth and visual of the resulting pixmap is dependent
|
* resulting pixmap is dependent on the widget being snapshot and likely
|
||||||
* on the widget being snapshot and likely differs from those of a target
|
* differs from those of a target widget displaying the pixmap.
|
||||||
* widget displaying the pixmap. Use gdk_pixbuf_get_from_drawable()
|
* The function gdk_pixbuf_get_from_drawable() can be used to convert
|
||||||
* to convert the pixmap to a visual independant representation.
|
* 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
|
* Since: 2.16
|
||||||
**/
|
**/
|
||||||
GdkPixmap*
|
GdkPixmap*
|
||||||
gtk_widget_get_snapshot (GtkWidget *widget)
|
gtk_widget_get_snapshot (GtkWidget *widget,
|
||||||
|
GdkRectangle *clip_rect)
|
||||||
{
|
{
|
||||||
int x, y, width, height;
|
int x, y, width, height;
|
||||||
GdkWindow *parent_window = NULL;
|
GdkWindow *parent_window = NULL;
|
||||||
GdkPixmap *pixmap;
|
GdkPixmap *pixmap;
|
||||||
|
|
||||||
|
/* the widget (and parent_window) must be realized to be drawable */
|
||||||
if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
|
if (widget->parent && !GTK_WIDGET_REALIZED (widget->parent))
|
||||||
gtk_widget_realize (widget->parent);
|
gtk_widget_realize (widget->parent);
|
||||||
if (!GTK_WIDGET_REALIZED (widget))
|
if (!GTK_WIDGET_REALIZED (widget))
|
||||||
gtk_widget_realize (widget);
|
gtk_widget_realize (widget);
|
||||||
|
|
||||||
/* figure snapshot rectangle */
|
/* determine snapshot rectangle */
|
||||||
x = widget->allocation.x;
|
x = widget->allocation.x;
|
||||||
y = widget->allocation.y;
|
y = widget->allocation.y;
|
||||||
width = widget->allocation.width;
|
width = widget->allocation.width;
|
||||||
@ -8345,6 +8364,7 @@ gtk_widget_get_snapshot (GtkWidget *widget)
|
|||||||
GList *windows = NULL, *list;
|
GList *windows = NULL, *list;
|
||||||
if (widget->parent && !GTK_WIDGET_NO_WINDOW (widget))
|
if (widget->parent && !GTK_WIDGET_NO_WINDOW (widget))
|
||||||
{
|
{
|
||||||
|
/* grow snapshot rectangle to cover all widget windows */
|
||||||
parent_window = gtk_widget_get_parent_window (widget);
|
parent_window = gtk_widget_get_parent_window (widget);
|
||||||
for (list = gdk_window_peek_children (parent_window); list; list = list->next)
|
for (list = gdk_window_peek_children (parent_window); list; list = list->next)
|
||||||
{
|
{
|
||||||
@ -8377,18 +8397,50 @@ gtk_widget_get_snapshot (GtkWidget *widget)
|
|||||||
else if (!widget->parent)
|
else if (!widget->parent)
|
||||||
x = y = 0; /* toplevel */
|
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 */
|
/* render snapshot */
|
||||||
pixmap = gdk_pixmap_new (widget->window, width, height, gdk_drawable_get_depth (widget->window));
|
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;
|
GdkWindow *subwin = list->data;
|
||||||
int wx, wy;
|
int wx, wy;
|
||||||
gdk_window_get_position (subwin, &wx, &wy);
|
gdk_window_get_position (subwin, &wx, &wy);
|
||||||
gdk_window_redirect_to_drawable (subwin, pixmap, MAX (0, x - wx), MAX (0, y - 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);
|
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_redirect_to_drawable (widget->window, pixmap, x, y, 0, 0, width, height);
|
||||||
gdk_window_invalidate_rect (widget->window, NULL, TRUE);
|
gdk_window_invalidate_rect (widget->window, NULL, TRUE);
|
||||||
@ -8404,6 +8456,25 @@ gtk_widget_get_snapshot (GtkWidget *widget)
|
|||||||
if (!windows) /* NO_WINDOW || toplevel */
|
if (!windows) /* NO_WINDOW || toplevel */
|
||||||
gdk_window_remove_redirection (widget->window);
|
gdk_window_remove_redirection (widget->window);
|
||||||
g_list_free (windows);
|
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;
|
return pixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +614,8 @@ GdkWindow * gtk_widget_get_root_window (GtkWidget *widget);
|
|||||||
GtkSettings* gtk_widget_get_settings (GtkWidget *widget);
|
GtkSettings* gtk_widget_get_settings (GtkWidget *widget);
|
||||||
GtkClipboard *gtk_widget_get_clipboard (GtkWidget *widget,
|
GtkClipboard *gtk_widget_get_clipboard (GtkWidget *widget,
|
||||||
GdkAtom selection);
|
GdkAtom selection);
|
||||||
GdkPixmap * gtk_widget_get_snapshot (GtkWidget *widget);
|
GdkPixmap * gtk_widget_get_snapshot (GtkWidget *widget,
|
||||||
|
GdkRectangle *clip_rect);
|
||||||
|
|
||||||
#ifndef GTK_DISABLE_DEPRECATED
|
#ifndef GTK_DISABLE_DEPRECATED
|
||||||
#define gtk_widget_set_visual(widget,visual) ((void) 0)
|
#define gtk_widget_set_visual(widget,visual) ((void) 0)
|
||||||
|
@ -12259,16 +12259,16 @@ snapshot_widget_event (GtkWidget *widget,
|
|||||||
if (res_widget)
|
if (res_widget)
|
||||||
{
|
{
|
||||||
GdkPixmap *pixmap;
|
GdkPixmap *pixmap;
|
||||||
GdkPixbuf *pixbuf = NULL;
|
|
||||||
GtkWidget *window, *image;
|
GtkWidget *window, *image;
|
||||||
|
|
||||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
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);
|
gtk_widget_realize (window);
|
||||||
if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
|
if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
|
||||||
{
|
{
|
||||||
/* this branch is needed to convert ARGB -> RGB */
|
/* this branch is needed to convert ARGB -> RGB */
|
||||||
int width, height;
|
int width, height;
|
||||||
|
GdkPixbuf *pixbuf;
|
||||||
gdk_drawable_get_size (pixmap, &width, &height);
|
gdk_drawable_get_size (pixmap, &width, &height);
|
||||||
pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
|
pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
|
||||||
gtk_widget_get_colormap (res_widget),
|
gtk_widget_get_colormap (res_widget),
|
||||||
@ -12276,10 +12276,10 @@ snapshot_widget_event (GtkWidget *widget,
|
|||||||
0, 0,
|
0, 0,
|
||||||
width, height);
|
width, height);
|
||||||
image = gtk_image_new_from_pixbuf (pixbuf);
|
image = gtk_image_new_from_pixbuf (pixbuf);
|
||||||
|
g_object_unref (pixbuf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
image = gtk_image_new_from_pixmap (pixmap, NULL);
|
image = gtk_image_new_from_pixmap (pixmap, NULL);
|
||||||
g_object_unref (pixbuf);
|
|
||||||
gtk_container_add (GTK_CONTAINER (window), image);
|
gtk_container_add (GTK_CONTAINER (window), image);
|
||||||
g_object_unref (pixmap);
|
g_object_unref (pixmap);
|
||||||
gtk_widget_show_all (window);
|
gtk_widget_show_all (window);
|
||||||
|
Loading…
Reference in New Issue
Block a user