]> git.lizzy.rs Git - bspwm.git/commitdiff
Handle `single_monocle` more carefully
authorBastien Dejean <nihilhill@gmail.com>
Thu, 31 Jan 2019 19:29:10 +0000 (20:29 +0100)
committerBastien Dejean <nihilhill@gmail.com>
Fri, 1 Feb 2019 12:45:09 +0000 (13:45 +0100)
Closes #919.
Fixes #730.

src/desktop.c
src/desktop.h
src/helpers.h
src/messages.c
src/query.c
src/restore.c
src/subscribe.c
src/tree.c
src/tree.h
src/types.h
src/window.c

index 098c97a3dafe0d5aef4208c4efcd2735160602d2..c51e3dbc787f9121accaf38fd50ad9995f179a21 100644 (file)
@@ -135,32 +135,41 @@ bool find_any_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t *
        return false;
 }
 
-bool set_layout(monitor_t *m, desktop_t *d, layout_t l)
+bool set_layout(monitor_t *m, desktop_t *d, layout_t l, bool user)
 {
-       layout_t actual_layout = IS_SINGLE_MONOCLE(d) ? LAYOUT_MONOCLE : l;
-       bool actual_layout_changed = (d->layout != actual_layout);
-
-       if (d->layout == l) {
+       if ((user && d->user_layout == l) || (!user && d->layout == l)) {
                return false;
        }
 
-       d->layout = l;
+       layout_t old_layout = d->layout;
 
-       handle_presel_feedbacks(m, d);
+       if (user) {
+               d->user_layout = l;
+       } else {
+               d->layout = l;
+       }
 
-       if (!actual_layout_changed) {
-               return true;
+       if (user && (!single_monocle || tiled_count(d->root, true) > 1)) {
+               d->layout = l;
        }
 
-       arrange(m, d);
+       if (d->layout != old_layout) {
+               handle_presel_feedbacks(m, d);
 
-       put_status(SBSC_MASK_DESKTOP_LAYOUT, "desktop_layout 0x%08X 0x%08X %s\n", m->id, d->id, LAYOUT_STR(actual_layout));
+               if (user) {
+                       arrange(m, d);
+               }
 
-       if (d == m->desk) {
-               put_status(SBSC_MASK_REPORT);
-       }
+               put_status(SBSC_MASK_DESKTOP_LAYOUT, "desktop_layout 0x%08X 0x%08X %s\n", m->id, d->id, LAYOUT_STR(d->layout));
 
-       return true;
+               if (d == m->desk) {
+                       put_status(SBSC_MASK_REPORT);
+               }
+
+               return true;
+       } else {
+               return false;
+       }
 }
 
 void handle_presel_feedbacks(monitor_t *m, desktop_t *d)
@@ -255,7 +264,7 @@ desktop_t *make_desktop(const char *name, uint32_t id)
        }
        d->prev = d->next = NULL;
        d->root = d->focus = NULL;
-       d->layout = LAYOUT_TILED;
+       d->layout = d->user_layout = LAYOUT_TILED;
        d->padding = (padding_t) PADDING;
        d->window_gap = window_gap;
        d->border_width = border_width;
index dd544a494e910a1fd252586f954b9c43f7eb5cd3..132a4824bbe07b6c27536d5aeae834d43d971973 100644 (file)
@@ -31,7 +31,7 @@ void focus_desktop(monitor_t *m, desktop_t *d);
 bool activate_desktop(monitor_t *m, desktop_t *d);
 bool find_closest_desktop(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, desktop_select_t *sel);
 bool find_any_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t *sel);
-bool set_layout(monitor_t *m, desktop_t *d, layout_t l);
+bool set_layout(monitor_t *m, desktop_t *d, layout_t l, bool user);
 void handle_presel_feedbacks(monitor_t *m, desktop_t *d);
 bool transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d, bool follow);
 desktop_t *make_desktop(const char *name, uint32_t id);
index 060a4943266b4ea8453f80341492ca3f0879d73a..e51e5d06e2c36e8b969fc52292a6aa5534485ca7 100644 (file)
 #define IS_FULLSCREEN(c)  (c->state == STATE_FULLSCREEN)
 #define IS_RECEPTACLE(n)  (is_leaf(n) && n->client == NULL)
 
