Git init
[framework/uifw/xorg/xcb/xcb-util.git] / aux / xcb_aux.c
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 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <xcb/xcb.h>
37 #include "xcb_aux.h"
38
39 /* Connection related functions */
40
41 uint8_t
42 xcb_aux_get_depth (xcb_connection_t *c,
43                    xcb_screen_t     *screen)
44 {
45   xcb_drawable_t            drawable;
46   xcb_get_geometry_reply_t *geom;
47   int                       depth = 0;
48
49   drawable = screen->root;
50   geom = xcb_get_geometry_reply (c, xcb_get_geometry(c, drawable), 0);
51
52   if (geom) {
53     depth = geom->depth;
54     free (geom);
55   }
56
57   return depth;
58 }
59
60 uint8_t
61 xcb_aux_get_depth_of_visual (xcb_screen_t *screen,
62                              xcb_visualid_t id)
63 {
64     xcb_depth_iterator_t i;
65     xcb_visualtype_iterator_t j;
66     for (i = xcb_screen_allowed_depths_iterator(screen);
67          i.rem; xcb_depth_next(&i))
68         for (j = xcb_depth_visuals_iterator(i.data);
69              j.rem; xcb_visualtype_next(&j))
70             if (j.data->visual_id == id)
71                 return i.data->depth;
72     return 0;
73 }
74
75 xcb_screen_t *
76 xcb_aux_get_screen (xcb_connection_t *c,
77                     int               screen)
78 {
79   xcb_screen_iterator_t i = xcb_setup_roots_iterator(xcb_get_setup(c));
80   for (; i.rem; --screen, xcb_screen_next(&i))
81     if (screen == 0)
82       return i.data;
83   return 0;
84 }
85
86 xcb_visualtype_t *
87 xcb_aux_get_visualtype (xcb_connection_t *c,
88                         int               scr,
89                         xcb_visualid_t    vid)
90 {
91   xcb_screen_t        *screen;
92   xcb_depth_t         *depth;
93   xcb_visualtype_iterator_t iter;
94   int               cur;
95
96   screen = xcb_aux_get_screen (c, scr);
97   if (!screen) return NULL;
98
99   depth = xcb_screen_allowed_depths_iterator(screen).data;
100   if (!depth) return NULL;
101    
102    iter = xcb_depth_visuals_iterator(depth);
103    for (cur = 0 ; cur < iter.rem ; xcb_visualtype_next(&iter), ++cur)
104       if (vid == iter.data->visual_id)
105          return iter.data;
106
107    return NULL;
108 }
109
110 xcb_visualtype_t *
111 xcb_aux_find_visual_by_id (xcb_screen_t *screen,
112                            xcb_visualid_t id)
113 {
114     xcb_depth_iterator_t i;
115     xcb_visualtype_iterator_t j;
116     for (i = xcb_screen_allowed_depths_iterator(screen);
117          i.rem; xcb_depth_next(&i))
118         for (j = xcb_depth_visuals_iterator(i.data);
119              j.rem; xcb_visualtype_next(&j))
120             if (j.data->visual_id == id)
121                 return j.data;
122     return 0;
123 }
124
125 xcb_visualtype_t *
126 xcb_aux_find_visual_by_attrs (xcb_screen_t *screen,
127                               int8_t class,
128                               int8_t depth)
129 {
130     xcb_depth_iterator_t i;
131     xcb_visualtype_iterator_t j;
132     for (i = xcb_screen_allowed_depths_iterator(screen);
133          i.rem; xcb_depth_next(&i)) {
134         if (depth != -1 && i.data->depth != depth)
135             continue;
136         for (j = xcb_depth_visuals_iterator(i.data);
137              j.rem; xcb_visualtype_next(&j))
138             if (class == -1 || j.data->_class == class)
139                 return j.data;
140     }
141     return 0;
142 }
143
144 void
145 xcb_aux_sync (xcb_connection_t *c)
146 {
147     free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL));
148 }
149
150 /* structs instead of value lists */
151 /* TODO: generate the struct types and functions from protocol masks and descriptions */
152
153 /* This generic implementation of pack_list depends on:
154    a) structs packed to uint32_t size
155    b) structs consist of just uint32_t/int32_t fields in the same order as bitmask
156 */
157
158 static void
159 pack_list( uint32_t mask, const uint32_t *src, uint32_t *dest )
160 {
161         for ( ; mask; mask >>= 1, src++)
162                 if (mask & 1)
163                         *dest++ = *src;
164 }
165
166 xcb_void_cookie_t
167 xcb_aux_create_window (xcb_connection_t       *c,
168                        uint8_t                depth,
169                        xcb_window_t           wid,
170                        xcb_window_t           parent,
171                        int16_t                x,
172                        int16_t                y,
173                        uint16_t               width,
174                        uint16_t               height,
175                        uint16_t               border_width,
176                        uint16_t               _class,
177                        xcb_visualid_t         visual,
178                        uint32_t               mask,
179                        const xcb_params_cw_t *params)
180 {
181         uint32_t value_list[16];
182         pack_list(mask, (const uint32_t *)params, value_list);
183         return xcb_create_window(c, depth, wid, parent,
184                 x, y, width, height, border_width,
185                 _class, visual, mask, value_list);
186 }
187
188 xcb_void_cookie_t
189 xcb_aux_create_window_checked (xcb_connection_t       *c,
190                                uint8_t                depth,
191                                xcb_window_t           wid,
192                                xcb_window_t           parent,
193                                int16_t                x,
194                                int16_t                y,
195                                uint16_t               width,
196                                uint16_t               height,
197                                uint16_t               border_width,
198                                uint16_t               _class,
199                                xcb_visualid_t         visual,
200                                uint32_t               mask,
201                                const xcb_params_cw_t *params)
202 {
203         uint32_t value_list[16];
204         pack_list(mask, (const uint32_t *)params, value_list);
205         return xcb_create_window_checked(c, depth, wid, parent,
206                                          x, y, width, height, border_width,
207                                          _class, visual, mask, value_list);
208 }
209
210 xcb_void_cookie_t
211 xcb_aux_change_window_attributes_checked (xcb_connection_t      *c,
212                                           xcb_window_t           window,
213                                           uint32_t               mask,
214                                           const xcb_params_cw_t *params)
215 {
216         uint32_t value_list[16];
217         pack_list(mask, (const uint32_t *)params, value_list);
218         return xcb_change_window_attributes_checked( c, window, mask, value_list );
219 }
220
221 xcb_void_cookie_t
222 xcb_aux_change_window_attributes (xcb_connection_t      *c,
223                                   xcb_window_t           window,
224                                   uint32_t               mask,
225                                   const xcb_params_cw_t *params)
226 {
227         uint32_t value_list[16];
228         pack_list(mask, (const uint32_t *)params, value_list);
229         return xcb_change_window_attributes( c, window, mask, value_list );
230 }
231
232 xcb_void_cookie_t
233 xcb_aux_configure_window (xcb_connection_t                    *c,
234                           xcb_window_t                         window,
235                           uint16_t                             mask,
236                           const xcb_params_configure_window_t *params)
237 {
238         uint32_t value_list[8];
239         pack_list(mask, (const uint32_t *)params, value_list);
240         return xcb_configure_window( c, window, mask, value_list );
241 }
242
243 xcb_void_cookie_t
244 xcb_aux_create_gc (xcb_connection_t      *c,
245                    xcb_gcontext_t         gid,
246                    xcb_drawable_t         drawable,
247                    uint32_t               mask,
248                    const xcb_params_gc_t *params)
249 {
250         uint32_t value_list[32];
251         pack_list(mask, (const uint32_t *)params, value_list);
252         return xcb_create_gc( c, gid, drawable, mask, value_list );
253 }
254
255 xcb_void_cookie_t
256 xcb_aux_create_gc_checked (xcb_connection_t      *c,
257                            xcb_gcontext_t         gid,
258                            xcb_drawable_t         drawable,
259                            uint32_t               mask,
260                            const xcb_params_gc_t *params)
261 {
262         uint32_t value_list[32];
263         pack_list(mask, (const uint32_t *)params, value_list);
264         return xcb_create_gc_checked( c, gid, drawable, mask, value_list);
265 }
266
267 xcb_void_cookie_t
268 xcb_aux_change_gc (xcb_connection_t     *c,
269                    xcb_gcontext_t        gc,
270                    uint32_t              mask,
271                    const xcb_params_gc_t *params)
272 {
273         uint32_t value_list[32];
274         pack_list(mask, (const uint32_t *)params, value_list);
275         return xcb_change_gc( c, gc, mask, value_list );
276 }
277
278 xcb_void_cookie_t
279 xcb_aux_change_gc_checked (xcb_connection_t     *c,
280                            xcb_gcontext_t        gc,
281                            uint32_t              mask,
282                            const xcb_params_gc_t *params)
283 {
284         uint32_t value_list[32];
285         pack_list(mask, (const uint32_t *)params, value_list);
286         return xcb_change_gc_checked( c, gc, mask, value_list );
287 }
288
289 xcb_void_cookie_t
290 xcb_aux_change_keyboard_control (xcb_connection_t            *c,
291                                  uint32_t                     mask,
292                                  const xcb_params_keyboard_t *params)
293 {
294         uint32_t value_list[16];
295         pack_list(mask, (const uint32_t *)params, value_list);
296         return xcb_change_keyboard_control( c, mask, value_list );
297 }
298
299 /* Color related functions */
300
301 /* Return true if the given color name can be translated locally,
302    in which case load the components.  Otherwise, a lookup_color request
303    will be needed, so return false. */
304 int
305 xcb_aux_parse_color(char *color_name,
306                     uint16_t *red,  uint16_t *green,  uint16_t *blue)
307 {
308     int n, r, g, b, i;
309     if (!color_name || *color_name != '#')
310         return 0;
311     /*
312      * Excitingly weird RGB parsing code from Xlib.
313      */
314     n = strlen (color_name);
315     color_name++;
316     n--;
317     if (n != 3 && n != 6 && n != 9 && n != 12)
318         return 0;
319     n /= 3;
320     g = b = 0;
321     do {
322         r = g;
323         g = b;
324         b = 0;
325         for (i = n; --i >= 0; ) {
326             char c = *color_name++;
327             b <<= 4;
328             if (c >= '0' && c <= '9')
329                 b |= c - '0';
330             else if (c >= 'A' && c <= 'F')
331                 b |= c - ('A' - 10);
332             else if (c >= 'a' && c <= 'f')
333                 b |= c - ('a' - 10);
334             else return 0;
335         }
336     } while (*color_name != '\0');
337     n <<= 2;
338     n = 16 - n;
339     *red = r << n;
340     *green = g << n;
341     *blue = b << n;
342     return 1;
343 }
344
345 /* Drawing related functions */
346
347 /* Adapted from Xlib */
348 xcb_void_cookie_t
349 xcb_aux_set_line_attributes_checked (xcb_connection_t *dpy,
350                                      xcb_gcontext_t gc,
351                                      uint16_t linewidth,
352                                      int32_t linestyle,
353                                      int32_t capstyle,
354                                      int32_t joinstyle)
355 {
356     uint32_t mask = 0;
357     xcb_params_gc_t gv;
358
359     XCB_AUX_ADD_PARAM(&mask, &gv, line_width, linewidth);
360     XCB_AUX_ADD_PARAM(&mask, &gv, line_style, linestyle);
361     XCB_AUX_ADD_PARAM(&mask, &gv, cap_style, capstyle);
362     XCB_AUX_ADD_PARAM(&mask, &gv, join_style, joinstyle);
363     return xcb_aux_change_gc_checked(dpy, gc, mask, &gv);
364 }
365
366 /* Adapted from Xlib */
367 /* XXX It would be wiser for apps just to call
368    clear_area() directly. */
369 xcb_void_cookie_t
370 xcb_aux_clear_window(xcb_connection_t *  dpy,
371                      xcb_window_t        w)
372 {
373     return xcb_clear_area(dpy, 0, w, 0, 0, 0, 0);
374 }