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_XDISPLAY (gdk_display_get_default ()), 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_XDISPLAY (gdk_display_get_default ()), 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)
129 GdkPixbuf *tmp, *tmp2;
132 if (include_decoration)
133 xid = find_toplevel_window (child);
137 window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), xid);
139 width = gdk_window_get_width (window);
140 height = gdk_window_get_height (window);
141 gdk_window_get_origin (window, &x_orig, &y_orig);
146 width = width + x_orig;
153 height = height + y_orig;
157 if (x_orig + width > gdk_screen_width ())
158 width = gdk_screen_width () - x_orig;
160 if (y_orig + height > gdk_screen_height ())
161 height = gdk_screen_height () - y_orig;
163 tmp = gdk_pixbuf_get_from_window (window,
164 x, y, width, height);
166 if (include_decoration)
167 tmp2 = remove_shaped_area (tmp, xid);
169 tmp2 = add_border_to_shot (tmp);
171 retval = create_shadowed_pixbuf (tmp2);
172 g_object_unref (tmp);
173 g_object_unref (tmp2);
178 int main (int argc, char **argv)
181 GdkPixbuf *screenshot = NULL;
184 /* If there's no DISPLAY, we silently error out. We don't want to break
185 * headless builds. */
186 if (! gtk_init_check (&argc, &argv))
189 toplevels = get_all_widgets ();
191 for (node = toplevels; node; node = g_list_next (node))
193 GtkAllocation allocation;
201 gtk_widget_show (info->window);
203 window = gtk_widget_get_window (info->window);
204 gtk_widget_get_allocation (info->window, &allocation);
206 gtk_widget_show_now (info->window);
207 gtk_widget_queue_draw_area (info->window,
208 allocation.x, allocation.y,
209 allocation.width, allocation.height);
210 gdk_window_process_updates (window, TRUE);
212 while (gtk_events_pending ())
214 gtk_main_iteration ();
218 while (gtk_events_pending ())
220 gtk_main_iteration ();
223 id = gdk_x11_window_get_xid (window);
224 screenshot = take_window_shot (id, info->include_decorations);
225 filename = g_strdup_printf ("./%s.png", info->name);
226 gdk_pixbuf_save (screenshot, filename, "png", NULL, NULL);
228 gtk_widget_hide (info->window);