-#define IS_SINGLE_MONOCLE(d) (single_monocle && tiled_count(d->root, true) <= 1)
-#define IS_MONOCLE(d)    (d->layout == LAYOUT_MONOCLE || IS_SINGLE_MONOCLE(d))
-#define ACTUAL_LAYOUT(d)  (IS_MONOCLE(d) ? LAYOUT_MONOCLE : d->layout)
-
 #define BOOL_STR(A)       ((A) ? "true" : "false")
 #define ON_OFF_STR(A)     ((A) ? "on" : "off")
 #define LAYOUT_STR(A)     ((A) == LAYOUT_TILED ? "tiled" : "monocle")
index b08ca045901cade8da1f966924b817afaf6aecd3..62eaa85df1bbd1525da7a558402b7b7c481475ae 100644 (file)
@@ -745,9 +745,9 @@ void cmd_desktop(char **args, int num, FILE *rsp)
                        layout_t lyt;
                        cycle_dir_t cyc;
                        if (parse_cycle_direction(*args, &cyc)) {
-                               ret = set_layout(trg.monitor, trg.desktop, (trg.desktop->layout + 1) % 2);
+                               ret = set_layout(trg.monitor, trg.desktop, (trg.desktop->layout + 1) % 2, true);
                        } else if (parse_layout(*args, &lyt)) {
-                               ret = set_layout(trg.monitor, trg.desktop, lyt);
+                               ret = set_layout(trg.monitor, trg.desktop, lyt, true);
                        } else {
                                fail(rsp, "desktop %s: Invalid argument: '%s'.\n", *(args - 1), *args);
                                break;
@@ -1637,6 +1637,24 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp)
                        fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
                        return;
                }
