8 my_handler(Display *display, XErrorEvent *error) {
11 XGetErrorText(display, error->error_code, buffer, sizeof(buffer));
12 i_push_error(error->error_code, buffer);
18 imss_x11(unsigned long display_ul, int window_id,
19 int left, int top, int right, int bottom) {
20 Display *display = (Display *)display_ul;
21 int own_display = 0; /* non-zero if we connect */
23 XWindowAttributes attr;
28 XErrorHandler old_handler;
33 /* we don't want the default noisy error handling */
34 old_handler = XSetErrorHandler(my_handler);
37 display = XOpenDisplay(NULL);
40 XSetErrorHandler(old_handler);
41 i_push_error(0, "No display supplied and cannot connect");
47 int screen = DefaultScreen(display);
48 window_id = RootWindow(display, screen);
51 if (!XGetWindowAttributes(display, window_id, &attr)) {
52 XSetErrorHandler(old_handler);
54 XCloseDisplay(display);
55 i_push_error(0, "Cannot XGetWindowAttributes");
59 /* adjust negative/zero values to window size */
67 bottom += attr.height;
72 if (right > attr.width)
76 if (bottom > attr.height)
80 if (right <= left || bottom <= top) {
81 XSetErrorHandler(old_handler);
83 XCloseDisplay(display);
84 i_push_error(0, "image would be empty");
88 height = bottom - top;
89 image = XGetImage(display, window_id, left, top, width, height,
92 XSetErrorHandler(old_handler);
94 XCloseDisplay(display);
95 i_push_error(0, "Cannot XGetImage");
99 result = i_img_8_new(width, height, 3);
100 line = mymalloc(sizeof(i_color) * width);
101 colors = mymalloc(sizeof(XColor) * width);
102 for (y = 0; y < height; ++y) {
104 /* XQueryColors seems to be a round-trip, so do one big request
105 instead of one per pixel */
106 for (x = 0; x < width; ++x) {
107 colors[x].pixel = XGetPixel(image, x, y);
109 XQueryColors(display, attr.colormap, colors, width);
110 for (x = 0; x < width; ++x) {
111 cp->rgb.r = colors[x].red >> 8;
112 cp->rgb.g = colors[x].green >> 8;
113 cp->rgb.b = colors[x].blue >> 8;
116 i_plin(result, 0, width, y, line);
120 XDestroyImage(image);
122 XSetErrorHandler(old_handler);
124 XCloseDisplay(display);
126 i_tags_setn(&result->tags, "ss_window_width", attr.width);
127 i_tags_setn(&result->tags, "ss_window_height", attr.height);
128 i_tags_set(&result->tags, "ss_type", "X11", 3);
129 i_tags_setn(&result->tags, "ss_left", left);
130 i_tags_setn(&result->tags, "ss_top", top);
136 imss_x11_open(char const *display_name) {
137 XErrorHandler old_handler;
141 old_handler = XSetErrorHandler(my_handler);
142 display = XOpenDisplay(display_name);
144 i_push_errorf(0, "Cannot connect to X server %s", XDisplayName(display_name));
146 XSetErrorHandler(old_handler);
148 return (unsigned long)display;
152 imss_x11_close(unsigned long display) {
153 XCloseDisplay((Display *)display);