0.003 release
[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 }
bc7a6f7b
TC
83 myfree(line);
84 myfree(colors);
85 XDestroyImage(image);
b2239557
TC
86
87 XSetErrorHandler(old_handler);
88 if (own_display)
89 XCloseDisplay(display);
90
91 return result;
92}
93
94unsigned long
95imss_x11_open(char const *display_name) {
96 XErrorHandler old_handler;
97 Display *display;
98
99 i_clear_error();
bc7a6f7b 100 old_handler = XSetErrorHandler(my_handler);
b2239557
TC
101 display = XOpenDisplay(display_name);
102 if (!display)
103 i_push_errorf(0, "Cannot connect to X server %s", XDisplayName(display_name));
104
105 XSetErrorHandler(old_handler);
106
107 return (unsigned long)display;
108}
109
110void
111imss_x11_close(unsigned long display) {
112 XCloseDisplay((Display *)display);
113}