1 /*
2 * Copyright © 2008 Bart Massey <bart@cs.pdx.edu>
3 * Copyright © 2008 Ian Osgood <iano@quirkster.com>
4 * Copyright © 2008 Jamey Sharp <jamey@minilop.net>
5 * Copyright © 2008 Josh Triplett <josh@freedesktop.org>
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use, copy,
11 * modify, merge, publish, distribute, sublicense, and/or sell copies
12 * of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Except as contained in this notice, the names of the authors or
27 * their institutions shall not be used in advertising or otherwise to
28 * promote the sale, use or other dealings in this Software without
29 * prior written authorization from the authors.
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <xcb/xcb.h>
41 #include "xcb_aux.h"
42
43 /* Connection related functions */
44
45 uint8_t
xcb_aux_get_depth(xcb_connection_t * c,xcb_screen_t * screen)46 xcb_aux_get_depth (xcb_connection_t *c,
47 xcb_screen_t *screen)
48 {
49 xcb_drawable_t drawable;
50 xcb_get_geometry_reply_t *geom;
51 int depth = 0;
52
53 drawable = screen->root;
54 geom = xcb_get_geometry_reply (c, xcb_get_geometry(c, drawable), 0);
55
56 if (geom) {
57 depth = geom->depth;
58 free (geom);
59 }
60
61 return depth;
62 }
63
64 uint8_t
xcb_aux_get_depth_of_visual(xcb_screen_t * screen,xcb_visualid_t id)65 xcb_aux_get_depth_of_visual (xcb_screen_t *screen,
66 xcb_visualid_t id)
67 {
68 xcb_depth_iterator_t i;
69 xcb_visualtype_iterator_t j;
70 for (i = xcb_screen_allowed_depths_iterator(screen);
71 i.rem; xcb_depth_next(&i))
72 for (j = xcb_depth_visuals_iterator(i.data);
73 j.rem; xcb_visualtype_next(&j))
74 if (j.data->visual_id == id)
75 return i.data->depth;
76 return 0;
77 }
78
79 xcb_screen_t *
xcb_aux_get_screen(xcb_connection_t * c,int screen)80 xcb_aux_get_screen (xcb_connection_t *c,
81 int screen)
82 {
83 xcb_screen_iterator_t i = xcb_setup_roots_iterator(xcb_get_setup(c));
84 for (; i.rem; --screen, xcb_screen_next(&i))
85 if (screen == 0)
86 return i.data;
87 return 0;
88 }
89
90 xcb_visualtype_t *
xcb_aux_get_visualtype(xcb_connection_t * c,int scr,xcb_visualid_t vid)91 xcb_aux_get_visualtype (xcb_connection_t *c,
92 int scr,
93 xcb_visualid_t vid)
94 {
95 xcb_screen_t *screen;
96 xcb_depth_t *depth;
97 xcb_visualtype_iterator_t iter;
98 int cur;
99
100 screen = xcb_aux_get_screen (c, scr);
101 if (!screen) return NULL;
102
103 depth = xcb_screen_allowed_depths_iterator(screen).data;
104 if (!depth) return NULL;
105
106 iter = xcb_depth_visuals_iterator(depth);
107 for (cur = 0 ; cur < iter.rem ; xcb_visualtype_next(&iter), ++cur)
108 if (vid == iter.data->visual_id)
109 return iter.data;
110
111 return NULL;
112 }
113
114 xcb_visualtype_t *
xcb_aux_find_visual_by_id(xcb_screen_t * screen,xcb_visualid_t id)115 xcb_aux_find_visual_by_id (xcb_screen_t *screen,
116 xcb_visualid_t id)
117 {
118 xcb_depth_iterator_t i;
119 xcb_visualtype_iterator_t j;
120 for (i = xcb_screen_allowed_depths_iterator(screen);
121 i.rem; xcb_depth_next(&i))
122 for (j = xcb_depth_visuals_iterator(i.data);
123 j.rem; xcb_visualtype_next(&j))
124 if (j.data->visual_id == id)
125 return j.data;
126 return 0;
127 }
128
129 xcb_visualtype_t *
xcb_aux_find_visual_by_attrs(xcb_screen_t * screen,int8_t class,int8_t depth)130 xcb_aux_find_visual_by_attrs (xcb_screen_t *screen,
131 int8_t class,
132 int8_t depth)
133 {
134 xcb_depth_iterator_t i;
135 xcb_visualtype_iterator_t j;
136 for (i = xcb_screen_allowed_depths_iterator(screen);
137 i.rem; xcb_depth_next(&i)) {
138 if (depth != -1 && i.data->depth != depth)
139 continue;
140 for (j = xcb_depth_visuals_iterator(i.data);
141 j.rem; xcb_visualtype_next(&j))
142 if (class == -1 || j.data->_class == class)
143 return j.data;
144 }
145 return 0;
146 }
147
148 void
xcb_aux_sync(xcb_connection_t * c)149 xcb_aux_sync (xcb_connection_t *c)
150 {
151 free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL));
152 }
153
154 /* structs instead of value lists */
155 /* TODO: generate the struct types and functions from protocol masks and descriptions */
156
157 /* This generic implementation of pack_list depends on:
158 a) structs packed to uint32_t size
159 b) structs consist of just uint32_t/int32_t fields in the same order as bitmask
160 */
161
162 static void
pack_list(uint32_t mask,const uint32_t * src,uint32_t * dest)163 pack_list( uint32_t mask, const uint32_t *src, uint32_t *dest )
164 {
165 for ( ; mask; mask >>= 1, src++)
166 if (mask & 1)
167 *dest++ = *src;
168 }
169
170 xcb_void_cookie_t
xcb_aux_create_window(xcb_connection_t * c,uint8_t depth,xcb_window_t wid,xcb_window_t parent,int16_t x,int16_t y,uint16_t width,uint16_t height,uint16_t border_width,uint16_t _class,xcb_visualid_t visual,uint32_t mask,const xcb_params_cw_t * params)171 xcb_aux_create_window (xcb_connection_t *c,
172 uint8_t depth,
173 xcb_window_t wid,
174 xcb_window_t parent,
175 int16_t x,
176 int16_t y,
177 uint16_t width,
178 uint16_t height,
179 uint16_t border_width,
180 uint16_t _class,
181 xcb_visualid_t visual,
182 uint32_t mask,
183 const xcb_params_cw_t *params)
184 {
185 uint32_t value_list[16];
186 pack_list(mask, (const uint32_t *)params, value_list);
187 return xcb_create_window(c, depth, wid, parent,
188 x, y, width, height, border_width,
189 _class, visual, mask, value_list);
190 }
191
192 xcb_void_cookie_t
xcb_aux_create_window_checked(xcb_connection_t * c,uint8_t depth,xcb_window_t wid,xcb_window_t parent,int16_t x,int16_t y,uint16_t width,uint16_t height,uint16_t border_width,uint16_t _class,xcb_visualid_t visual,uint32_t mask,const xcb_params_cw_t * params)193 xcb_aux_create_window_checked (xcb_connection_t *c,
194 uint8_t depth,
195 xcb_window_t wid,
196 xcb_window_t parent,
197 int16_t x,
198 int16_t y,
199 uint16_t width,
200 uint16_t height,
201 uint16_t border_width,
202 uint16_t _class,
203 xcb_visualid_t visual,
204 uint32_t mask,
205 const xcb_params_cw_t *params)
206 {
207 uint32_t value_list[16];
208 pack_list(mask, (const uint32_t *)params, value_list);
209 return xcb_create_window_checked(c, depth, wid, parent,
210 x, y, width, height, border_width,
211 _class, visual, mask, value_list);
212 }
213
214 xcb_void_cookie_t
xcb_aux_change_window_attributes_checked(xcb_connection_t * c,xcb_window_t window,uint32_t mask,const xcb_params_cw_t * params)215 xcb_aux_change_window_attributes_checked (xcb_connection_t *c,
216 xcb_window_t window,
217 uint32_t mask,
218 const xcb_params_cw_t *params)
219 {
220 uint32_t value_list[16];
221 pack_list(mask, (const uint32_t *)params, value_list);
222 return xcb_change_window_attributes_checked( c, window, mask, value_list );
223 }
224
225 xcb_void_cookie_t
xcb_aux_change_window_attributes(xcb_connection_t * c,xcb_window_t window,uint32_t mask,const xcb_params_cw_t * params)226 xcb_aux_change_window_attributes (xcb_connection_t *c,
227 xcb_window_t window,
228 uint32_t mask,
229 const xcb_params_cw_t *params)
230 {
231 uint32_t value_list[16];
232 pack_list(mask, (const uint32_t *)params, value_list);
233 return xcb_change_window_attributes( c, window, mask, value_list );
234 }
235
236 xcb_void_cookie_t
xcb_aux_configure_window(xcb_connection_t * c,xcb_window_t window,uint16_t mask,const xcb_params_configure_window_t * params)237 xcb_aux_configure_window (xcb_connection_t *c,
238 xcb_window_t window,
239 uint16_t mask,
240 const xcb_params_configure_window_t *params)
241 {
242 uint32_t value_list[8];
243 pack_list(mask, (const uint32_t *)params, value_list);
244 return xcb_configure_window( c, window, mask, value_list );
245 }
246
247 xcb_void_cookie_t
xcb_aux_create_gc(xcb_connection_t * c,xcb_gcontext_t gid,xcb_drawable_t drawable,uint32_t mask,const xcb_params_gc_t * params)248 xcb_aux_create_gc (xcb_connection_t *c,
249 xcb_gcontext_t gid,
250 xcb_drawable_t drawable,
251 uint32_t mask,
252 const xcb_params_gc_t *params)
253 {
254 uint32_t value_list[32];
255 pack_list(mask, (const uint32_t *)params, value_list);
256 return xcb_create_gc( c, gid, drawable, mask, value_list );
257 }
258
259 xcb_void_cookie_t
xcb_aux_create_gc_checked(xcb_connection_t * c,xcb_gcontext_t gid,xcb_drawable_t drawable,uint32_t mask,const xcb_params_gc_t * params)260 xcb_aux_create_gc_checked (xcb_connection_t *c,
261 xcb_gcontext_t gid,
262 xcb_drawable_t drawable,
263 uint32_t mask,
264 const xcb_params_gc_t *params)
265 {
266 uint32_t value_list[32];
267 pack_list(mask, (const uint32_t *)params, value_list);
268 return xcb_create_gc_checked( c, gid, drawable, mask, value_list);
269 }
270
271 xcb_void_cookie_t
xcb_aux_change_gc(xcb_connection_t * c,xcb_gcontext_t gc,uint32_t mask,const xcb_params_gc_t * params)272 xcb_aux_change_gc (xcb_connection_t *c,
273 xcb_gcontext_t gc,
274 uint32_t mask,
275 const xcb_params_gc_t *params)
276 {
277 uint32_t value_list[32];
278 pack_list(mask, (const uint32_t *)params, value_list);
279 return xcb_change_gc( c, gc, mask, value_list );
280 }
281
282 xcb_void_cookie_t
xcb_aux_change_gc_checked(xcb_connection_t * c,xcb_gcontext_t gc,uint32_t mask,const xcb_params_gc_t * params)283 xcb_aux_change_gc_checked (xcb_connection_t *c,
284 xcb_gcontext_t gc,
285 uint32_t mask,
286 const xcb_params_gc_t *params)
287 {
288 uint32_t value_list[32];
289 pack_list(mask, (const uint32_t *)params, value_list);
290 return xcb_change_gc_checked( c, gc, mask, value_list );
291 }
292
293 xcb_void_cookie_t
xcb_aux_change_keyboard_control(xcb_connection_t * c,uint32_t mask,const xcb_params_keyboard_t * params)294 xcb_aux_change_keyboard_control (xcb_connection_t *c,
295 uint32_t mask,
296 const xcb_params_keyboard_t *params)
297 {
298 uint32_t value_list[16];
299 pack_list(mask, (const uint32_t *)params, value_list);
300 return xcb_change_keyboard_control( c, mask, value_list );
301 }
302
303 /* Color related functions */
304
305 /* Return true if the given color name can be translated locally,
306 in which case load the components. Otherwise, a lookup_color request
307 will be needed, so return false. */
308 int
xcb_aux_parse_color(const char * color_name,uint16_t * red,uint16_t * green,uint16_t * blue)309 xcb_aux_parse_color(const char *color_name,
310 uint16_t *red, uint16_t *green, uint16_t *blue)
311 {
312 int n, r, g, b, i;
313 if (!color_name || *color_name != '#')
314 return 0;
315 /*
316 * Excitingly weird RGB parsing code from Xlib.
317 */
318 n = strlen (color_name);
319 color_name++;
320 n--;
321 if (n != 3 && n != 6 && n != 9 && n != 12)
322 return 0;
323 n /= 3;
324 g = b = 0;
325 do {
326 r = g;
327 g = b;
328 b = 0;
329 for (i = n; --i >= 0; ) {
330 char c = *color_name++;
331 b <<= 4;
332 if (c >= '0' && c <= '9')
333 b |= c - '0';
334 else if (c >= 'A' && c <= 'F')
335 b |= c - ('A' - 10);
336 else if (c >= 'a' && c <= 'f')
337 b |= c - ('a' - 10);
338 else return 0;
339 }
340 } while (*color_name != '\0');
341 n <<= 2;
342 n = 16 - n;
343 *red = r << n;
344 *green = g << n;
345 *blue = b << n;
346 return 1;
347 }
348
349 /* Drawing related functions */
350
351 /* Adapted from Xlib */
352 xcb_void_cookie_t
xcb_aux_set_line_attributes_checked(xcb_connection_t * dpy,xcb_gcontext_t gc,uint16_t linewidth,int32_t linestyle,int32_t capstyle,int32_t joinstyle)353 xcb_aux_set_line_attributes_checked (xcb_connection_t *dpy,
354 xcb_gcontext_t gc,
355 uint16_t linewidth,
356 int32_t linestyle,
357 int32_t capstyle,
358 int32_t joinstyle)
359 {
360 uint32_t mask = 0;
361 xcb_params_gc_t gv;
362
363 XCB_AUX_ADD_PARAM(&mask, &gv, line_width, linewidth);
364 XCB_AUX_ADD_PARAM(&mask, &gv, line_style, linestyle);
365 XCB_AUX_ADD_PARAM(&mask, &gv, cap_style, capstyle);
366 XCB_AUX_ADD_PARAM(&mask, &gv, join_style, joinstyle);
367 return xcb_aux_change_gc_checked(dpy, gc, mask, &gv);
368 }
369
370 /* Adapted from Xlib */
371 /* XXX It would be wiser for apps just to call
372 clear_area() directly. */
373 xcb_void_cookie_t
xcb_aux_clear_window(xcb_connection_t * dpy,xcb_window_t w)374 xcb_aux_clear_window(xcb_connection_t * dpy,
375 xcb_window_t w)
376 {
377 return xcb_clear_area(dpy, 0, w, 0, 0, 0, 0);
378 }
379