]> git.lizzy.rs Git - bspwm.git/commitdiff
The `birth_rotation` attribute replaces `birth_mode`
authorBastien Dejean <nihilhill@gmail.com>
Wed, 8 May 2013 12:10:53 +0000 (14:10 +0200)
committerBastien Dejean <nihilhill@gmail.com>
Wed, 8 May 2013 12:10:53 +0000 (14:10 +0200)
The `birth_mode` was not sufficient for properly unrotate the brother of
a removed node. The `birth_rotation` stores the rotation applied to the
brother subtree when the node was inserted.

This should help to enforce that (L + n) - n = L in every possible
cases. Which means that adding a node and removing it should leave the
layout unchanged.

README.md
bspwm.1
messages.c
tree.c
tree.h
types.c
types.h
window.c

index 7d3e113ae365a082e19915c25b4c39fe76ce3ff1..a1aa773dc0d6ace13546bdca3c02bfbf1666869d 100644 (file)
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ The following messages are handled:
 
 - `list_monitors [--quiet]` — Perform a dump of each monitor.
 
-- `list_history [DESKTOP_NAME]` — Return the node focus history.
+- `list_history` — Return the node focus history of each desktop.
 
 - `list_windows` — Return the list of managed windows (i.e. their identifiers).
 
diff --git a/bspwm.1 b/bspwm.1
index 4ce17c669505617b405a9bbc5a80efbdefda4a77..b9bb358657d5567e46e0cf03e511863445a23bcf 100644 (file)
--- a/bspwm.1
+++ b/bspwm.1
@@ -106,6 +106,9 @@ Perform a dump of each desktop for the current monitor.
 .BI list_monitors " [--quiet]"
 Perform a dump of each monitor.
 .TP
+.BI list_history
+Return the node focus history of each desktop.
+.TP
 .BI list_windows
 Return the list of managed windows (i.e. their identifiers).
 .TP
index 71164c48888451b7325c3366ebf6a79146d669cc..5252bfd88594468152d09eb8f458076ac9669f8d 100644 (file)
@@ -55,14 +55,7 @@ void process_message(char *msg, char *rsp)
         list_windows(rsp);
         return;
     } else if (strcmp(cmd, "list_history") == 0) {
-        char *name = strtok(NULL, TOK_SEP);
-        if (name != NULL) {
-            desktop_location_t loc;
-            if (locate_desktop(name, &loc))
-                list_history(loc.desktop, rsp);
-        } else {
-            list_history(mon->desk, rsp);
-        }
+        list_history(rsp);
         return;
     } else if (strcmp(cmd, "list_rules") == 0) {
         list_rules(rsp);
diff --git a/tree.c b/tree.c
index 63b09b05ea39e1a8ad048e4c566ded3a5b715a7d..a412f2234eeb86ff560aa9ed56ff4e873e233838 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -252,6 +252,41 @@ void rotate_tree(node_t *n, rotate_t rot)
     rotate_tree(n->second_child, rot);
 }
 
+void rotate_brother(node_t *n)
+{
+    if (n == NULL || n->parent == NULL)
+        return;
+    if (is_first_child(n))
+        rotate_tree(n->parent->second_child, n->birth_rotation);
+    else
+        rotate_tree(n->parent->first_child, n->birth_rotation);
+}
+
+void unrotate_tree(node_t *n, rotate_t rot)
+{
+    switch(rot) {
+        case ROTATE_CLOCKWISE:
+            rotate_tree(n, ROTATE_COUNTER_CLOCKWISE);
+            break;
+        case ROTATE_COUNTER_CLOCKWISE:
+            rotate_tree(n, ROTATE_CLOCKWISE);
+            break;
+        case ROTATE_IDENTITY:
+        case ROTATE_FULL_CYCLE:
+            break;
+    }
+}
+
+void unrotate_brother(node_t *n)
+{
+    if (n == NULL || n->parent == NULL)
+        return;
+    if (is_first_child(n))
+        unrotate_tree(n->parent->second_child, n->birth_rotation);
+    else
+        unrotate_tree(n->parent->first_child, n->birth_rotation);
+}
+
 void flip_tree(node_t *n, flip_t flp)
 {
     if (n == NULL || is_leaf(n))
@@ -271,13 +306,18 @@ void flip_tree(node_t *n, flip_t flp)
     flip_tree(n->second_child, flp);
 }
 
