1/* 2 * Copyright © 2008 Arnaud Fontaine <arnau@debian.org> 3 * Copyright © 2007-2008 Vincent Torri <vtorri@univ-evry.fr> 4 * 5 * Permission is hereby granted, free of charge, to any person 6 * obtaining a copy of this software and associated documentation 7 * files (the "Software"), to deal in the Software without 8 * restriction, including without limitation the rights to use, copy, 9 * modify, merge, publish, distribute, sublicense, and/or sell copies 10 * of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 20 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Except as contained in this notice, the names of the authors or 25 * their institutions shall not be used in advertising or otherwise to 26 * promote the sale, use or other dealings in this Software without 27 * prior written authorization from the authors. 28 */ 29 30#include <stdlib.h> 31#include <limits.h> 32#include <string.h> 33 34#include "xcb_icccm.h" 35#include "xcb_atom.h" 36 37xcb_get_property_cookie_t 38xcb_get_text_property(xcb_connection_t *c, 39 xcb_window_t window, 40 xcb_atom_t property) 41{ 42 return xcb_get_any_property(c, 0, window, property, UINT_MAX); 43} 44 45xcb_get_property_cookie_t 46xcb_get_text_property_unchecked(xcb_connection_t *c, 47 xcb_window_t window, 48 xcb_atom_t property) 49{ 50 return xcb_get_any_property_unchecked(c, 0, window, property, UINT_MAX); 51} 52 53uint8_t 54xcb_get_text_property_reply(xcb_connection_t *c, 55 xcb_get_property_cookie_t cookie, 56 xcb_get_text_property_reply_t *prop, 57 xcb_generic_error_t **e) 58{ 59 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 60 61 if(!reply) 62 return 0; 63 64 prop->_reply = reply; 65 prop->encoding = prop->_reply->type; 66 prop->format = prop->_reply->format; 67 prop->name_len = xcb_get_property_value_length(prop->_reply); 68 prop->name = xcb_get_property_value(prop->_reply); 69 70 return 1; 71} 72 73void 74xcb_get_text_property_reply_wipe(xcb_get_text_property_reply_t *prop) 75{ 76 free(prop->_reply); 77} 78 79/* WM_NAME */ 80 81void 82xcb_set_wm_name_checked(xcb_connection_t *c, xcb_window_t window, 83 xcb_atom_t encoding, uint32_t name_len, 84 const char *name) 85{ 86 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_NAME, 87 encoding, 8, name_len, name); 88} 89 90void 91xcb_set_wm_name(xcb_connection_t *c, xcb_window_t window, xcb_atom_t encoding, 92 uint32_t name_len, const char *name) 93{ 94 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_NAME, encoding, 8, 95 name_len, name); 96} 97 98xcb_get_property_cookie_t 99xcb_get_wm_name(xcb_connection_t *c, 100 xcb_window_t window) 101{ 102 return xcb_get_text_property(c, window, WM_NAME); 103} 104 105xcb_get_property_cookie_t 106xcb_get_wm_name_unchecked(xcb_connection_t *c, 107 xcb_window_t window) 108{ 109 return xcb_get_text_property_unchecked(c, window, WM_NAME); 110} 111 112uint8_t 113xcb_get_wm_name_reply(xcb_connection_t *c, 114 xcb_get_property_cookie_t cookie, 115 xcb_get_text_property_reply_t *prop, 116 xcb_generic_error_t **e) 117{ 118 return xcb_get_text_property_reply(c, cookie, prop, e); 119} 120 121void 122xcb_watch_wm_name(xcb_property_handlers_t *prophs, uint32_t long_len, 123 xcb_generic_property_handler_t handler, void *data) 124{ 125 xcb_property_set_handler(prophs, WM_NAME, long_len, handler, data); 126} 127 128/* WM_ICON_NAME */ 129 130void 131xcb_set_wm_icon_name_checked(xcb_connection_t *c, xcb_window_t window, 132 xcb_atom_t encoding, uint32_t name_len, 133 const char *name) 134{ 135 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_ICON_NAME, 136 encoding, 8, name_len, name); 137} 138 139void 140xcb_set_wm_icon_name(xcb_connection_t *c, xcb_window_t window, 141 xcb_atom_t encoding, uint32_t name_len, const char *name) 142{ 143 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_ICON_NAME, encoding, 144 8, name_len, name); 145} 146 147xcb_get_property_cookie_t 148xcb_get_wm_icon_name(xcb_connection_t *c, 149 xcb_window_t window) 150{ 151 return xcb_get_text_property(c, window, WM_ICON_NAME); 152} 153 154xcb_get_property_cookie_t 155xcb_get_wm_icon_name_unchecked(xcb_connection_t *c, 156 xcb_window_t window) 157{ 158 return xcb_get_text_property_unchecked(c, window, WM_ICON_NAME); 159} 160 161uint8_t 162xcb_get_wm_icon_name_reply(xcb_connection_t *c, 163 xcb_get_property_cookie_t cookie, 164 xcb_get_text_property_reply_t *prop, 165 xcb_generic_error_t **e) 166{ 167 return xcb_get_text_property_reply(c, cookie, prop, e); 168} 169 170void 171xcb_watch_wm_icon_name(xcb_property_handlers_t *prophs, uint32_t long_len, 172 xcb_generic_property_handler_t handler, void *data) 173{ 174 xcb_property_set_handler(prophs, WM_ICON_NAME, long_len, handler, data); 175} 176 177/* WM_CLIENT_MACHINE */ 178 179void 180xcb_set_wm_client_machine_checked(xcb_connection_t *c, xcb_window_t window, 181 xcb_atom_t encoding, uint32_t name_len, 182 const char *name) 183{ 184 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, 185 WM_CLIENT_MACHINE, encoding, 8, name_len, name); 186} 187 188void 189xcb_set_wm_client_machine(xcb_connection_t *c, xcb_window_t window, 190 xcb_atom_t encoding, uint32_t name_len, 191 const char *name) 192{ 193 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_CLIENT_MACHINE, 194 encoding, 8, name_len, name); 195} 196 197xcb_get_property_cookie_t 198xcb_get_wm_client_machine(xcb_connection_t *c, 199 xcb_window_t window) 200{ 201 return xcb_get_text_property(c, window, WM_CLIENT_MACHINE); 202} 203 204xcb_get_property_cookie_t 205xcb_get_wm_client_machine_unchecked(xcb_connection_t *c, 206 xcb_window_t window) 207{ 208 return xcb_get_text_property_unchecked(c, window, WM_CLIENT_MACHINE); 209} 210 211uint8_t 212xcb_get_wm_client_machine_reply(xcb_connection_t *c, 213 xcb_get_property_cookie_t cookie, 214 xcb_get_text_property_reply_t *prop, 215 xcb_generic_error_t **e) 216{ 217 return xcb_get_text_property_reply(c, cookie, prop, e); 218} 219 220void 221xcb_watch_wm_client_machine(xcb_property_handlers_t *prophs, uint32_t long_len, 222 xcb_generic_property_handler_t handler, void *data) 223{ 224 xcb_property_set_handler(prophs, WM_CLIENT_MACHINE, long_len, handler, data); 225} 226 227/* WM_CLASS */ 228 229xcb_get_property_cookie_t 230xcb_get_wm_class(xcb_connection_t *c, xcb_window_t window) 231{ 232 return xcb_get_property(c, 0, window, WM_CLASS, STRING, 0L, 2048L); 233} 234 235xcb_get_property_cookie_t 236xcb_get_wm_class_unchecked(xcb_connection_t *c, xcb_window_t window) 237{ 238 return xcb_get_property_unchecked(c, 0, window, WM_CLASS, STRING, 0L, 2048L); 239} 240 241uint8_t 242xcb_get_wm_class_from_reply(xcb_get_wm_class_reply_t *prop, 243 xcb_get_property_reply_t *reply) 244{ 245 if(!reply || reply->type != STRING || reply->format != 8) 246 return 0; 247 248 prop->_reply = reply; 249 prop->instance_name = (char *) xcb_get_property_value(prop->_reply); 250 251 int name_len = strlen(prop->instance_name); 252 if(name_len == xcb_get_property_value_length(prop->_reply)) 253 name_len--; 254 255 prop->class_name = prop->instance_name + name_len + 1; 256 257 return 1; 258} 259 260uint8_t 261xcb_get_wm_class_reply(xcb_connection_t *c, xcb_get_property_cookie_t cookie, 262 xcb_get_wm_class_reply_t *prop, xcb_generic_error_t **e) 263{ 264 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 265 uint8_t ret = xcb_get_wm_class_from_reply(prop, reply); 266 /* if reply parsing failed, free the reply to avoid mem leak */ 267 if(!ret) 268 free(reply); 269 return ret; 270} 271 272void 273xcb_get_wm_class_reply_wipe(xcb_get_wm_class_reply_t *prop) 274{ 275 free(prop->_reply); 276} 277 278/* WM_TRANSIENT_FOR */ 279 280xcb_get_property_cookie_t 281xcb_get_wm_transient_for(xcb_connection_t *c, xcb_window_t window) 282{ 283 return xcb_get_property(c, 0, window, WM_TRANSIENT_FOR, WINDOW, 0, 1); 284} 285 286xcb_get_property_cookie_t 287xcb_get_wm_transient_for_unchecked(xcb_connection_t *c, xcb_window_t window) 288{ 289 return xcb_get_property_unchecked(c, 0, window, WM_TRANSIENT_FOR, WINDOW, 0, 1); 290} 291 292uint8_t 293xcb_get_wm_transient_for_from_reply(xcb_window_t *prop, 294 xcb_get_property_reply_t *reply) 295{ 296 if(!reply || reply->type != WINDOW || reply->format != 32 || !reply->length) 297 return 0; 298 299 *prop = *((xcb_window_t *) xcb_get_property_value(reply)); 300 301 return 1; 302} 303 304uint8_t 305xcb_get_wm_transient_for_reply(xcb_connection_t *c, 306 xcb_get_property_cookie_t cookie, 307 xcb_window_t *prop, 308 xcb_generic_error_t **e) 309{ 310 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 311 uint8_t ret = xcb_get_wm_transient_for_from_reply(prop, reply); 312 free(reply); 313 return ret; 314} 315 316/* WM_SIZE_HINTS */ 317 318void 319xcb_size_hints_set_position(xcb_size_hints_t *hints, int user_specified, 320 int32_t x, int32_t y) 321{ 322 hints->flags &= ~(XCB_SIZE_HINT_US_POSITION | XCB_SIZE_HINT_P_POSITION); 323 if (user_specified) 324 hints->flags |= XCB_SIZE_HINT_US_POSITION; 325 else 326 hints->flags |= XCB_SIZE_HINT_P_POSITION; 327 hints->x = x; 328 hints->y = y; 329} 330 331void 332xcb_size_hints_set_size(xcb_size_hints_t *hints, int user_specified, 333 int32_t width, int32_t height) 334{ 335 hints->flags &= ~(XCB_SIZE_HINT_US_SIZE | XCB_SIZE_HINT_P_SIZE); 336 if (user_specified) 337 hints->flags |= XCB_SIZE_HINT_US_SIZE; 338 else 339 hints->flags |= XCB_SIZE_HINT_P_SIZE; 340 hints->width = width; 341 hints->height = height; 342} 343 344void 345xcb_size_hints_set_min_size(xcb_size_hints_t *hints, int32_t min_width, 346 int32_t min_height) 347{ 348 hints->flags |= XCB_SIZE_HINT_P_MIN_SIZE; 349 hints->min_width = min_width; 350 hints->min_height = min_height; 351} 352 353void 354xcb_size_hints_set_max_size(xcb_size_hints_t *hints, int32_t max_width, 355 int32_t max_height) 356{ 357 hints->flags |= XCB_SIZE_HINT_P_MAX_SIZE; 358 hints->max_width = max_width; 359 hints->max_height = max_height; 360} 361 362void 363xcb_size_hints_set_resize_inc(xcb_size_hints_t *hints, int32_t width_inc, 364 int32_t height_inc) 365{ 366 hints->flags |= XCB_SIZE_HINT_P_RESIZE_INC; 367 hints->width_inc = width_inc; 368 hints->height_inc = height_inc; 369} 370 371void 372xcb_size_hints_set_aspect(xcb_size_hints_t *hints, int32_t min_aspect_num, 373 int32_t min_aspect_den, int32_t max_aspect_num, 374 int32_t max_aspect_den) 375{ 376 hints->flags |= XCB_SIZE_HINT_P_ASPECT; 377 hints->min_aspect_num = min_aspect_num; 378 hints->min_aspect_den = min_aspect_den; 379 hints->max_aspect_num = max_aspect_num; 380 hints->max_aspect_den = max_aspect_den; 381} 382 383void 384xcb_size_hints_set_base_size(xcb_size_hints_t *hints, int32_t base_width, 385 int32_t base_height) 386{ 387 hints->flags |= XCB_SIZE_HINT_BASE_SIZE; 388 hints->base_width = base_width; 389 hints->base_height = base_height; 390} 391 392void 393xcb_size_hints_set_win_gravity(xcb_size_hints_t *hints, xcb_gravity_t win_gravity) 394{ 395 hints->flags |= XCB_SIZE_HINT_P_WIN_GRAVITY; 396 hints->win_gravity = win_gravity; 397} 398 399void 400xcb_set_wm_size_hints_checked(xcb_connection_t *c, xcb_window_t window, 401 xcb_atom_t property, xcb_size_hints_t *hints) 402{ 403 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, property, 404 WM_SIZE_HINTS, 32, sizeof(*hints) >> 2, hints); 405} 406 407void 408xcb_set_wm_size_hints(xcb_connection_t *c, xcb_window_t window, 409 xcb_atom_t property, xcb_size_hints_t *hints) 410{ 411 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, property, 412 WM_SIZE_HINTS, 32, sizeof(*hints) >> 2, hints); 413} 414 415xcb_get_property_cookie_t 416xcb_get_wm_size_hints(xcb_connection_t *c, xcb_window_t window, 417 xcb_atom_t property) 418{ 419 /* NumPropSizeElements = 18 (ICCCM version 1). */ 420 return xcb_get_property(c, 0, window, property, WM_SIZE_HINTS, 0L, 18); 421} 422 423xcb_get_property_cookie_t 424xcb_get_wm_size_hints_unchecked(xcb_connection_t *c, xcb_window_t window, 425 xcb_atom_t property) 426{ 427 return xcb_get_property_unchecked(c, 0, window, property, WM_SIZE_HINTS, 428 0L, 18); 429} 430 431uint8_t 432xcb_get_wm_size_hints_from_reply(xcb_size_hints_t *hints, xcb_get_property_reply_t *reply) 433{ 434 uint32_t flags; 435 436 if(!reply) 437 return 0; 438 439 int length = xcb_get_property_value_length(reply) / (reply->format / 8); 440 441 if (!(reply->type == WM_SIZE_HINTS && 442 (reply->format == 8 || reply->format == 16 || 443 reply->format == 32) && 444 /* OldNumPropSizeElements = 15 (pre-ICCCM) */ 445 length >= 15)) 446 return 0; 447 448 memcpy(hints, (xcb_size_hints_t *) xcb_get_property_value (reply), 449 length * reply->format >> 3); 450 451 flags = (XCB_SIZE_HINT_US_POSITION | XCB_SIZE_HINT_US_SIZE | 452 XCB_SIZE_HINT_P_POSITION | XCB_SIZE_HINT_P_SIZE | 453 XCB_SIZE_HINT_P_MIN_SIZE | XCB_SIZE_HINT_P_MAX_SIZE | 454 XCB_SIZE_HINT_P_RESIZE_INC | XCB_SIZE_HINT_P_ASPECT); 455 456 /* NumPropSizeElements = 18 (ICCCM version 1) */ 457 if(length >= 18) 458 flags |= (XCB_SIZE_HINT_BASE_SIZE | XCB_SIZE_HINT_P_WIN_GRAVITY); 459 else 460 { 461 hints->base_width = 0; 462 hints->base_height = 0; 463 hints->win_gravity = 0; 464 } 465 /* get rid of unwanted bits */ 466 hints->flags &= flags; 467 468 return 1; 469} 470 471uint8_t 472xcb_get_wm_size_hints_reply(xcb_connection_t *c, xcb_get_property_cookie_t cookie, 473 xcb_size_hints_t *hints, xcb_generic_error_t **e) 474{ 475 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 476 uint8_t ret = xcb_get_wm_size_hints_from_reply(hints, reply); 477 free(reply); 478 return ret; 479} 480 481/* WM_NORMAL_HINTS */ 482 483void 484xcb_set_wm_normal_hints_checked(xcb_connection_t *c, xcb_window_t window, 485 xcb_size_hints_t *hints) 486{ 487 xcb_set_wm_size_hints_checked(c, window, WM_NORMAL_HINTS, hints); 488} 489 490void 491xcb_set_wm_normal_hints(xcb_connection_t *c, xcb_window_t window, 492 xcb_size_hints_t *hints) 493{ 494 xcb_set_wm_size_hints(c, window, WM_NORMAL_HINTS, hints); 495} 496 497xcb_get_property_cookie_t 498xcb_get_wm_normal_hints(xcb_connection_t *c, xcb_window_t window) 499{ 500 return xcb_get_wm_size_hints(c, window, WM_NORMAL_HINTS); 501} 502 503xcb_get_property_cookie_t 504xcb_get_wm_normal_hints_unchecked(xcb_connection_t *c, xcb_window_t window) 505{ 506 return xcb_get_wm_size_hints_unchecked(c, window, WM_NORMAL_HINTS); 507} 508 509uint8_t 510xcb_get_wm_normal_hints_reply(xcb_connection_t *c, 511 xcb_get_property_cookie_t cookie, 512 xcb_size_hints_t *hints, 513 xcb_generic_error_t **e) 514{ 515 return xcb_get_wm_size_hints_reply(c, cookie, hints, e); 516} 517 518/* WM_HINTS */ 519 520uint32_t 521xcb_wm_hints_get_urgency(xcb_wm_hints_t *hints) 522{ 523 return (hints->flags & XCB_WM_HINT_X_URGENCY); 524} 525 526void 527xcb_wm_hints_set_input(xcb_wm_hints_t *hints, uint8_t input) 528{ 529 hints->input = input; 530 hints->flags |= XCB_WM_HINT_INPUT; 531} 532 533void 534xcb_wm_hints_set_iconic(xcb_wm_hints_t *hints) 535{ 536 hints->initial_state = XCB_WM_STATE_ICONIC; 537 hints->flags |= XCB_WM_HINT_STATE; 538} 539 540void 541xcb_wm_hints_set_normal(xcb_wm_hints_t *hints) 542{ 543 hints->initial_state = XCB_WM_STATE_NORMAL; 544 hints->flags |= XCB_WM_HINT_STATE; 545} 546 547void 548xcb_wm_hints_set_withdrawn(xcb_wm_hints_t *hints) 549{ 550 hints->initial_state = XCB_WM_STATE_WITHDRAWN; 551 hints->flags |= XCB_WM_HINT_STATE; 552} 553 554void 555xcb_wm_hints_set_none(xcb_wm_hints_t *hints) 556{ 557 hints->flags &= ~XCB_WM_HINT_STATE; 558} 559 560void 561xcb_wm_hints_set_icon_pixmap(xcb_wm_hints_t *hints, xcb_pixmap_t icon_pixmap) 562{ 563 hints->icon_pixmap = icon_pixmap; 564 hints->flags |= XCB_WM_HINT_ICON_PIXMAP; 565} 566 567void 568xcb_wm_hints_set_icon_mask(xcb_wm_hints_t *hints, xcb_pixmap_t icon_mask) 569{ 570 hints->icon_mask = icon_mask; 571 hints->flags |= XCB_WM_HINT_ICON_MASK; 572} 573 574void 575xcb_wm_hints_set_icon_window(xcb_wm_hints_t *hints, xcb_window_t icon_window) 576{ 577 hints->icon_window = icon_window; 578 hints->flags |= XCB_WM_HINT_ICON_WINDOW; 579} 580 581void 582xcb_wm_hints_set_window_group(xcb_wm_hints_t *hints, xcb_window_t window_group) 583{ 584 hints->window_group = window_group; 585 hints->flags |= XCB_WM_HINT_WINDOW_GROUP; 586} 587 588void 589xcb_wm_hints_set_urgency(xcb_wm_hints_t *hints) 590{ 591 hints->flags |= XCB_WM_HINT_X_URGENCY; 592} 593 594void 595xcb_set_wm_hints_checked(xcb_connection_t *c, xcb_window_t window, 596 xcb_wm_hints_t *hints) 597{ 598 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, WM_HINTS, 599 WM_HINTS, 32, sizeof(*hints) >> 2, hints); 600} 601 602void 603xcb_set_wm_hints(xcb_connection_t *c, xcb_window_t window, 604 xcb_wm_hints_t *hints) 605{ 606 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, WM_HINTS, WM_HINTS, 32, 607 sizeof(*hints) >> 2, hints); 608} 609 610xcb_get_property_cookie_t 611xcb_get_wm_hints(xcb_connection_t *c, 612 xcb_window_t window) 613{ 614 return xcb_get_property(c, 0, window, WM_HINTS, WM_HINTS, 0L, 615 XCB_NUM_WM_HINTS_ELEMENTS); 616} 617 618xcb_get_property_cookie_t 619xcb_get_wm_hints_unchecked(xcb_connection_t *c, 620 xcb_window_t window) 621{ 622 return xcb_get_property_unchecked(c, 0, window, WM_HINTS, WM_HINTS, 0L, 623 XCB_NUM_WM_HINTS_ELEMENTS); 624} 625 626uint8_t 627xcb_get_wm_hints_from_reply(xcb_wm_hints_t *hints, 628 xcb_get_property_reply_t *reply) 629{ 630 if(!reply) 631 return 0; 632 633 int length = xcb_get_property_value_length(reply); 634 int num_elem = length / (reply->format / 8); 635 636 if (reply->type != WM_HINTS 637 || reply->format != 32 638 || num_elem < XCB_NUM_WM_HINTS_ELEMENTS - 1) 639 return 0; 640 641 memcpy(hints, (xcb_size_hints_t *) xcb_get_property_value(reply), length); 642 643 if(num_elem < XCB_NUM_WM_HINTS_ELEMENTS) 644 hints->window_group = XCB_NONE; 645 646 return 1; 647} 648 649uint8_t 650xcb_get_wm_hints_reply(xcb_connection_t *c, 651 xcb_get_property_cookie_t cookie, 652 xcb_wm_hints_t *hints, 653 xcb_generic_error_t **e) 654{ 655 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 656 int ret = xcb_get_wm_hints_from_reply(hints, reply); 657 free(reply); 658 return ret; 659} 660 661/* WM_PROTOCOLS */ 662 663void 664xcb_set_wm_protocols_checked(xcb_connection_t *c, xcb_atom_t wm_protocols, 665 xcb_window_t window, uint32_t list_len, 666 xcb_atom_t *list) 667{ 668 xcb_change_property_checked(c, XCB_PROP_MODE_REPLACE, window, wm_protocols, 669 ATOM, 32, list_len, list); 670} 671 672void 673xcb_set_wm_protocols(xcb_connection_t *c, xcb_atom_t wm_protocols, 674 xcb_window_t window, uint32_t list_len, xcb_atom_t *list) 675{ 676 xcb_change_property(c, XCB_PROP_MODE_REPLACE, window, wm_protocols, ATOM, 32, 677 list_len, list); 678} 679 680xcb_get_property_cookie_t 681xcb_get_wm_protocols(xcb_connection_t *c, xcb_window_t window, 682 xcb_atom_t wm_protocol_atom) 683{ 684 return xcb_get_property(c, 0, window, wm_protocol_atom, ATOM, 0, UINT_MAX); 685} 686 687xcb_get_property_cookie_t 688xcb_get_wm_protocols_unchecked(xcb_connection_t *c, 689 xcb_window_t window, 690 xcb_atom_t wm_protocol_atom) 691{ 692 return xcb_get_property_unchecked(c, 0, window, wm_protocol_atom, ATOM, 0, 693 UINT_MAX); 694} 695 696uint8_t 697xcb_get_wm_protocols_from_reply(xcb_get_property_reply_t *reply, xcb_get_wm_protocols_reply_t *protocols) 698{ 699 if(!reply || reply->type != ATOM || reply->format != 32) 700 return 0; 701 702 protocols->_reply = reply; 703 protocols->atoms_len = xcb_get_property_value_length(protocols->_reply) / (reply->format / 8); 704 protocols->atoms = (xcb_atom_t *) xcb_get_property_value(protocols->_reply); 705 706 return 1; 707} 708 709uint8_t 710xcb_get_wm_protocols_reply(xcb_connection_t *c, 711 xcb_get_property_cookie_t cookie, 712 xcb_get_wm_protocols_reply_t *protocols, 713 xcb_generic_error_t **e) 714{ 715 xcb_get_property_reply_t *reply = xcb_get_property_reply(c, cookie, e); 716 uint8_t ret = xcb_get_wm_protocols_from_reply(reply, protocols); 717 if(!ret) 718 free(reply); 719 return ret; 720} 721 722void 723xcb_get_wm_protocols_reply_wipe(xcb_get_wm_protocols_reply_t *protocols) 724{ 725 free(protocols->_reply); 726} 727