+       } else if (streq("single_monocle", name)) {
+               bool b;
+               if (parse_bool(value, &b)) {
+                       if (b == single_monocle) {
+                               fail(rsp, "");
+                               return;
+                       }
+                       single_monocle = b;
+                       for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+                               for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+                                       layout_t l = (single_monocle && tiled_count(d->root, true) <= 1) ? LAYOUT_MONOCLE : d->user_layout;
+                                       set_layout(m, d, l, false);
+                               }
+                       }
+               } else {
+                       fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
+                       return;
+               }
        } else if (streq("focus_follows_pointer", name)) {
                bool b;
                if (parse_bool(value, &b)) {
@@ -1674,8 +1692,6 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp)
                SET_BOOL(presel_feedback)
                SET_BOOL(borderless_monocle)
                SET_BOOL(gapless_monocle)
-               SET_BOOL(single_monocle)
-               put_status(SBSC_MASK_REPORT);
                SET_BOOL(swallow_first_click)
                SET_BOOL(pointer_follows_focus)
                SET_BOOL(pointer_follows_monitor)
index 156dbfe86433f54d301697c45061dd6287554ce8..9084e4c44ab94c97ec47d541598a8499f77504e6 100644 (file)
@@ -101,6 +101,7 @@ void query_desktop(desktop_t *d, FILE *rsp)
        fprintf(rsp, "\"name\":\"%s\",", d->name);
        fprintf(rsp, "\"id\":%u,", d->id);
        fprintf(rsp, "\"layout\":\"%s\",", LAYOUT_STR(d->layout));
+       fprintf(rsp, "\"userLayout\":\"%s\",", LAYOUT_STR(d->user_layout));
        fprintf(rsp, "\"windowGap\":%i,", d->window_gap);
        fprintf(rsp, "\"borderWidth\":%u,", d->border_width);
        fprintf(rsp, "\"focusedNodeId\":%u,", d->focus != NULL ? d->focus->id : 0);
index 46d2dda32fbcca7a67fc3e062cd601e864d3a02d..79a9159d82e01d67b75134deedfbdb608b71a923 100644 (file)
@@ -314,6 +314,7 @@ desktop_t *restore_desktop(jsmntok_t **t, char *json)
                        snprintf(d->name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
                RESTORE_UINT(id, &d->id)
                RESTORE_ANY(layout, &d->layout, parse_layout)
+               RESTORE_ANY(userLayout, &d->user_layout, parse_layout)
                RESTORE_INT(windowGap, &d->window_gap)
                RESTORE_UINT(borderWidth, &d->border_width)
                } else if (keyeq("focusedNodeId", *t, json)) {
index 54dd0d2aebb968d4a3b51758d2470eb425af2af7..ebf121acc468fd245a0d4968c9f99737a5732130 100644 (file)
@@ -101,7 +101,7 @@ int print_report(FILE *stream)
                        fprintf(stream, ":%c%s", c, d->name);
                }
                if (m->desk != NULL) {
-                       fprintf(stream, ":L%c", LAYOUT_CHR(ACTUAL_LAYOUT(m->desk)));
+                       fprintf(stream, ":L%c", LAYOUT_CHR(m->desk->layout));
                        if (m->desk->focus != NULL) {
                                node_t *n = m->desk->focus;
                                if (n->client != NULL) {
index fa79a1b985b8fb212661315009d0e3de0ec83244..8bdae318f33962b4fc71977ac8a9e8ea54ad0c48 100644 (file)
@@ -46,8 +46,6 @@ void arrange(monitor_t *m, desktop_t *d)
                return;
        }
 
-       layout_t l = ACTUAL_LAYOUT(d);
-
        xcb_rectangle_t rect = m->rectangle;
 
        rect.x += m->padding.left + d->padding.left;
@@ -55,24 +53,24 @@ void arrange(monitor_t *m, desktop_t *d)
        rect.width -= m->padding.left + d->padding.left + d->padding.right + m->padding.right;
        rect.height -= m->padding.top + d->padding.top + d->padding.bottom + m->padding.bottom;
 
-       if (l == LAYOUT_MONOCLE) {
+       if (d->layout == LAYOUT_MONOCLE) {
                rect.x += monocle_padding.left;
                rect.y += monocle_padding.top;
                rect.width -= monocle_padding.left + monocle_padding.right;
                rect.height -= monocle_padding.top + monocle_padding.bottom;
        }
 
-       if (!gapless_monocle || l != LAYOUT_MONOCLE) {
+       if (!gapless_monocle || d->layout != LAYOUT_MONOCLE) {
                rect.x += d->window_gap;
                rect.y += d->window_gap;
                rect.width -= d->window_gap;
                rect.height -= d->window_gap;
        }
 
-       apply_layout(m, d, d->root, l, rect, rect);
+       apply_layout(m, d, d->root, rect, rect);
 }
 
-void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectangle_t rect, xcb_rectangle_t root_rect)
+void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, xcb_rectangle_t root_rect)
 {
        if (n == NULL) {
                return;
@@ -91,7 +89,7 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectang
                }
 
                unsigned int bw;
-               if ((borderless_monocle && l == LAYOUT_MONOCLE && IS_TILED(n->client))
+               if ((borderless_monocle && d->layout == LAYOUT_MONOCLE && IS_TILED(n->client))
                    || n->client->state == STATE_FULLSCREEN) {
                        bw = 0;
                } else {
@@ -103,7 +101,7 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectang
                client_state_t s = n->client->state;
                /* tiled and pseudo-tiled clients */
                if (s == STATE_TILED || s == STATE_PSEUDO_TILED) {
-                       int wg = (gapless_monocle && l == LAYOUT_MONOCLE ? 0 : d->window_gap);
+                       int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap);
                        r = rect;
                        int bleed = wg + 2 * bw;
                        r.width = (bleed < r.width ? r.width - bleed : 1);
@@ -143,7 +141,7 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectang
                xcb_rectangle_t first_rect;
                xcb_rectangle_t second_rect;
 
-               if (l == LAYOUT_MONOCLE || n->first_child->vacant || n->second_child->vacant) {
+               if (d->layout == LAYOUT_MONOCLE || n->first_child->vacant || n->second_child->vacant) {
                        first_rect = second_rect = rect;
                } else {
                        unsigned int fence;
@@ -176,8 +174,8 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectang
                        }
                }
 
-               apply_layout(m, d, n->first_child, l, first_rect, root_rect);
-               apply_layout(m, d, n->second_child, l, second_rect, root_rect);
+               apply_layout(m, d, n->first_child, first_rect, root_rect);
+               apply_layout(m, d, n->second_child, second_rect, root_rect);
        }
 }
 
@@ -440,7 +438,9 @@ void insert_receptacle(monitor_t *m, desktop_t *d, node_t *n)
        node_t *r = make_node(XCB_NONE);
        insert_node(m, d, r, n);
 
-       put_status(SBSC_MASK_REPORT);
+       if (single_monocle && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+               set_layout(m, d, d->user_layout, false);
+       }
 }
 
 bool activate_node(monitor_t *m, desktop_t *d, node_t *n)
@@ -1321,6 +1321,10 @@ void remove_node(monitor_t *m, desktop_t *d, node_t *n)
        }
        free_node(n);
 
+       if (single_monocle && d->layout != LAYOUT_MONOCLE && tiled_count(d->root, true) <= 1) {
+               set_layout(m, d, LAYOUT_MONOCLE, false);
+       }
+
        ewmh_update_client_list(false);
        ewmh_update_client_list(true);
 
@@ -1430,6 +1434,13 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop
                        show_node(d1, n2);
                }
 
