various distribution fixes:
[imager-screenshot.git] / scx11.c
CommitLineData
b2239557
TC
1#include "imext.h"
2#include <X11/Xlib.h>
3
4static
5int
6my_handler(Display *display, XErrorEvent *error) {
7 char buffer[500];
8
9 XGetErrorText(display, error->error_code, buffer, sizeof(buffer));
10 i_push_error(error->error_code, buffer);
11}
12
13i_img *
14imss_x11(unsigned long display_ul, unsigned long window_id) {
15 Display *display = (Display *)display_ul;
16 int own_display = 0; /* non-zero if we connect */
17 GC gc;
18 XImage *image;
19 XWindowAttributes attr;
20 i_img *result;
21 i_color *line, *cp;
22 int x, y;
23 XColor *colors;
24 XErrorHandler old_handler;
25
26 i_clear_error();
27
28 /* we don't want the default noisy error handling */
29 old_handler = XSetErrorHandler(my_handler);
30
31 if (!display) {
32 display = XOpenDisplay(NULL);
33 ++own_display;
34 if (!display) {
35 XSetErrorHandler(old_handler);
36 i_push_error(0, "No display supplied and cannot connect");
37 return NULL;
38 }
39 }
40
41 if (!window_id) {
42 int screen = DefaultScreen(display);
43 window_id = RootWindow(display, 0);
44 }
45
46 if (!XGetWindowAttributes(display, window_id, &attr)) {
47 XSetErrorHandler(old_handler);
48 if (own_display)
49 XCloseDisplay(display);
50 i_push_error(0, "Cannot XGetWindowAttributes");
51 return NULL;
52 }
53
54 image = XGetImage(display, window_id, 0, 0, attr.width, attr.height,
55 -1, ZPixmap);
56 if (!image) {
57 XSetErrorHandler(old_handler);
58 if (own_display)
59 XCloseDisplay(display);
60 i_push_error(0, "Cannot XGetImage");
61 return NULL;
62 }
63
64 result = i_img_8_new(attr.width, attr.height, 3);
65 line = mymalloc(sizeof(i_color) * attr.width);
66 colors = mymalloc(sizeof(XColor) * attr.width);
67 for (y = 0; y < attr.height; ++y) {
68 cp = line;
69 /* XQueryColors seems to be a round-trip, so do one big request
70 instead of one per pixel */
71 for (x = 0; x < attr.width; ++x) {
72 colors[x].pixel = XGetPixel(image, x, y);
73 }
74 XQueryColors(display, attr.colormap, colors, attr.width);
75 for (x = 0; x < attr.width; ++x) {
76 cp->rgb.r = colors[x].red >> 8;
77 cp->rgb.g = colors[x].green >> 8;
78 cp->rgb.b = colors[x].blue >> 8;
79 ++cp;
80 }
81 i_plin(result, 0, attr.width, y, line);
82 }
83
84 XSetErrorHandler(old_handler);
85 if (own_display)
86 XCloseDisplay(display);
87
88 return result;
89}
90
91unsigned long
92imss_x11_open(char const *display_name) {
93 XErrorHandler old_handler;
94 Display *display;
95
96 i_clear_error();
97 XSetErrorHandler(my_handler);
98 display = XOpenDisplay(display_name);
99 if (!display)
100 i_push_errorf(0, "Cannot connect to X server %s", XDisplayName(display_name));
101
102 XSetErrorHandler(old_handler);
103
104 return (unsigned long)display;
105}
106
107void
108imss_x11_close(unsigned long display) {
109 XCloseDisplay((Display *)display);
110}