diff options
Diffstat (limited to 'manager.c')
| -rw-r--r-- | manager.c | 108 |
1 files changed, 107 insertions, 1 deletions
| @@ -253,6 +253,11 @@ void init_window_manager(void) { | |||
| 253 | XChangeProperty(wm.dpy, wm.root, _NET_CURRENT_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)¤t_desktop, 1); | 253 | XChangeProperty(wm.dpy, wm.root, _NET_CURRENT_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)¤t_desktop, 1); |
| 254 | log_message(stdout, LOG_DEBUG, "Registering %d desktops", NUM_DESKTOPS); | 254 | log_message(stdout, LOG_DEBUG, "Registering %d desktops", NUM_DESKTOPS); |
| 255 | 255 | ||
| 256 | // Initialize layout modes. | ||
| 257 | for (int i = 0; i <= NUM_DESKTOPS; i++) { | ||
| 258 | wm.layout_modes[i] = LAYOUT_FLOATING; | ||
| 259 | } | ||
| 260 | |||
| 256 | // Initialize colormap early as it's needed for Xft. | 261 | // Initialize colormap early as it's needed for Xft. |
| 257 | wm.cmap = DefaultColormap(wm.dpy, wm.screen); | 262 | wm.cmap = DefaultColormap(wm.dpy, wm.screen); |
| 258 | 263 | ||
| @@ -308,6 +313,30 @@ void init_window_manager(void) { | |||
| 308 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_mic_muted_fg); | 313 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_mic_muted_fg); |
| 309 | } | 314 | } |
| 310 | 315 | ||
| 316 | if (!XftColorAllocName(wm.dpy, visual, wm.cmap, layout_tile_bg_color, &wm.xft_layout_tile_bg)) { | ||
| 317 | log_message(stdout, LOG_WARNING, "Failed to allocate color %s, falling back to dark green", layout_tile_bg_color); | ||
| 318 | XRenderColor render_color = {0x0000, 0x6400, 0x0000, 0xFFFF}; | ||
| 319 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_layout_tile_bg); | ||
| 320 | } | ||
| 321 | |||
| 322 | if (!XftColorAllocName(wm.dpy, visual, wm.cmap, layout_float_bg_color, &wm.xft_layout_float_bg)) { | ||
| 323 | log_message(stdout, LOG_WARNING, "Failed to allocate color %s, falling back to gray", layout_float_bg_color); | ||
| 324 | XRenderColor render_color = {0x3333, 0x3333, 0x3333, 0xFFFF}; | ||
| 325 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_layout_float_bg); | ||
| 326 | } | ||
| 327 | |||
| 328 | if (!XftColorAllocName(wm.dpy, visual, wm.cmap, layout_tile_fg_color, &wm.xft_layout_tile_fg)) { | ||
| 329 | log_message(stdout, LOG_WARNING, "Failed to allocate color %s, falling back to white", layout_tile_fg_color); | ||
| 330 | XRenderColor render_color = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; | ||
| 331 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_layout_tile_fg); | ||
| 332 | } | ||
| 333 | |||
| 334 | if (!XftColorAllocName(wm.dpy, visual, wm.cmap, layout_float_fg_color, &wm.xft_layout_float_fg)) { | ||
| 335 | log_message(stdout, LOG_WARNING, "Failed to allocate color %s, falling back to white", layout_float_fg_color); | ||
| 336 | XRenderColor render_color = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; | ||
| 337 | XftColorAllocValue(wm.dpy, visual, wm.cmap, &render_color, &wm.xft_layout_float_fg); | ||
| 338 | } | ||
| 339 | |||
| 311 | wm.running = 1; | 340 | wm.running = 1; |
| 312 | 341 | ||
| 313 | scan_windows(); | 342 | scan_windows(); |
| @@ -641,7 +670,8 @@ void handle_map_request(void) { | |||
| 641 | grab_buttons(window); | 670 | grab_buttons(window); |
| 642 | 671 | ||
| 643 | add_client(window); | 672 | add_client(window); |
| 644 | 673 | apply_tiling_layout(); | |
| 674 | |||
| 645 | XSync(wm.dpy, False); | 675 | XSync(wm.dpy, False); |
| 646 | XSetErrorHandler(old); | 676 | XSetErrorHandler(old); |
| 647 | 677 | ||
| @@ -663,6 +693,7 @@ void handle_unmap_notify(void) { | |||
| 663 | } | 693 | } |
| 664 | 694 | ||
| 665 | log_message(stdout, LOG_DEBUG, "Window 0x%lx unmapped", window); | 695 | log_message(stdout, LOG_DEBUG, "Window 0x%lx unmapped", window); |
| 696 | apply_tiling_layout(); | ||
| 666 | update_client_list(); | 697 | update_client_list(); |
| 667 | } | 698 | } |
| 668 | 699 | ||
| @@ -673,6 +704,7 @@ void handle_destroy_notify(void) { | |||
| 673 | wm.active = None; | 704 | wm.active = None; |
| 674 | } | 705 | } |
| 675 | remove_client(window); | 706 | remove_client(window); |
| 707 | apply_tiling_layout(); | ||
| 676 | log_message(stdout, LOG_DEBUG, "Window 0x%lx destroyed", window); | 708 | log_message(stdout, LOG_DEBUG, "Window 0x%lx destroyed", window); |
| 677 | update_client_list(); | 709 | update_client_list(); |
| 678 | } | 710 | } |
| @@ -938,6 +970,7 @@ void goto_desktop(const Arg *arg) { | |||
| 938 | 970 | ||
| 939 | set_active_window(new_active, CurrentTime); | 971 | set_active_window(new_active, CurrentTime); |
| 940 | set_active_border(new_active); | 972 | set_active_border(new_active); |
| 973 | apply_tiling_layout(); | ||
| 941 | 974 | ||
| 942 | widget_desktop_indicator(); | 975 | widget_desktop_indicator(); |
| 943 | widget_datetime(); | 976 | widget_datetime(); |
| @@ -956,6 +989,7 @@ void send_window_to_desktop(const Arg *arg) { | |||
| 956 | XUnmapWindow(wm.dpy, wm.active); | 989 | XUnmapWindow(wm.dpy, wm.active); |
| 957 | 990 | ||
| 958 | wm.active = None; | 991 | wm.active = None; |
| 992 | apply_tiling_layout(); | ||
| 959 | widget_desktop_indicator(); | 993 | widget_desktop_indicator(); |
| 960 | widget_datetime(); | 994 | widget_datetime(); |
| 961 | log_message(stdout, LOG_DEBUG, "Moved window to desktop %d", arg->i); | 995 | log_message(stdout, LOG_DEBUG, "Moved window to desktop %d", arg->i); |
| @@ -1612,3 +1646,75 @@ void reload(const Arg *arg) { | |||
| 1612 | wm.restart = 1; | 1646 | wm.restart = 1; |
| 1613 | log_message(stdout, LOG_DEBUG, "Reload window manager"); | 1647 | log_message(stdout, LOG_DEBUG, "Reload window manager"); |
| 1614 | } | 1648 | } |
| 1649 | |||
| 1650 | void apply_tiling_layout(void) { | ||
| 1651 | if (wm.layout_modes[wm.current_desktop] != LAYOUT_TILING) return; | ||
| 1652 | |||
| 1653 | int n = 0; | ||
| 1654 | for (Client *c = wm.clients; c; c = c->next) { | ||
| 1655 | if (window_exists(c->window)) { | ||
| 1656 | unsigned long desktop; | ||
| 1657 | Atom actual_type; | ||
| 1658 | int actual_format; | ||
| 1659 | unsigned long nitems, bytes_after; | ||
| 1660 | unsigned char *prop = NULL; | ||
| 1661 | |||
| 1662 | int status = XGetWindowProperty(wm.dpy, c->window, _NET_WM_DESKTOP, 0, 1, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop); | ||
| 1663 | if (status == Success && prop && nitems > 0) { | ||
| 1664 | desktop = *(unsigned long *)prop; | ||
| 1665 | XFree(prop); | ||
| 1666 | if (desktop == wm.current_desktop && !is_sticky(c->window) && !is_always_on_top(c->window) && !has_wm_state(c->window, _NET_WM_STATE_FULLSCREEN)) { | ||
| 1667 | n++; | ||
| 1668 | } | ||
| 1669 | } else if (prop) { | ||
| 1670 | XFree(prop); | ||
| 1671 | } | ||
| 1672 | } | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | if (n == 0) return; | ||
| 1676 | |||
| 1677 | int screen_width = DisplayWidth(wm.dpy, wm.screen); | ||
| 1678 | int screen_height = DisplayHeight(wm.dpy, wm.screen); | ||
| 1679 | int mw = (n > 1) ? screen_width / 3 : screen_width; | ||
| 1680 | int i = 0; | ||
| 1681 | |||
| 1682 | for (Client *c = wm.clients; c; c = c->next) { | ||
| 1683 | if (window_exists(c->window)) { | ||
| 1684 | unsigned long desktop; | ||
| 1685 | Atom actual_type; | ||
| 1686 | int actual_format; | ||
| 1687 | unsigned long nitems, bytes_after; | ||
| 1688 | unsigned char *prop = NULL; | ||
| 1689 | |||
| 1690 | int status = XGetWindowProperty(wm.dpy, c->window, _NET_WM_DESKTOP, 0, 1, False, XA_CARDINAL, &actual_type, &actual_format, &nitems, &bytes_after, &prop); | ||
| 1691 | if (status == Success && prop && nitems > 0) { | ||
| 1692 | desktop = *(unsigned long *)prop; | ||
| 1693 | XFree(prop); | ||
| 1694 | if (desktop == wm.current_desktop && !is_sticky(c->window) && !is_always_on_top(c->window) && !has_wm_state(c->window, _NET_WM_STATE_FULLSCREEN)) { | ||
| 1695 | if (n == 1) { | ||
| 1696 | XMoveResizeWindow(wm.dpy, c->window, 0, 0, screen_width - 2 * border_size, screen_height - 2 * border_size); | ||
| 1697 | } else if (i == 0) { // Master | ||
| 1698 | XMoveResizeWindow(wm.dpy, c->window, 0, 0, mw - 2 * border_size, screen_height - 2 * border_size); | ||
| 1699 | } else { // Stack | ||
| 1700 | int h = screen_height / (n - 1); | ||
| 1701 | XMoveResizeWindow(wm.dpy, c->window, mw, (i - 1) * h, screen_width - mw - 2 * border_size, h - 2 * border_size); | ||
| 1702 | } | ||
| 1703 | i++; | ||
| 1704 | } | ||
| 1705 | } else if (prop) { | ||
| 1706 | XFree(prop); | ||
| 1707 | } | ||
| 1708 | } | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | void toggle_layout(const Arg *arg) { | ||
| 1713 | (void)arg; | ||
| 1714 | wm.layout_modes[wm.current_desktop] = (wm.layout_modes[wm.current_desktop] == LAYOUT_TILING) ? LAYOUT_FLOATING : LAYOUT_TILING; | ||
| 1715 | if (wm.layout_modes[wm.current_desktop] == LAYOUT_TILING) { | ||
| 1716 | apply_tiling_layout(); | ||
| 1717 | } | ||
| 1718 | redraw_widgets(); | ||
| 1719 | log_message(stdout, LOG_DEBUG, "Toggled layout for desktop %d to %s", wm.current_desktop, wm.layout_modes[wm.current_desktop] == LAYOUT_TILING ? "TILING" : "FLOATING"); | ||
| 1720 | } | ||