+               if (single_monocle) {
+                       layout_t l1 = tiled_count(d1->root, true) <= 1 ? LAYOUT_MONOCLE : d1->user_layout;
+                       layout_t l2 = tiled_count(d2->root, true) <= 1 ? LAYOUT_MONOCLE : d2->user_layout;
+                       set_layout(m1, d1, l1, false);
+                       set_layout(m2, d2, l2, false);
+               }
+
                if (n1_held_focus) {
                        if (d1_was_focused) {
                                if (follow) {
@@ -1526,6 +1537,14 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk
                        draw_border(ns, is_descendant(ns, ds->focus), (ms == mon));
                }
        } else {
+               if (single_monocle) {
+                       if (ds->layout != LAYOUT_MONOCLE && tiled_count(ds->root, true) <= 1) {
+                               set_layout(ms, ds, LAYOUT_MONOCLE, false);
+                       }
+                       if (dd->layout == LAYOUT_MONOCLE && tiled_count(dd->root, true) > 1) {
+                               set_layout(md, dd, dd->user_layout, false);
+                       }
+               }
                if (held_focus) {
                        if (follow) {
                                if (ds_was_focused) {
@@ -1725,6 +1744,8 @@ bool set_state(monitor_t *m, desktop_t *d, node_t *n, client_state_t s)
 
        client_t *c = n->client;
 
+       bool was_tiled = IS_TILED(c);
+
        c->last_state = c->state;
        c->state = s;
 
@@ -1760,6 +1781,14 @@ bool set_state(monitor_t *m, desktop_t *d, node_t *n, client_state_t s)
                put_status(SBSC_MASK_REPORT);
        }
 
+       if (single_monocle && was_tiled != IS_TILED(c)) {
+               if (was_tiled && d->layout != LAYOUT_MONOCLE && tiled_count(d->root, true) <= 1) {
+                       set_layout(m, d, LAYOUT_MONOCLE, false);
+               } else if (!was_tiled && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+                       set_layout(m, d, d->user_layout, false);
+               }
+       }
+
        return true;
 }
 
@@ -2054,7 +2083,7 @@ xcb_rectangle_t get_rectangle(monitor_t *m, desktop_t *d, node_t *n)
                        return c->tiled_rectangle;
                }
        } else {
-               int wg = (d == NULL ? 0 : (gapless_monocle && IS_MONOCLE(d) ? 0 : d->window_gap));
+               int wg = (d == NULL ? 0 : (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap));
                xcb_rectangle_t rect = n->rectangle;
                rect.width -= wg;
                rect.height -= wg;
index 0334c2e8d92725a89d26d3f4497bf575b32356cc..b571ada9f58e9efd76d43c0baa32eecfbeff95c2 100644 (file)
@@ -29,7 +29,7 @@
 #define MIN_HEIGHT  32
 
 void arrange(monitor_t *m, desktop_t *d);
-void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectangle_t rect, xcb_rectangle_t root_rect);
+void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, xcb_rectangle_t root_rect);
 presel_t *make_presel(void);
 void set_ratio(node_t *n, double rat);
 void presel_dir(monitor_t *m, desktop_t *d, node_t *n, direction_t dir);
index a04fc8406ff3a1891cf4ce5b4f4ebe6f914f10fc..2c15a2649063a80535f89f5ad1f9836deb9f2c85 100644 (file)
@@ -268,6 +268,7 @@ struct desktop_t {
        char name[SMALEN];
        uint32_t id;
        layout_t layout;
+       layout_t user_layout;
        node_t *root;
        node_t *focus;
        desktop_t *prev;
index b311cbf77c4c0fe02126e819855753f52749488a..71e42597315ee38577b25830be769c3a1b66980e 100644 (file)
@@ -30,6 +30,7 @@
 #include "bspwm.h"
 #include "ewmh.h"
 #include "monitor.h"
+#include "desktop.h"
 #include "query.h"
 #include "rule.h"
 #include "settings.h"
@@ -165,6 +166,9 @@ bool manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
 
        f = insert_node(m, d, n, f);
        clients_count++;
+       if (single_monocle && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+               set_layout(m, d, d->user_layout, false);
+       }
 
        n->vacant = false;
 
@@ -293,7 +297,7 @@ void draw_presel_feedback(monitor_t *m, desktop_t *d, node_t *n)
                initialize_presel_feedback(n);
        }
 
-       int gap = gapless_monocle && IS_MONOCLE(d) ? 0 : d->window_gap;
+       int gap = gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap;
        presel_t *p = n->presel;
        xcb_rectangle_t rect = n->rectangle;
        rect.x = rect.y = 0;