-void list_history(desktop_t *d, char *rsp)
+void list_history(char *rsp)
 {
     char line[MAXLEN];
-    for (node_list_t *a = d->history->head; a != NULL; a = a->next) {
-        snprintf(line, sizeof(line), "%s %X\n", a->node->client->class_name, a->node->client->window);
-        strncat(rsp, line, REMLEN(rsp));
-    }
+    for (monitor_t *m = mon_head; m != NULL; m = m->next)
+        for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+            snprintf(line, sizeof(line), "%s\n", d->name);
+            strncat(rsp, line, REMLEN(rsp));
+            for (node_list_t *a = d->history->tail; a != NULL; a = a->prev) {
+                snprintf(line, sizeof(line), "  %X\n", a->node->client->window);
+                strncat(rsp, line, REMLEN(rsp));
+            }
+        }
 }
 
 int balance_tree(node_t *n)
@@ -383,7 +423,6 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n)
     PRINTF("insert node %X\n", n->client->window);
 
     node_t *focus = d->focus;
-    n->birth_mode = split_mode;
 
     if (focus == NULL) {
         d->root = n;
@@ -391,7 +430,7 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n)
         node_t *dad = make_node();
         node_t *fopar = focus->parent;
         n->parent = dad;
-        dad->birth_mode = focus->birth_mode;
+        dad->birth_rotation = focus->birth_rotation;
         switch (split_mode) {
             case MODE_AUTOMATIC:
                 if (fopar == NULL) {
@@ -417,15 +456,18 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n)
                     dad->split_type = fopar->split_type;
                     dad->split_ratio = fopar->split_ratio;
                     fopar->parent = dad;
+                    rotate_t rot;
                     if (is_first_child(focus)) {
                         dad->first_child = n;
                         dad->second_child = fopar;
-                        rotate_tree(fopar, ROTATE_CLOCKWISE);
+                        rot = ROTATE_CLOCKWISE;
                     } else {
                         dad->first_child = fopar;
                         dad->second_child = n;
-                        rotate_tree(fopar, ROTATE_COUNTER_CLOCKWISE);
+                        rot = ROTATE_COUNTER_CLOCKWISE;
                     }
+                    rotate_tree(fopar, rot);
+                    n->birth_rotation = rot;
                 }
                 break;
             case MODE_MANUAL:
@@ -438,7 +480,7 @@ void insert_node(monitor_t *m, desktop_t *d, node_t *n)
                 dad->split_ratio = focus->split_ratio;
                 dad->parent = fopar;
                 focus->parent = dad;
