8
#include <X11/extensions/shape.h>
10
#include <gdk-pixbuf/gdk-pixbuf.h>
11
#include <sys/types.h>
23
#define MAXIMUM_WM_REPARENTING_DEPTH 4
29
find_toplevel_window (Window xid)
31
Window root, parent, *children;
36
if (XQueryTree (GDK_DISPLAY (), xid, &root,
37
&parent, &children, &nchildren) == 0)
39
g_warning ("Couldn't find window manager window");
52
add_border_to_shot (GdkPixbuf *pixbuf)
56
retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
57
gdk_pixbuf_get_width (pixbuf) + 2,
58
gdk_pixbuf_get_height (pixbuf) + 2);
60
/* Fill with solid black */
61
gdk_pixbuf_fill (retval, 0xFF);
62
gdk_pixbuf_copy_area (pixbuf,
64
gdk_pixbuf_get_width (pixbuf),
65
gdk_pixbuf_get_height (pixbuf),
72
remove_shaped_area (GdkPixbuf *pixbuf,
76
XRectangle *rectangles;
77
int rectangle_count, rectangle_order;
80
retval = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
81
gdk_pixbuf_get_width (pixbuf),
82
gdk_pixbuf_get_height (pixbuf));
84
gdk_pixbuf_fill (retval, 0);
85
rectangles = XShapeGetRectangles (GDK_DISPLAY (), window,
86
ShapeBounding, &rectangle_count, &rectangle_order);
88
for (i = 0; i < rectangle_count; i++)
92
for (y = rectangles[i].y; y < rectangles[i].y + rectangles[i].height; y++)
94
guchar *src_pixels, *dest_pixels;
96
src_pixels = gdk_pixbuf_get_pixels (pixbuf) +
97
y * gdk_pixbuf_get_rowstride (pixbuf) +
98
rectangles[i].x * (gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3);
99
dest_pixels = gdk_pixbuf_get_pixels (retval) +
100
y * gdk_pixbuf_get_rowstride (retval) +
103
for (x = rectangles[i].x; x < rectangles[i].x + rectangles[i].width; x++)
105
*dest_pixels++ = *src_pixels ++;
106
*dest_pixels++ = *src_pixels ++;
107
*dest_pixels++ = *src_pixels ++;
108
*dest_pixels++ = 255;
110
if (gdk_pixbuf_get_has_alpha (pixbuf))
120
take_window_shot (Window child,
121
gboolean include_decoration)
130
GdkPixbuf *tmp, *tmp2;
133
disp = GDK_DISPLAY ();
134
w = GDK_ROOT_WINDOW ();
136
if (include_decoration)
137
xid = find_toplevel_window (child);
141
window = gdk_window_foreign_new (xid);
143
gdk_drawable_get_size (window, &width, &height);
144
gdk_window_get_origin (window, &x_orig, &y_orig);
149
width = width + x_orig;
156
height = height + y_orig;
160
if (x_orig + width > gdk_screen_width ())
161
width = gdk_screen_width () - x_orig;
163
if (y_orig + height > gdk_screen_height ())
164
height = gdk_screen_height () - y_orig;
166
tmp = gdk_pixbuf_get_from_drawable (NULL, window, NULL,
167
x, y, 0, 0, width, height);
169
if (include_decoration)
170
tmp2 = remove_shaped_area (tmp, xid);
172
tmp2 = add_border_to_shot (tmp);
174
retval = create_shadowed_pixbuf (tmp2);
175
g_object_unref (tmp);
176
g_object_unref (tmp2);
181
int main (int argc, char **argv)
184
GdkPixbuf *screenshot = NULL;
187
/* If there's no DISPLAY, we silently error out. We don't want to break
188
* headless builds. */
189
if (! gtk_init_check (&argc, &argv))
192
toplevels = get_all_widgets ();
194
for (node = toplevels; node; node = g_list_next (node))
203
gtk_widget_show (info->window);
205
window = info->window->window;
207
gtk_widget_show_now (info->window);
208
gtk_widget_draw (info->window, &(info->window->allocation));
210
while (gtk_events_pending ())
212
gtk_main_iteration ();
216
while (gtk_events_pending ())
218
gtk_main_iteration ();
221
id = gdk_x11_drawable_get_xid (GDK_DRAWABLE (window));
222
screenshot = take_window_shot (id, info->include_decorations);
223
filename = g_strdup_printf ("./%s.png", info->name);
224
gdk_pixbuf_save (screenshot, filename, "png", NULL, NULL);
226
gtk_widget_hide (info->window);