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_queue_draw_area (info->window,
209 info->window->allocation.x, info->window->allocation.y,
210 info->window->allocation.width, info->window->allocation.height);
212 while (gtk_events_pending ())
214 gtk_main_iteration ();
218 while (gtk_events_pending ())
220 gtk_main_iteration ();
223 id = gdk_x11_drawable_get_xid (GDK_DRAWABLE (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);