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)
130 GdkPixbuf *tmp, *tmp2;
133 disp = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
134 w = GDK_ROOT_WINDOW ();
136 if (include_decoration)
137 xid = find_toplevel_window (child);
141 window = gdk_window_foreign_new (xid);
143 width = gdk_window_get_width (window);
144 height = gdk_window_get_height (window);
145 gdk_window_get_origin (window, &x_orig, &y_orig);
150 width = width + x_orig;
157 height = height + y_orig;
161 if (x_orig + width > gdk_screen_width ())
162 width = gdk_screen_width () - x_orig;
164 if (y_orig + height > gdk_screen_height ())
165 height = gdk_screen_height () - y_orig;
167 tmp = gdk_pixbuf_get_from_window (window,
168 x, y, width, height);
170 if (include_decoration)
171 tmp2 = remove_shaped_area (tmp, xid);
173 tmp2 = add_border_to_shot (tmp);
175 retval = create_shadowed_pixbuf (tmp2);
176 g_object_unref (tmp);
177 g_object_unref (tmp2);
182 int main (int argc, char **argv)
185 GdkPixbuf *screenshot = NULL;
188 /* If there's no DISPLAY, we silently error out. We don't want to break
189 * headless builds. */
190 if (! gtk_init_check (&argc, &argv))
193 toplevels = get_all_widgets ();
195 for (node = toplevels; node; node = g_list_next (node))
197 GtkAllocation allocation;
205 gtk_widget_show (info->window);
207 window = gtk_widget_get_window (info->window);
208 gtk_widget_get_allocation (info->window, &allocation);
210 gtk_widget_show_now (info->window);
211 gtk_widget_queue_draw_area (info->window,
212 allocation.x, allocation.y,
213 allocation.width, allocation.height);
214 gdk_window_process_updates (window, TRUE);
216 while (gtk_events_pending ())
218 gtk_main_iteration ();
222 while (gtk_events_pending ())
224 gtk_main_iteration ();
227 id = gdk_x11_drawable_get_xid (GDK_DRAWABLE (window));
228 screenshot = take_window_shot (id, info->include_decorations);
229 filename = g_strdup_printf ("./%s.png", info->name);
230 gdk_pixbuf_save (screenshot, filename, "png", NULL, NULL);
232 gtk_widget_hide (info->window);