progman.exe^H^H^H^H
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 632 lines 17 kB view raw
1/* 2 * Copyright 2020 joshua stein <jcs@jcs.org> 3 * Copyright 1998-2007 Decklin Foster <decklin@red-bean.com>. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to 7 * deal in the Software without restriction, including without limitation the 8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 * sell copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#ifdef __linux__ 24#define _GNU_SOURCE 25#endif 26 27#include <stdlib.h> 28#include <stdio.h> 29#include <string.h> 30#include <unistd.h> 31#include <signal.h> 32#include <locale.h> 33#include <errno.h> 34#include <err.h> 35#include <fcntl.h> 36#include <sys/wait.h> 37#include <X11/Xatom.h> 38#include <X11/cursorfont.h> 39#include <X11/extensions/shape.h> 40#ifdef USE_GDK_PIXBUF 41#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h> 42#endif 43#include "progman.h" 44#include "atom.h" 45#include "parser.h" 46 47#include "icons/close.xpm" 48#include "icons/utility_close.xpm" 49#include "icons/iconify.xpm" 50#include "icons/zoom.xpm" 51#include "icons/unzoom.xpm" 52#include "icons/default_icon.xpm" 53#include "icons/hidpi-close.xpm" 54#include "icons/hidpi-utility_close.xpm" 55#include "icons/hidpi-iconify.xpm" 56#include "icons/hidpi-zoom.xpm" 57#include "icons/hidpi-unzoom.xpm" 58#include "icons/hidpi-default_icon.xpm" 59 60#ifndef WAIT_ANY 61#define WAIT_ANY (-1) 62#endif 63 64char *orig_argv0; 65Display *dpy; 66Window root; 67client_t *cycle_head; 68client_t *focused, *dragging; 69int screen; 70int ignore_xerrors = 0; 71unsigned long ndesks = DEF_NDESKS; 72unsigned long cur_desk = 0; 73unsigned int focus_order = 0; 74Bool shape_support; 75int shape_event; 76Window supporting_wm_win; 77 78XftFont *font; 79XftFont *iconfont; 80XftColor xft_fg; 81XftColor xft_fg_unfocused; 82XftColor xft_launcher; 83XftColor xft_launcher_highlighted; 84 85Colormap def_cmap; 86XColor fg; 87XColor bg; 88XColor unfocused_fg; 89XColor unfocused_bg; 90XColor button_bg; 91XColor bevel_dark; 92XColor bevel_light; 93XColor border_fg; 94XColor border_bg; 95XColor launcher_fg; 96XColor launcher_bg; 97GC pixmap_gc; 98GC invert_gc; 99Pixmap close_pm; 100Pixmap close_pm_mask; 101XpmAttributes close_pm_attrs; 102Pixmap utility_close_pm; 103Pixmap utility_close_pm_mask; 104XpmAttributes utility_close_pm_attrs; 105Pixmap iconify_pm; 106Pixmap iconify_pm_mask; 107XpmAttributes iconify_pm_attrs; 108Pixmap zoom_pm; 109Pixmap zoom_pm_mask; 110XpmAttributes zoom_pm_attrs; 111Pixmap unzoom_pm; 112Pixmap unzoom_pm_mask; 113XpmAttributes unzoom_pm_attrs; 114Pixmap default_icon_pm; 115Pixmap default_icon_pm_mask; 116XpmAttributes default_icon_pm_attrs; 117Cursor map_curs; 118Cursor move_curs; 119Cursor resize_n_curs; 120Cursor resize_s_curs; 121Cursor resize_e_curs; 122Cursor resize_w_curs; 123Cursor resize_nw_curs; 124Cursor resize_sw_curs; 125Cursor resize_ne_curs; 126Cursor resize_se_curs; 127 128int exitmsg[2]; 129 130char *opt_config_file = NULL; 131char *opt_font = DEF_FONT; 132char *opt_iconfont = DEF_ICONFONT; 133char *opt_fg = DEF_FG; 134char *opt_bg = DEF_BG; 135char *opt_unfocused_fg = DEF_UNFOCUSED_FG; 136char *opt_unfocused_bg = DEF_UNFOCUSED_BG; 137char *opt_button_bg = DEF_BUTTON_BG; 138char *opt_bevel_dark = DEF_BEVEL_DARK; 139char *opt_bevel_light = DEF_BEVEL_LIGHT; 140char *opt_border_fg = DEF_BORDER_FG; 141char *opt_border_bg = DEF_BORDER_BG; 142char *opt_launcher_fg = DEF_LAUNCHER_FG; 143char *opt_launcher_bg = DEF_LAUNCHER_BG; 144char *opt_root_bg = DEF_ROOTBG; 145int opt_bw = DEF_BW; 146int opt_pad = DEF_PAD; 147int opt_bevel = DEF_BEVEL; 148int opt_edge_resist = DEF_EDGE_RES; 149int opt_scale = DEF_SCALE; 150int icon_size = ICON_SIZE_MULT * DEF_SCALE; 151int opt_drag_button = 0; 152int opt_drag_mod = 0; 153 154void read_config(void); 155void setup_display(void); 156void scale_icon(void *xpm, void *hidpi_xpm, Pixmap *pm, Pixmap *pm_mask, 157 XpmAttributes *xpm_attrs); 158 159int 160main(int argc, char **argv) 161{ 162 struct sigaction act; 163 int ch; 164 165 orig_argv0 = strdup(argv[0]); 166 167 setlocale(LC_ALL, ""); 168 169 while ((ch = getopt(argc, argv, "c:")) != -1) { 170 switch (ch) { 171 case 'c': 172 if (opt_config_file) 173 free(opt_config_file); 174 opt_config_file = strdup(optarg); 175 break; 176 default: 177 printf("usage: %s [-c <config file>]\n", argv[0]); 178 exit(1); 179 } 180 } 181 argc -= optind; 182 argv += optind; 183 184 /* parsing the config file may need dpy, so connect early */ 185 dpy = XOpenDisplay(NULL); 186 if (!dpy) 187 err(1, "can't open $DISPLAY \"%s\"", getenv("DISPLAY")); 188 189 XSetErrorHandler(handle_xerror); 190 screen = DefaultScreen(dpy); 191 root = RootWindow(dpy, screen); 192 193 read_config(); 194 195 if (pipe2(exitmsg, O_CLOEXEC) != 0) 196 err(1, "pipe2"); 197 198 act.sa_handler = sig_handler; 199 act.sa_flags = 0; 200 sigaction(SIGTERM, &act, NULL); 201 sigaction(SIGINT, &act, NULL); 202 sigaction(SIGHUP, &act, NULL); 203 sigaction(SIGCHLD, &act, NULL); 204 205 setup_display(); 206 launcher_setup(); 207 event_loop(); 208 cleanup(); 209 210 return 0; 211} 212 213void 214read_config(void) 215{ 216 FILE *ini = NULL; 217 char *key, *val; 218 action_t *act; 219 220 ini = open_ini(opt_config_file); 221 222 if (find_ini_section(ini, "progman")) { 223 while (get_ini_kv(ini, &key, &val)) { 224 if (strcmp(key, "font") == 0) 225 opt_font = strdup(val); 226 else if (strcmp(key, "iconfont") == 0) 227 opt_iconfont = strdup(val); 228 else if (strcmp(key, "fgcolor") == 0) 229 opt_fg = strdup(val); 230 else if (strcmp(key, "bgcolor") == 0) 231 opt_bg = strdup(val); 232 else if (strcmp(key, "unfocused_fgcolor") == 0) 233 opt_unfocused_fg = strdup(val); 234 else if (strcmp(key, "unfocused_bgcolor") == 0) 235 opt_unfocused_bg = strdup(val); 236 else if (strcmp(key, "button_bgcolor") == 0) 237 opt_button_bg = strdup(val); 238 else if (strcmp(key, "border_fgcolor") == 0) 239 opt_border_fg = strdup(val); 240 else if (strcmp(key, "border_bgcolor") == 0) 241 opt_border_bg = strdup(val); 242 else if (strcmp(key, "launcher_fgcolor") == 0) 243 opt_launcher_fg = strdup(val); 244 else if (strcmp(key, "launcher_bgcolor") == 0) 245 opt_launcher_bg = strdup(val); 246 else if (strcmp(key, "root_bgcolor") == 0) 247 opt_root_bg = strdup(val); 248 else if (strcmp(key, "border_width") == 0) { 249 opt_bw = atoi(val); 250 if (opt_bw < 0) { 251 warnx("invalid value for border_width"); 252 opt_bw = DEF_BW; 253 } 254 } else if (strcmp(key, "title_padding") == 0) { 255 opt_pad = atoi(val); 256 if (opt_pad < 0) { 257 warnx("invalid value for " 258 "title_padding"); 259 opt_pad = DEF_PAD; 260 } 261 } else if (strcmp(key, "edgeresist") == 0) { 262 opt_edge_resist = atoi(val); 263 if (opt_edge_resist < 0) { 264 warnx("invalid value for edgeresist"); 265 opt_edge_resist = DEF_EDGE_RES; 266 } 267 } else if (strcmp(key, "scale") == 0) { 268 opt_scale = atoi(val); 269 if (opt_scale < 0) { 270 warnx("invalid value for scale"); 271 opt_scale = DEF_SCALE; 272 } 273 } else if (strcmp(key, "drag_combo") == 0) { 274 act = bind_key(BINDING_TYPE_DRAG, val, "drag"); 275 if (act == NULL) 276 warnx("invalid drag_combo \"%s\" in " 277 "ini", val); 278 else { 279 opt_drag_button = act->button; 280 opt_drag_mod = act->mod; 281 } 282 } else 283 warnx("unknown key \"%s\" and value \"%s\" in " 284 "ini", key, val); 285 286 free(key); 287 free(val); 288 } 289 } 290 291 if (find_ini_section(ini, "keyboard")) 292 while (get_ini_kv(ini, &key, &val)) 293 bind_key(BINDING_TYPE_KEYBOARD, key, val); 294 295 if (find_ini_section(ini, "desktop")) 296 while (get_ini_kv(ini, &key, &val)) 297 bind_key(BINDING_TYPE_DESKTOP, key, val); 298 299 fclose(ini); 300} 301 302void 303setup_display(void) 304{ 305 XGCValues gv; 306 XColor exact; 307 XSetWindowAttributes sattr; 308 XWindowAttributes attr; 309 XIconSize *xis; 310 XColor root_bg; 311 Pixmap rootpx; 312 int shape_err; 313 Window qroot, qparent, *wins; 314 unsigned int nwins, i; 315 client_t *c; 316 317 focused = NULL; 318 dragging = NULL; 319 320#ifdef USE_GDK_PIXBUF 321 gdk_pixbuf_xlib_init(dpy, screen); 322#endif 323 324 map_curs = XCreateFontCursor(dpy, XC_dotbox); 325 move_curs = XCreateFontCursor(dpy, XC_fleur); 326 resize_n_curs = XCreateFontCursor(dpy, XC_top_side); 327 resize_s_curs = XCreateFontCursor(dpy, XC_bottom_side); 328 resize_e_curs = XCreateFontCursor(dpy, XC_right_side); 329 resize_w_curs = XCreateFontCursor(dpy, XC_left_side); 330 resize_nw_curs = XCreateFontCursor(dpy, XC_top_left_corner); 331 resize_sw_curs = XCreateFontCursor(dpy, XC_bottom_left_corner); 332 resize_ne_curs = XCreateFontCursor(dpy, XC_top_right_corner); 333 resize_se_curs = XCreateFontCursor(dpy, XC_bottom_right_corner); 334 335#define alloc_color(val, var, name) \ 336 if (!XAllocNamedColor(dpy, def_cmap, val, var, &exact)) \ 337 warnx("invalid %s value \"%s\"", name, val); 338 339 def_cmap = DefaultColormap(dpy, screen); 340 alloc_color(opt_fg, &fg, "fgcolor"); 341 alloc_color(opt_bg, &bg, "opt_fg"); 342 alloc_color(opt_unfocused_fg, &unfocused_fg, "unfocused_fgcolor"); 343 alloc_color(opt_unfocused_bg, &unfocused_bg, "unfocused_bgcolor"); 344 alloc_color(opt_button_bg, &button_bg, "button_bgcolor"); 345 alloc_color(opt_bevel_dark, &bevel_dark, "bevel_darkcolor"); 346 alloc_color(opt_bevel_light, &bevel_light, "bevel_lightcolor"); 347 alloc_color(opt_border_fg, &border_fg, "border_fgcolor"); 348 alloc_color(opt_border_bg, &border_bg, "border_bgcolor"); 349 alloc_color(opt_launcher_fg, &launcher_fg, "launcher_fgcolor"); 350 alloc_color(opt_launcher_bg, &launcher_bg, "launcher_bgcolor"); 351 352 XSetLineAttributes(dpy, DefaultGC(dpy, screen), 1, LineSolid, CapButt, 353 JoinBevel); 354 XSetFillStyle(dpy, DefaultGC(dpy, screen), FillSolid); 355 356#define create_xft_color(_xft, _pixel) \ 357 (_xft).color.red = (_pixel).red; \ 358 (_xft).color.green = (_pixel).green; \ 359 (_xft).color.blue = (_pixel).blue; \ 360 (_xft).color.alpha = 0xffff; \ 361 (_xft).pixel = (_pixel).pixel; 362 363 create_xft_color(xft_fg, fg); 364 create_xft_color(xft_fg_unfocused, unfocused_fg); 365 create_xft_color(xft_launcher, launcher_fg); 366 create_xft_color(xft_launcher_highlighted, launcher_bg); 367 368 font = XftFontOpenName(dpy, screen, opt_font); 369 if (!font) 370 errx(1, "Xft font \"%s\" not found", opt_font); 371 372 iconfont = XftFontOpenName(dpy, screen, opt_iconfont); 373 if (!iconfont) 374 errx(1, "icon Xft font \"%s\" not found", opt_iconfont); 375 376 pixmap_gc = XCreateGC(dpy, root, 0, &gv); 377 378 gv.function = GXinvert; 379 gv.subwindow_mode = IncludeInferiors; 380 invert_gc = XCreateGC(dpy, root, 381 GCFunction | GCSubwindowMode | GCLineWidth, &gv); 382 383 scale_icon(close_xpm, hidpi_close_xpm, &close_pm, &close_pm_mask, 384 &close_pm_attrs); 385 scale_icon(utility_close_xpm, hidpi_utility_close_xpm, 386 &utility_close_pm, &utility_close_pm_mask, &utility_close_pm_attrs); 387 scale_icon(iconify_xpm, hidpi_iconify_xpm, &iconify_pm, 388 &iconify_pm_mask, &iconify_pm_attrs); 389 scale_icon(zoom_xpm, hidpi_zoom_xpm, &zoom_pm, &zoom_pm_mask, 390 &zoom_pm_attrs); 391 scale_icon(unzoom_xpm, hidpi_unzoom_xpm, &unzoom_pm, &unzoom_pm_mask, 392 &unzoom_pm_attrs); 393 scale_icon(default_icon_xpm, hidpi_default_icon_xpm, &default_icon_pm, 394 &default_icon_pm_mask, &default_icon_pm_attrs); 395 396 icon_size = ICON_SIZE_MULT * opt_scale; 397 xis = XAllocIconSize(); 398 xis->min_width = icon_size; 399 xis->min_height = icon_size; 400 xis->max_width = icon_size; 401 xis->max_height = icon_size; 402 xis->width_inc = 1; 403 xis->height_inc = 1; 404 XSetIconSizes(dpy, root, xis, 1); 405 XFree(xis); 406 407 find_supported_atoms(); 408 409 if (opt_root_bg != NULL && strlen(opt_root_bg) && 410 XAllocNamedColor(dpy, def_cmap, opt_root_bg, &root_bg, &exact)) { 411 rootpx = XCreatePixmap(dpy, root, 1, 1, 412 DefaultDepth(dpy, screen)); 413 XSetForeground(dpy, pixmap_gc, root_bg.pixel); 414 XFillRectangle(dpy, rootpx, pixmap_gc, 0, 0, 1, 1); 415 XSetWindowBackgroundPixmap(dpy, root, rootpx); 416 XClearWindow(dpy, root); 417 set_atoms(root, xrootpmap_id, XA_PIXMAP, &rootpx, 1); 418 } else if (opt_root_bg) 419 warnx("invalid root_bgcolor value \"%s\"", opt_root_bg); 420 421 set_atoms(root, net_num_desks, XA_CARDINAL, &ndesks, 1); 422 get_atoms(root, net_cur_desk, XA_CARDINAL, 0, &cur_desk, 1, NULL); 423 if (cur_desk >= ndesks) { 424 cur_desk = ndesks - 1; 425 set_atoms(root, net_cur_desk, XA_CARDINAL, &cur_desk, 1); 426 } 427 428 shape_support = XShapeQueryExtension(dpy, &shape_event, &shape_err); 429 430 XQueryTree(dpy, root, &qroot, &qparent, &wins, &nwins); 431 for (i = 0; i < nwins; i++) { 432 ignore_xerrors++; 433 XGetWindowAttributes(dpy, wins[i], &attr); 434 ignore_xerrors--; 435 if (!attr.override_redirect && attr.map_state == IsViewable) { 436 c = new_client(wins[i]); 437 c->placed = 1; 438 map_client(c); 439 map_if_desk(c); 440 } 441 } 442 XFree(wins); 443 444 /* become "the" window manager with SubstructureRedirectMask on root */ 445 sattr.event_mask = SubMask | ColormapChangeMask | ButtonMask; 446 XChangeWindowAttributes(dpy, root, CWEventMask, &sattr); 447 448 /* create a hidden window for _NET_SUPPORTING_WM_CHECK */ 449 supporting_wm_win = XCreateWindow(dpy, root, 0, 0, 1, 1, 450 0, DefaultDepth(dpy, screen), CopyFromParent, 451 DefaultVisual(dpy, screen), 0, NULL); 452 set_string_atom(supporting_wm_win, net_wm_name, 453 (unsigned char *)"progman", 7); 454 set_atoms(root, net_supporting_wm, XA_WINDOW, &supporting_wm_win, 1); 455} 456 457void 458scale_icon(void *xpm, void *hidpi_xpm, Pixmap *pm, Pixmap *pm_mask, 459 XpmAttributes *xpm_attrs) 460{ 461 GC scale_gc, mask_scale_gc; 462 Pixmap pm_scaled, pm_scaled_mask; 463 int x, y, i, j; 464 465 if (opt_scale == 2) { 466 /* regular-sized icons are too big to 2x, so use hidpi ones */ 467 if (XpmCreatePixmapFromData(dpy, root, hidpi_xpm, pm, pm_mask, 468 xpm_attrs) != XpmSuccess) 469 err(1, "XpmCreatePixmapFromData"); 470 471 return; 472 } 473 474 if (XpmCreatePixmapFromData(dpy, root, xpm, pm, pm_mask, 475 xpm_attrs) != XpmSuccess) 476 err(1, "XpmCreatePixmapFromData"); 477 478 if (opt_scale == 1) 479 return; 480 481 scale_gc = XCreateGC(dpy, *pm, 0, 0); 482 mask_scale_gc = XCreateGC(dpy, *pm_mask, 0, 0); 483 484 pm_scaled = XCreatePixmap(dpy, *pm, 485 xpm_attrs->width * opt_scale, xpm_attrs->height * opt_scale, 486 DefaultDepth(dpy, screen)); 487 pm_scaled_mask = XCreatePixmap(dpy, *pm_mask, 488 xpm_attrs->width * opt_scale, xpm_attrs->height * opt_scale, 489 1); 490 491 for (y = 0; y < xpm_attrs->height; y++) { 492 for (x = 0; x < xpm_attrs->width; x++) { 493 for (i = 0; i < opt_scale; i++) { 494 for (j = 0; j < opt_scale; j++) { 495 XCopyArea(dpy, *pm, pm_scaled, scale_gc, 496 x, y, 1, 1, 497 (x * opt_scale) + i, 498 (y * opt_scale) + j); 499 XCopyArea(dpy, *pm_mask, pm_scaled_mask, 500 mask_scale_gc, 501 x, y, 1, 1, 502 (x * opt_scale) + i, 503 (y * opt_scale) + j); 504 } 505 } 506 } 507 } 508 509 XFreeGC(dpy, scale_gc); 510 XFreeGC(dpy, mask_scale_gc); 511 512 xpm_attrs->width *= opt_scale; 513 xpm_attrs->height *= opt_scale; 514 515 XFreePixmap(dpy, *pm); 516 XFreePixmap(dpy, *pm_mask); 517 *pm = pm_scaled; 518 *pm_mask = pm_scaled_mask; 519} 520 521void 522sig_handler(int signum) 523{ 524 pid_t pid; 525 int status; 526 527 switch (signum) { 528 case SIGINT: 529 case SIGTERM: 530 case SIGHUP: 531 quit(); 532 break; 533 case SIGCHLD: 534 while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0 || 535 (pid < 0 && errno == EINTR)) 536 ; 537 break; 538 } 539} 540 541void 542quit(void) 543{ 544 if (write(exitmsg[1], &exitmsg, 1)) 545 return; 546 547 warn("failed to exit cleanly"); 548 exit(0); 549} 550 551int 552handle_xerror(Display *dpy, XErrorEvent *e) 553{ 554 char msg[255]; 555 556 if (e->error_code == BadAccess && e->resourceid == root) 557 errx(1, "root window unavailable"); 558 559 if (!ignore_xerrors) { 560 XGetErrorText(dpy, e->error_code, msg, sizeof(msg)); 561 warnx("X error (%#lx): %s", e->resourceid, msg); 562 fflush(stdout); 563 fflush(stderr); 564 } 565 566 return 0; 567} 568 569/* 570 * We use XQueryTree here to preserve the window stacking order, since the 571 * order in our linked list is different. 572 */ 573void 574cleanup(void) 575{ 576 unsigned int nwins, i; 577 XSetWindowAttributes sattr; 578 Window qroot, qparent, *wins; 579 client_t *c; 580 581 XQueryTree(dpy, root, &qroot, &qparent, &wins, &nwins); 582 for (i = 0; i < nwins; i++) { 583 c = find_client(wins[i], MATCH_FRAME); 584 if (c) 585 del_client(c, DEL_REMAP); 586 } 587 XFree(wins); 588 589 XftFontClose(dpy, font); 590 XftFontClose(dpy, iconfont); 591 XFreeCursor(dpy, map_curs); 592 XFreeCursor(dpy, move_curs); 593 XFreeCursor(dpy, resize_n_curs); 594 XFreeCursor(dpy, resize_s_curs); 595 XFreeCursor(dpy, resize_e_curs); 596 XFreeCursor(dpy, resize_w_curs); 597 XFreeCursor(dpy, resize_nw_curs); 598 XFreeCursor(dpy, resize_sw_curs); 599 XFreeCursor(dpy, resize_ne_curs); 600 XFreeCursor(dpy, resize_se_curs); 601 XFreeGC(dpy, pixmap_gc); 602 XFreeGC(dpy, invert_gc); 603 XFreePixmap(dpy, close_pm); 604 XFreePixmap(dpy, close_pm_mask); 605 XFreePixmap(dpy, utility_close_pm); 606 XFreePixmap(dpy, utility_close_pm_mask); 607 XFreePixmap(dpy, iconify_pm); 608 XFreePixmap(dpy, iconify_pm_mask); 609 XFreePixmap(dpy, zoom_pm); 610 XFreePixmap(dpy, zoom_pm_mask); 611 XFreePixmap(dpy, unzoom_pm); 612 XFreePixmap(dpy, unzoom_pm_mask); 613 XFreePixmap(dpy, default_icon_pm); 614 XFreePixmap(dpy, default_icon_pm_mask); 615 616 XInstallColormap(dpy, DefaultColormap(dpy, screen)); 617 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 618 619 XDeleteProperty(dpy, root, net_supporting_wm); 620 XDestroyWindow(dpy, supporting_wm_win); 621 622 XDeleteProperty(dpy, root, net_supported); 623 XDeleteProperty(dpy, root, net_client_list); 624 625 launcher_programs_free(); 626 627 /* resign as "the" window manager */ 628 sattr.event_mask = 0; 629 XChangeWindowAttributes(dpy, root, CWEventMask, &sattr); 630 631 XCloseDisplay(dpy); 632}