├── LICENSE ├── Makefile ├── README.md ├── config.mk ├── libwm.c └── wm.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, 2 | , 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 10 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | 3 | LIB = libwm.a 4 | HDR = wm.h 5 | 6 | .POSIX: 7 | .SUFFIXES: .a .o 8 | 9 | all: $(LIB) 10 | 11 | .o.a: 12 | @echo "AR $@" 13 | @$(AR) rcs $@ $< 14 | 15 | .c.o: 16 | @echo "CC $<" 17 | @$(CC) -c $< $(CFLAGS) 18 | 19 | install: $(LIB) $(HDR) 20 | mkdir -p $(DESTDIR)$(PREFIX)/lib 21 | mkdir -p $(DESTDIR)$(PREFIX)/include 22 | cp -f $(LIB) $(DESTDIR)$(PREFIX)/lib/ 23 | cp -f $(HDR) $(DESTDIR)$(PREFIX)/include/ 24 | 25 | uninstall: 26 | rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB) 27 | rm -f $(DESTDIR)$(PREFIX)/include/$(HDR) 28 | 29 | clean : 30 | rm -f $(LIB) 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | libwm 2 | ===== 3 | A small library for X window manipulation 4 | 5 | Features 6 | ----- 7 | * Depends on [libxcb][0] only 8 | * Wrappers for all window management operations 9 | * Built-in checks for off-screen operations 10 | 11 | Usage 12 | ----- 13 | In order to use the library, you must first include its header file in 14 | your source file: 15 | 16 | #include 17 | 18 | To link your program against it, compile it as follows: 19 | 20 | cc pgm.c -lwm -lxcb -o pgm 21 | 22 | Here is the list of all functions provided by `libwm`: 23 | 24 | wm_init_xcb(); 25 | wm_kill_xcb(); 26 | wm_is_alive(wid); 27 | wm_is_ignored(wid); 28 | wm_is_listable(wid, mask); 29 | wm_is_mapped(wid); 30 | wm_add_atom(name, len); 31 | wm_set_atom(wid, atom, type, len, data); 32 | wm_get_atom(wid, atom, type, &len); 33 | wm_get_atom_name(wid, atom, &len); 34 | wm_get_screen(); 35 | wm_get_windows(wid, &list); 36 | wm_get_focus(); 37 | wm_get_attribute(wid, attr); 38 | wm_get_cursor(mode, wid, &x, &y); 39 | wm_set_border(width, color, wid); 40 | wm_set_focus(wid); 41 | wm_set_cursor(x, y, mode); 42 | wm_set_override(wid, mode); 43 | wm_teleport(wid, w, h, x, y); 44 | wm_move(wid, mode, x, y); 45 | wm_remap(wid, mode); 46 | wm_resize(wid, mode, w, h); 47 | wm_restack(wid, mode); 48 | wm_reg_event(wid, mask); 49 | wm_get_monitors(wid, list); 50 | wm_get_monitor(index); 51 | 52 | Their usage is specified in the `wm.h` header file, as it is quite small for 53 | now. 54 | 55 | Installation 56 | ----- 57 | Edit config.mk as needed, then build/install with the following commands: 58 | 59 | make 60 | make install 61 | 62 | Require [libxcb][0]. 63 | 64 | [0]: https://xcb.freedesktop.org 65 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | PREFIX = /usr/local 2 | 3 | CC = cc 4 | LD = $(CC) 5 | 6 | CFLAGS = -std=c99 -pedantic -Wall -fPIC -Os 7 | LDFLAGS = -lxcb-cursor -lxcb-randr -lxcb 8 | -------------------------------------------------------------------------------- /libwm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "wm.h" 9 | 10 | int 11 | wm_init_xcb() 12 | { 13 | conn = xcb_connect(NULL, NULL); 14 | if (xcb_connection_has_error(conn)) 15 | return -1; 16 | return 0; 17 | } 18 | 19 | int 20 | wm_kill_xcb() 21 | { 22 | if (!conn) 23 | return -1; 24 | xcb_disconnect(conn); 25 | return 0; 26 | } 27 | 28 | int 29 | wm_is_alive(xcb_window_t wid) 30 | { 31 | xcb_get_window_attributes_cookie_t c; 32 | xcb_get_window_attributes_reply_t *r; 33 | 34 | c = xcb_get_window_attributes(conn, wid); 35 | r = xcb_get_window_attributes_reply(conn, c, NULL); 36 | 37 | if (r == NULL) 38 | return 0; 39 | 40 | free(r); 41 | return 1; 42 | } 43 | 44 | int 45 | wm_is_mapped(xcb_window_t wid) 46 | { 47 | int ms; 48 | xcb_get_window_attributes_cookie_t c; 49 | xcb_get_window_attributes_reply_t *r; 50 | 51 | c = xcb_get_window_attributes(conn, wid); 52 | r = xcb_get_window_attributes_reply(conn, c, NULL); 53 | 54 | if (r == NULL) 55 | return 0; 56 | 57 | ms = r->map_state; 58 | 59 | free(r); 60 | return ms == XCB_MAP_STATE_VIEWABLE; 61 | } 62 | 63 | int 64 | wm_is_ignored(xcb_window_t wid) 65 | { 66 | int or; 67 | xcb_get_window_attributes_cookie_t c; 68 | xcb_get_window_attributes_reply_t *r; 69 | 70 | c = xcb_get_window_attributes(conn, wid); 71 | r = xcb_get_window_attributes_reply(conn, c, NULL); 72 | 73 | if (r == NULL) 74 | return 0; 75 | 76 | or = r->override_redirect; 77 | 78 | free(r); 79 | return or; 80 | } 81 | 82 | int 83 | wm_is_listable(xcb_window_t wid, int mask) 84 | { 85 | if (!mask && wm_is_mapped (wid) && !wm_is_ignored(wid)) 86 | return 1; 87 | if ((mask & LIST_ALL)) 88 | return 1; 89 | if (!wm_is_mapped (wid) && mask & LIST_HIDDEN) 90 | return 1; 91 | if (wm_is_ignored(wid) && mask & LIST_IGNORE) 92 | return 1; 93 | 94 | return 0; 95 | } 96 | 97 | int 98 | wm_get_screen() 99 | { 100 | scrn = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; 101 | if (scrn == NULL) 102 | return -1; 103 | return 0; 104 | } 105 | 106 | int 107 | wm_get_windows(xcb_window_t wid, xcb_window_t **l) 108 | { 109 | uint32_t childnum = 0; 110 | xcb_query_tree_cookie_t c; 111 | xcb_query_tree_reply_t *r; 112 | 113 | c = xcb_query_tree(conn, wid); 114 | r = xcb_query_tree_reply(conn, c, NULL); 115 | if (r == NULL) 116 | return -1; 117 | 118 | *l = malloc(sizeof(xcb_window_t) * r->children_len); 119 | memcpy(*l, xcb_query_tree_children(r), 120 | sizeof(xcb_window_t) * r->children_len); 121 | 122 | childnum = r->children_len; 123 | 124 | free(r); 125 | return childnum; 126 | } 127 | 128 | xcb_window_t 129 | wm_get_focus(void) 130 | { 131 | xcb_window_t wid = 0; 132 | xcb_get_input_focus_cookie_t c; 133 | xcb_get_input_focus_reply_t *r; 134 | 135 | c = xcb_get_input_focus(conn); 136 | r = xcb_get_input_focus_reply(conn, c, NULL); 137 | if (r == NULL) 138 | return scrn->root; 139 | 140 | wid = r->focus; 141 | free(r); 142 | return wid; 143 | } 144 | 145 | 146 | int 147 | wm_get_attribute(xcb_window_t wid, int attr) 148 | { 149 | xcb_get_geometry_cookie_t c; 150 | xcb_get_geometry_reply_t *r; 151 | 152 | c = xcb_get_geometry(conn, wid); 153 | r = xcb_get_geometry_reply(conn, c, NULL); 154 | 155 | if (r == NULL) 156 | return -1; 157 | 158 | switch (attr) { 159 | case ATTR_X: 160 | attr = r->x; 161 | break; 162 | case ATTR_Y: 163 | attr = r->y; 164 | break; 165 | case ATTR_W: 166 | attr = r->width; 167 | break; 168 | case ATTR_H: 169 | attr = r->height; 170 | break; 171 | case ATTR_B: 172 | attr = r->border_width; 173 | break; 174 | case ATTR_D: 175 | attr = r->depth; 176 | break; 177 | } 178 | 179 | free(r); 180 | return attr; 181 | } 182 | 183 | xcb_atom_t 184 | wm_add_atom(char *name, size_t len) 185 | { 186 | xcb_atom_t atom; 187 | xcb_intern_atom_cookie_t c; 188 | xcb_intern_atom_reply_t *r; 189 | 190 | c = xcb_intern_atom(conn, 0, len, name); 191 | r = xcb_intern_atom_reply(conn, c, NULL); 192 | if (!r) 193 | return 0; 194 | 195 | atom = r->atom; 196 | free(r); 197 | 198 | return atom; 199 | } 200 | 201 | int 202 | wm_set_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t len, void *data) 203 | { 204 | int errcode; 205 | xcb_void_cookie_t c; 206 | xcb_generic_error_t *e; 207 | 208 | c = xcb_change_property_checked(conn, XCB_PROP_MODE_REPLACE, 209 | wid, atom, type, 32, len, data); 210 | e = xcb_request_check(conn, c); 211 | if (!e) 212 | return 0; 213 | 214 | errcode = e->error_code; 215 | free(e); 216 | 217 | return errcode; 218 | } 219 | 220 | void * 221 | wm_get_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t *len) 222 | { 223 | void *d; 224 | size_t n; 225 | xcb_get_property_cookie_t c; 226 | xcb_get_property_reply_t *r; 227 | 228 | c = xcb_get_property(conn, 0, wid, atom, type, 0, 32); 229 | r = xcb_get_property_reply(conn, c, NULL); 230 | if (!r) 231 | return NULL; 232 | 233 | if (!(n = xcb_get_property_value_length(r))) { 234 | free(r); 235 | return NULL; 236 | } 237 | 238 | if (len) 239 | *len = n; 240 | 241 | d = xcb_get_property_value(r); 242 | 243 | return d; 244 | } 245 | 246 | char * 247 | wm_get_atom_name(xcb_atom_t atom, size_t *len) 248 | { 249 | size_t n; 250 | char *name; 251 | xcb_get_atom_name_cookie_t c; 252 | xcb_get_atom_name_reply_t *r; 253 | 254 | c = xcb_get_atom_name(conn, atom); 255 | r = xcb_get_atom_name_reply(conn, c, NULL); 256 | if (!r) 257 | return NULL; 258 | 259 | n = xcb_get_atom_name_name_length(r) + 1; 260 | name = malloc(xcb_get_atom_name_name_length(r) + 1); 261 | if (!name) { 262 | free(r); 263 | return NULL; 264 | } 265 | 266 | if (len) 267 | *len = n; 268 | 269 | memset(name, 0, xcb_get_atom_name_name_length(r) + 1); 270 | strncpy(name, xcb_get_atom_name_name(r), xcb_get_atom_name_name_length(r)); 271 | free(r); 272 | 273 | return name; 274 | } 275 | 276 | 277 | int 278 | wm_get_cursor(int mode, uint32_t wid, int *x, int *y) 279 | { 280 | xcb_query_pointer_reply_t *r; 281 | xcb_query_pointer_cookie_t c; 282 | 283 | c = xcb_query_pointer(conn, wid); 284 | r = xcb_query_pointer_reply(conn, c, NULL); 285 | 286 | if (r == NULL) 287 | return -1; 288 | 289 | if (r->child != XCB_NONE) { 290 | *x = r->win_x; 291 | *y = r->win_y; 292 | } else { 293 | *x = r->root_x; 294 | *y = r->root_y; 295 | } 296 | 297 | return 0; 298 | } 299 | 300 | int 301 | wm_set_border(int width, int color, xcb_window_t wid) 302 | { 303 | uint32_t values[1]; 304 | int mask; 305 | 306 | /* change width if >= 0 */ 307 | if (width > -1) { 308 | values[0] = width; 309 | mask = XCB_CONFIG_WINDOW_BORDER_WIDTH; 310 | xcb_configure_window(conn, wid, mask, values); 311 | } 312 | 313 | /* 314 | * color is an ARGB representation (eg. 0x80ff0000) for 315 | * translucent red. 316 | * Absolutely all values are valid color representations, so we 317 | * will set it no matter what. 318 | */ 319 | values[0] = color; 320 | mask = XCB_CW_BORDER_PIXEL; 321 | xcb_change_window_attributes(conn, wid, mask, values); 322 | 323 | return 0; 324 | } 325 | 326 | int 327 | wm_set_cursor(int x, int y, int mode) 328 | { 329 | xcb_warp_pointer(conn, XCB_NONE, mode ? XCB_NONE : scrn->root, 330 | 0, 0, 0, 0, x, y); 331 | return 0; 332 | } 333 | 334 | int 335 | wm_teleport(xcb_window_t wid, int x, int y, int w, int h) 336 | { 337 | uint32_t values[4]; 338 | uint32_t mask = XCB_CONFIG_WINDOW_X 339 | | XCB_CONFIG_WINDOW_Y 340 | | XCB_CONFIG_WINDOW_WIDTH 341 | | XCB_CONFIG_WINDOW_HEIGHT; 342 | values[0] = x; 343 | values[1] = y; 344 | values[2] = w; 345 | values[3] = h; 346 | xcb_configure_window(conn, wid, mask, values); 347 | 348 | return 0; 349 | } 350 | 351 | int 352 | wm_move(xcb_window_t wid, int mode, int x, int y) 353 | { 354 | int curx, cury, curw, curh, curb; 355 | 356 | if (!wm_is_mapped(wid) || wid == scrn->root) 357 | return -1; 358 | 359 | curb = wm_get_attribute(wid, ATTR_B); 360 | curx = wm_get_attribute(wid, ATTR_X); 361 | cury = wm_get_attribute(wid, ATTR_Y); 362 | curw = wm_get_attribute(wid, ATTR_W); 363 | curh = wm_get_attribute(wid, ATTR_H); 364 | 365 | if (mode == RELATIVE) { 366 | x += curx; 367 | y += cury; 368 | } 369 | 370 | /* the following prevent windows from moving off the screen */ 371 | if (x < 0) 372 | x = 0; 373 | else if (x > scrn->width_in_pixels - curw - 2*curb) 374 | x = scrn->width_in_pixels - curw - 2*curb; 375 | 376 | if (y < 0) 377 | y = 0; 378 | else if (y > scrn->height_in_pixels - curh - 2*curb) 379 | y = scrn->height_in_pixels - curh - 2*curb; 380 | 381 | wm_teleport(wid, x, y, curw, curh); 382 | return 0; 383 | } 384 | 385 | int 386 | wm_set_override(xcb_window_t wid, int or) 387 | { 388 | uint32_t mask = XCB_CW_OVERRIDE_REDIRECT; 389 | uint32_t val[] = { or }; 390 | 391 | xcb_change_window_attributes(conn, wid, mask, val); 392 | 393 | return 0; 394 | } 395 | 396 | 397 | int 398 | wm_remap(xcb_window_t wid, int mode) 399 | { 400 | switch (mode) { 401 | case MAP: 402 | xcb_map_window(conn, wid); 403 | break; 404 | case UNMAP: 405 | xcb_unmap_window(conn, wid); 406 | break; 407 | case TOGGLE: 408 | if (wm_is_mapped(wid)) 409 | xcb_unmap_window(conn, wid); 410 | else 411 | xcb_map_window(conn, wid); 412 | break; 413 | } 414 | 415 | return 0; 416 | } 417 | 418 | int 419 | wm_resize(xcb_window_t wid, int mode, int w, int h) 420 | { 421 | int curx, cury, curw, curh, curb; 422 | 423 | if (!wm_is_mapped(wid) || wid == scrn->root) 424 | return -1; 425 | 426 | curb = wm_get_attribute(wid, ATTR_B); 427 | curx = wm_get_attribute(wid, ATTR_X); 428 | cury = wm_get_attribute(wid, ATTR_Y); 429 | curw = wm_get_attribute(wid, ATTR_W); 430 | curh = wm_get_attribute(wid, ATTR_H); 431 | 432 | if (mode == RELATIVE) { 433 | w += curw; 434 | h += curh; 435 | } else { 436 | w -= curx; 437 | h -= cury; 438 | } 439 | 440 | /* 441 | * The following prevent windows from growing out of the screen, or 442 | * having a negative size 443 | */ 444 | if (w < 0) 445 | w = curw; 446 | if (curx + w > scrn->width_in_pixels) 447 | w = scrn->width_in_pixels - curx - 2*curb; 448 | 449 | if (h < 0) 450 | h = curh; 451 | if (cury + h > scrn->height_in_pixels) 452 | h = scrn->height_in_pixels - cury - 2*curb; 453 | 454 | wm_teleport(wid, curx, cury, w, h); 455 | return 0; 456 | } 457 | 458 | int 459 | wm_restack(xcb_window_t wid, uint32_t mode) 460 | { 461 | uint32_t values[1] = { mode }; 462 | xcb_configure_window(conn, wid, XCB_CONFIG_WINDOW_STACK_MODE, values); 463 | return 0; 464 | } 465 | 466 | int 467 | wm_set_focus(xcb_window_t wid) 468 | { 469 | xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, wid, 470 | XCB_CURRENT_TIME); 471 | return 0; 472 | } 473 | 474 | int 475 | wm_reg_window_event(xcb_window_t wid, uint32_t mask) 476 | { 477 | uint32_t val[] = { mask }; 478 | xcb_void_cookie_t c; 479 | xcb_generic_error_t *e; 480 | 481 | c = xcb_change_window_attributes_checked(conn, wid, XCB_CW_EVENT_MASK, val); 482 | e = xcb_request_check(conn, c); 483 | if (!e) 484 | return -1; 485 | 486 | free(e); 487 | return 0; 488 | } 489 | 490 | 491 | int 492 | wm_reg_cursor_event(xcb_window_t wid, uint32_t mask, char *cursor) 493 | { 494 | xcb_cursor_t p; 495 | xcb_cursor_context_t *cx; 496 | xcb_grab_pointer_cookie_t c; 497 | xcb_grab_pointer_reply_t *r; 498 | 499 | p = XCB_NONE; 500 | if (cursor) { 501 | if (xcb_cursor_context_new(conn, scrn, &cx) < 0) 502 | return -1; 503 | 504 | p = xcb_cursor_load_cursor(cx, cursor); 505 | } 506 | 507 | c = xcb_grab_pointer(conn, 1, scrn->root, mask, 508 | XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, 509 | XCB_NONE, p, XCB_CURRENT_TIME); 510 | 511 | r = xcb_grab_pointer_reply(conn, c, NULL); 512 | if (!r || r->status != XCB_GRAB_STATUS_SUCCESS) 513 | return -1; 514 | 515 | xcb_cursor_context_free(cx); 516 | return 0; 517 | } 518 | 519 | int 520 | wm_get_monitors(xcb_window_t wid, int *l) 521 | { 522 | int n; 523 | xcb_randr_get_monitors_cookie_t c; 524 | xcb_randr_get_monitors_reply_t *r; 525 | xcb_randr_monitor_info_iterator_t i; 526 | 527 | /* get_active: ignore inactive monitors */ 528 | c = xcb_randr_get_monitors(conn, wid, 0); 529 | r = xcb_randr_get_monitors_reply(conn, c, NULL); 530 | if (!r) 531 | return -1; 532 | 533 | i = xcb_randr_get_monitors_monitors_iterator(r); 534 | if (!i.data) 535 | return 0; 536 | 537 | for (n = 0; l && i.rem > 0; xcb_randr_monitor_info_next(&i)) 538 | l[n++] = i.index; 539 | 540 | n = r->nMonitors; 541 | free(r); 542 | 543 | return n; 544 | } 545 | 546 | xcb_randr_monitor_info_t * 547 | wm_get_monitor(int index) 548 | { 549 | xcb_randr_monitor_info_t *monitor; 550 | xcb_randr_get_monitors_cookie_t c; 551 | xcb_randr_get_monitors_reply_t *r; 552 | xcb_randr_monitor_info_iterator_t i; 553 | 554 | /* get_active: ignore inactive monitors */ 555 | c = xcb_randr_get_monitors(conn, scrn->root, 0); 556 | r = xcb_randr_get_monitors_reply(conn, c, NULL); 557 | if (!r) 558 | return NULL; 559 | 560 | i = xcb_randr_get_monitors_monitors_iterator(r); 561 | if (!i.data) 562 | return NULL; 563 | 564 | for (; i.rem > 0; xcb_randr_monitor_info_next(&i)) { 565 | if (i.index != index) 566 | continue; 567 | 568 | monitor = calloc(1, sizeof(*monitor)); 569 | if (!monitor) 570 | return NULL; 571 | 572 | memcpy(monitor, i.data, sizeof(*monitor)); 573 | free(r); 574 | return monitor; 575 | } 576 | 577 | free(r); 578 | return NULL; 579 | } 580 | 581 | int 582 | wm_find_monitor(int x, int y) 583 | { 584 | /* patch me if you use more than 64 monitors, and get a reward! */ 585 | int n, monitors[64]; 586 | xcb_randr_monitor_info_t *p; 587 | 588 | n = wm_get_monitors(scrn->root, monitors); 589 | 590 | /* 591 | * When you have multiple monitors, like so: 592 | * - 1920x1080+0+0 593 | * - 1920x1080+1920+0 594 | * the pixel located at 1920,500 would match both the first AND 595 | * second monitor. By crawling monitors backward it ensures that 596 | * the "farthest" monitor will match first. 597 | * Also I love that backward loop notation. 598 | */ 599 | while (n --> 0) { 600 | p = wm_get_monitor(monitors[n]); 601 | if (!p) 602 | continue; 603 | 604 | if (x >= p->x && x <= p->x + p->width 605 | && y >= p->y && y <= p->y + p->height) { 606 | free(p); 607 | return monitors[n]; 608 | } 609 | free(p); 610 | } 611 | 612 | return -1; 613 | } 614 | -------------------------------------------------------------------------------- /wm.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBWM_H__ 2 | #define __LIBWM_H__ 3 | 4 | /* 5 | * Variables used to hold the connection to the X server, and the first screen 6 | * of this connection. Both have to be defined as `extern`. 7 | */ 8 | extern xcb_connection_t *conn; 9 | extern xcb_screen_t *scrn; 10 | 11 | /* 12 | * Mask attributes used to select which windows have to be listed by the 13 | * function `wm_is_listable(wid, mask)`. 14 | */ 15 | enum { 16 | LIST_HIDDEN = 1 << 0, /* windows that are not on-screen */ 17 | LIST_IGNORE = 1 << 1, /* windows with override_redirect set to 1 */ 18 | LIST_ALL = 1 << 2 /* All existing windows */ 19 | }; 20 | 21 | /* 22 | * Actions used by the `wm_remap(wid, mode)` function to select what needs to be 23 | * done. 24 | */ 25 | enum { 26 | MAP = 1 << 0, 27 | UNMAP = 1 << 1, 28 | TOGGLE = 1 << 2 29 | }; 30 | 31 | /* 32 | * Attributes used internally by different functions to refer to windows 33 | * attributes, and select them. 34 | */ 35 | enum { 36 | ATTR_W = 1 << 0, 37 | ATTR_H = 1 << 1, 38 | ATTR_X = 1 << 2, 39 | ATTR_Y = 1 << 3, 40 | ATTR_B = 1 << 4, 41 | ATTR_M = 1 << 5, 42 | ATTR_I = 1 << 6, 43 | ATTR_D = 1 << 7, 44 | ATTR_MAX 45 | }; 46 | 47 | /* 48 | * Selector used by both `wm_move(wid, mode, x, y)` and `wm_resize(wid, mode, w, h)` 49 | * to choose between relative or absolute coordinates 50 | */ 51 | enum { 52 | ABSOLUTE = 0, 53 | RELATIVE = 1 54 | }; 55 | 56 | /* 57 | * Initialize the connection to the X server. The connection could then be 58 | * accessed by other functions through the "conn" variable. 59 | */ 60 | int wm_init_xcb(); 61 | 62 | /* 63 | * Close connection to the X server. 64 | */ 65 | int wm_kill_xcb(); 66 | 67 | /* 68 | * Check existence of a window. 69 | * + 1 - window exists 70 | * + 0 - window doesn't exist 71 | */ 72 | int wm_is_alive(xcb_window_t wid); 73 | 74 | /* 75 | * Returns the value of the "override_redirect" attribute of a window. 76 | * When this attribute is set to 1, it means the window manager should NOT 77 | * handle this window. 78 | */ 79 | int wm_is_ignored(xcb_window_t wid); 80 | 81 | /* 82 | * Returns 1 if a window match the mask, 0 otherwise. 83 | * Possible value for the masks are: 84 | * LIST_HIDDEN 85 | * LIST_IGNORE 86 | * LIST_ALL 87 | */ 88 | int wm_is_listable(xcb_window_t wid, int mask); 89 | 90 | /* 91 | * Returns 1 if the window is mapped on screen, 0 otherwise 92 | */ 93 | int wm_is_mapped(xcb_window_t wid); 94 | 95 | /* 96 | * Request the X server to add a new atom, and return this new atom ID 97 | */ 98 | xcb_atom_t wm_add_atom(char *name, size_t len); 99 | 100 | /* 101 | * Change the value of the specified atom 102 | */ 103 | int wm_set_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t len, void *data); 104 | 105 | /* 106 | * Retrieve the value of the given atom. The value length is set in the 107 | * `len` pointer if specified 108 | */ 109 | void *wm_get_atom(xcb_window_t wid, xcb_atom_t atom, xcb_atom_t type, size_t *len); 110 | 111 | /* 112 | * Retrieve the name of the given atom. The name length is set in the 113 | * `len` pointer if specified 114 | */ 115 | char *wm_get_atom_name(xcb_atom_t atom, size_t *len); 116 | 117 | /* 118 | * Get the first screen, and set the `scrn` global variable accordingly. 119 | */ 120 | int wm_get_screen(); 121 | 122 | /* 123 | * Ask the list of all existing windows to the X server, and fills the `*list` 124 | * argument with them. 125 | * The windows are listed in stacking order, from lower to upper window. 126 | * Returns the number of windows in the *list array 127 | */ 128 | int wm_get_windows(xcb_window_t wid, xcb_window_t **list); 129 | 130 | /* 131 | * Returns the window that has keyboard focus 132 | * Will return the root window ID if no window has focus 133 | */ 134 | xcb_window_t wm_get_focus(void); 135 | 136 | /* 137 | * Retrieve the value of an attribute for a specific windows. 138 | * The possible values for the attributes are: 139 | * ATTR_W - width 140 | * ATTR_H - height 141 | * ATTR_X - X offset 142 | * ATTR_Y - Y offset 143 | * ATTR_B - border width 144 | * ATTR_M - map state 145 | * ATTR_I - ignore state (override_redirect) 146 | */ 147 | int wm_get_attribute(xcb_window_t wid, int attr); 148 | 149 | /* 150 | * Get the cursor position, and store its coordinates in the `x` and `y` 151 | * pointers. 152 | * The `mode` attribute isn't used yet, but is reserved to ask for either 153 | * absolute or relative coordinates 154 | */ 155 | int wm_get_cursor(int mode, uint32_t wid, int *x, int *y); 156 | 157 | /* 158 | * Set a window's border. 159 | * The color should be an hexadecimal number, eg: 0xdeadca7 160 | */ 161 | int wm_set_border(int width, int color, xcb_window_t wid); 162 | 163 | /* 164 | * Give the input focus to the specified window 165 | */ 166 | int wm_set_focus(xcb_window_t wid); 167 | 168 | /* 169 | * Change the cursor position, either relatively or absolutely, eg: 170 | * wm_set_cursor(10, 10, ABSOLUTE); 171 | * wm_set_cursor(-10, 20, RELATIVE); 172 | */ 173 | int wm_set_cursor(int x, int y, int mode); 174 | 175 | /* 176 | * Set override_redirect value for given window 177 | */ 178 | int wm_set_override(xcb_window_t wid, int override); 179 | 180 | /* 181 | * Teleport a window to the given position. 182 | */ 183 | int wm_teleport(xcb_window_t wid, int w, int h, int x, int y); 184 | 185 | /* 186 | * Move a window to the given position, either relatively or absolutely. 187 | * If the wm_move is supposed to wm_move the window outside the screen, then the 188 | * windows will only be wm_moved to the edge of the screen. 189 | * 190 | * You cannot wm_move windows outside the screen with this method. Use 191 | * `wm_teleport()` instead. 192 | */ 193 | int wm_move(xcb_window_t wid, int mode, int x, int y); 194 | 195 | /* 196 | * Resize a window to the given size, either relatively or absolutely. 197 | * If the wm_resize is supposed to put an area of the window outside the screen, 198 | * then the windows will only be wm_resized to the edge of the screen. 199 | * 200 | * You cannot wm_resize windows farther than the screen edge with this method. Use 201 | * `wm_teleport()` instead. 202 | */ 203 | int wm_resize(xcb_window_t wid, int mode, int w, int h); 204 | 205 | /* 206 | * Change the mapping state of a window. The `mode` attribute can be as follow: 207 | * MAP 208 | * UNMAP 209 | * TOGGLE 210 | */ 211 | int wm_remap(xcb_window_t wid, int mode); 212 | 213 | /* 214 | * Change the position of the given window in the stack order. 215 | * You can either put it at the top, or at the bottom. 216 | * The possible values for the mode are: 217 | * XCB_STACK_MODE_ABOVE 218 | * XCB_STACK_MODE_BELOW 219 | * XCB_STACK_MODE_OPPOSITE 220 | */ 221 | int wm_restack(xcb_window_t wid, uint32_t mode); 222 | 223 | /* 224 | * Register the given event(s) on the window. 225 | * Multiple events can be registered by ORing them together 226 | */ 227 | int wm_reg_window_event(xcb_window_t wid, uint32_t mask); 228 | 229 | /* 230 | * Register the given cursor event(s) on the window. 231 | * Multiple events can be registered by ORing them together. 232 | * The cursor will be changed to the `cursor` while the pointer is 233 | * grabbed, if not NULL. 234 | */ 235 | int wm_reg_cursor_event(xcb_window_t wid, uint32_t mask, char *cursor); 236 | 237 | /* 238 | * Return the number of active monitors connected to the display where 239 | * window `wid` is sitting. 240 | * The `list` argument, if not NULL, will be filled with the monitor's 241 | * index numbers. Note that `list` must be big enough to hold all indexes, 242 | * as it is not reallocated. 243 | */ 244 | int wm_get_monitors(xcb_window_t wid, int *list); 245 | 246 | /* 247 | * Return the info scructure defining monitor with index number `index`. 248 | */ 249 | xcb_randr_monitor_info_t *wm_get_monitor(int index); 250 | 251 | /* 252 | * Return the index of the (first) monitor associated with the 253 | * coordinates. 254 | */ 255 | int wm_find_monitor(int x, int y); 256 | 257 | #endif /* __LIBWM_H__ */ 258 | --------------------------------------------------------------------------------