-                focus->birth_mode = MODE_MANUAL;
+                focus->birth_rotation = ROTATE_IDENTITY;
                 switch (split_dir) {
                     case DIR_LEFT:
                         dad->split_type = TYPE_VERTICAL;
@@ -546,15 +588,14 @@ void unlink_node(desktop_t *d, node_t *n)
     } else {
         node_t *b;
         node_t *g = p->parent;
-        bool n_first_child = is_first_child(n);
-        if (n_first_child) {
+        if (is_first_child(n)) {
             b = p->second_child;
-            if (n->birth_mode == MODE_AUTOMATIC && !n->vacant)
-                rotate_tree(b, ROTATE_COUNTER_CLOCKWISE);
+            if (!n->vacant)
+                unrotate_tree(b, n->birth_rotation);
         } else {
             b = p->first_child;
-            if (n->birth_mode == MODE_AUTOMATIC && !n->vacant)
-                rotate_tree(b, ROTATE_CLOCKWISE);
+            if (!n->vacant)
+                unrotate_tree(b, n->birth_rotation);
         }
         b->parent = g;
         if (g != NULL) {
@@ -566,19 +607,12 @@ void unlink_node(desktop_t *d, node_t *n)
             d->root = b;
         }
 
-        b->birth_mode = p->birth_mode;
+        b->birth_rotation = p->birth_rotation;
         n->parent = NULL;
         free(p);
 
-        if (n == d->focus) {
-            node_t *last_focus = history_get(d->history, 1);
-            if (last_focus != NULL) {
-                d->focus = last_focus;
-            } else {
-                d->focus = (n_first_child ? first_extrema(b) : second_extrema(b));
-                history_add(d->history, d->focus);
-            }
-        }
+        if (n == d->focus)
+            d->focus = history_get(d->history, 1);
 
         update_vacant_state(b->parent);
     }
@@ -629,8 +663,8 @@ void swap_nodes(node_t *n1, node_t *n2)
     node_t *pn2 = n2->parent;
     bool n1_first_child = is_first_child(n1);
     bool n2_first_child = is_first_child(n2);
-    split_mode_t bm1 = n1->birth_mode;
-    split_mode_t bm2 = n2->birth_mode;
+    rotate_t br1 = n1->birth_rotation;
+    rotate_t br2 = n2->birth_rotation;
 
     if (pn1 != NULL) {
         if (n1_first_child)
@@ -648,8 +682,8 @@ void swap_nodes(node_t *n1, node_t *n2)
 
     n1->parent = pn2;
     n2->parent = pn1;
-    n1->birth_mode = bm2;
-    n2->birth_mode = bm1;
+    n1->birth_rotation = br2;
+    n2->birth_rotation = br1;
 
     if (n1->vacant != n2->vacant) {
         update_vacant_state(n1->parent);
@@ -946,9 +980,9 @@ void list(desktop_t *d, node_t *n, char *rsp, unsigned int depth)
 
     if (is_leaf(n)) {
         client_t *c = n->client;
-        snprintf(line, sizeof(line), "%c %s %X %u %u %ux%u%+i%+i %c%c%c%c%c", (n->birth_mode == MODE_AUTOMATIC ? 'a' : 'm'), c->class_name, c->window, c->uid, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (c->floating ? 'f' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'));
+        snprintf(line, sizeof(line), "%c %s %X %u %u %ux%u%+i%+i %c%c%c%c%c", (n->birth_rotation == ROTATE_CLOCKWISE ? 'a' : (n->birth_rotation == ROTATE_COUNTER_CLOCKWISE ? 'c' : 'm')), c->class_name, c->window, c->uid, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (c->floating ? 'f' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'));
     } else {
-        snprintf(line, sizeof(line), "%c %c %.2f", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'), (n->birth_mode == MODE_AUTOMATIC ? 'a' : 'm'), n->split_ratio);
+        snprintf(line, sizeof(line), "%c %c %.2f", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'), (n->birth_rotation == ROTATE_CLOCKWISE ? 'a' : (n->birth_rotation == ROTATE_COUNTER_CLOCKWISE ? 'c' : 'm')), n->split_ratio);
     }
 
     strncat(rsp, line, REMLEN(rsp));
@@ -1043,26 +1077,19 @@ void restore(char *file_path)
             }
             n = birth;
 
+            char br;
             if (isupper(line[level])) {
-                char st, bm;
-                sscanf(line + level, "%c %c %lf", &st, &bm, &n->split_ratio);
+                char st;
+                sscanf(line + level, "%c %c %lf", &st, &br, &n->split_ratio);
                 if (st == 'H')
                     n->split_type = TYPE_HORIZONTAL;
                 else if (st == 'V')
                     n->split_type = TYPE_VERTICAL;
-                if (bm == 'a')
-                    n->birth_mode = MODE_AUTOMATIC;
-                else if (bm == 'm')
-                    n->birth_mode = MODE_MANUAL;
             } else {
                 client_t *c = make_client(XCB_NONE);
                 num_clients++;
-                char bm, floating, transient, fullscreen, urgent, locked;
-                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c%c%c%c%c", &bm, c->class_name, &c->window, &c->uid, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &floating, &transient, &fullscreen, &urgent, &locked);
-                if (bm == 'a')
-                    n->birth_mode = MODE_AUTOMATIC;
-                else if (bm == 'm')
-                    n->birth_mode = MODE_MANUAL;
+                char floating, transient, fullscreen, urgent, locked;
+                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c%c%c%c%c", &br, c->class_name, &c->window, &c->uid, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &floating, &transient, &fullscreen, &urgent, &locked);
                 c->floating = (floating == '-' ? false : true);
                 c->transient = (transient == '-' ? false : true);
                 c->fullscreen = (fullscreen == '-' ? false : true);
@@ -1074,6 +1101,12 @@ void restore(char *file_path)
                 if (len >= 2 && line[len - 2] == '*')
                     d->focus = n;
             }
+            if (br == 'a')
+                n->birth_rotation = ROTATE_CLOCKWISE;
+            else if (br == 'c')
+                n->birth_rotation = ROTATE_COUNTER_CLOCKWISE;
+            else if (br == 'm')
+                n->birth_rotation = ROTATE_IDENTITY;
         }
         last_level = level;
     }
diff --git a/tree.h b/tree.h
index 775be3f89fef4c9ab25431c4c51ce3b703550e63..d5e987e8b3b0b1ec826d1bf36414990f004681e1 100644 (file)
--- a/tree.h
+++ b/tree.h
@@ -22,6 +22,9 @@ int tiled_area(node_t *);
 node_t *find_by_area(desktop_t *, swap_arg_t);
 void move_fence(node_t *, direction_t, fence_move_t);
 void rotate_tree(node_t *, rotate_t);
+void rotate_brother(node_t *);
+void unrotate_tree(node_t *, rotate_t);
+void unrotate_brother(node_t *);
 void flip_tree(node_t *, flip_t);
 int balance_tree(node_t *);
 void arrange(monitor_t *, desktop_t *);
@@ -44,7 +47,7 @@ void nearest_leaf(monitor_t *, desktop_t *, node_t *, nearest_arg_t, skip_client
 void circulate_leaves(monitor_t *, desktop_t *, circulate_dir_t);
 void update_vacant_state(node_t *);
 void put_status(void);
-void list_history(desktop_t *, char *);
+void list_history(char *);
 void list_monitors(list_option_t, char *);
 void list_desktops(monitor_t *, list_option_t, unsigned int, char *);
 void list(desktop_t *, node_t *, char *, unsigned int);
diff --git a/types.c b/types.c
index 0fe0b9274a49b348e110a5260009f68fb93e756d..350d04122713954c8921e908afbc5cc7c9fbba6e 100644 (file)
--- a/types.c
+++ b/types.c
@@ -14,6 +14,7 @@ node_t *make_node(void)
     n->parent = n->first_child = n->second_child = NULL;
     n->split_ratio = split_ratio;
     n->split_type = TYPE_VERTICAL;
+    n->birth_rotation = ROTATE_IDENTITY;
     n->client = NULL;
     n->vacant = false;
     return n;
diff --git a/types.h b/types.h
index 522f913803a610e7cbe8c3e19dc3cd9e29510476..ca620d4854af687207c08c214e70e6f09393b08d 100644 (file)
--- a/types.h
+++ b/types.h
@@ -80,6 +80,7 @@ typedef enum {
 } circulate_dir_t;
 
 typedef enum {
+    ROTATE_IDENTITY,
     ROTATE_CLOCKWISE,
     ROTATE_COUNTER_CLOCKWISE,
     ROTATE_FULL_CYCLE
@@ -137,7 +138,7 @@ typedef struct node_t node_t;
 struct node_t {
     split_type_t split_type;
     double split_ratio;
-    split_mode_t birth_mode;
+    rotate_t birth_rotation;
     xcb_rectangle_t rectangle;
     bool vacant;          /* vacant nodes only hold floating clients */
     node_t *first_child;
index 19688246bc4210227b19e5d8bdb7435130d2c613..c9bba165c56aceff7429086970ee0195b66bac3f 100644 (file)
--- a/window.c
+++ b/window.c
@@ -144,9 +144,6 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     node_t *birth = make_node();
     birth->client = c;
 
-    if (floating)
-        split_mode = MODE_MANUAL;
-
     insert_node(m, d, birth);
 
     disable_shadow(c->window);
@@ -364,19 +361,14 @@ void toggle_floating(node_t *n)
     c->floating = !c->floating;
     n->vacant = !n->vacant;
     update_vacant_state(n->parent);
-    if (c->floating)
+    if (c->floating) {
         window_raise(c->window);
-    else if (is_tiled(c))
-        window_lower(c->window);
-    if (c->floating)
         enable_shadow(c->window);
-    else
+        unrotate_brother(n);
+    } else {
+        window_lower(c->window);
         disable_shadow(c->window);
-    if (n->parent != NULL && n->birth_mode == MODE_AUTOMATIC) {
-        if (is_first_child(n))
-            rotate_tree(n->parent->second_child, c->floating ? ROTATE_COUNTER_CLOCKWISE : ROTATE_CLOCKWISE);
-        else
-            rotate_tree(n->parent->first_child, c->floating ? ROTATE_CLOCKWISE : ROTATE_COUNTER_CLOCKWISE);
+        rotate_brother(n);
     }
     update_current();
 }