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