xcb_aux.c revision ecce36be
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
41uint8_t
42xcb_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
60uint8_t
61xcb_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
75xcb_screen_t *
76xcb_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
86xcb_visualtype_t *
87xcb_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
110xcb_visualtype_t *
111xcb_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
125xcb_visualtype_t *
126xcb_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
144void
145xcb_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
158static void
159pack_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
166xcb_void_cookie_t
167xcb_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
188xcb_void_cookie_t
189xcb_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
210xcb_void_cookie_t
211xcb_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
221xcb_void_cookie_t
222xcb_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
232xcb_void_cookie_t
233xcb_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
243xcb_void_cookie_t
244xcb_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
255xcb_void_cookie_t
256xcb_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
267xcb_void_cookie_t
268xcb_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
278xcb_void_cookie_t
279xcb_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
289xcb_void_cookie_t
290xcb_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. */
304int
305xcb_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 */
348xcb_void_cookie_t
349xcb_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. */
369xcb_void_cookie_t
370xcb_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}
375