]> git.lizzy.rs Git - bspwm.git/blobdiff - tree.c
Remove window borders whenever possible
[bspwm.git] / tree.c
diff --git a/tree.c b/tree.c
index 80f9ff52a791a0de8a781c3128d14818e107e1d4..1a32782195ff75e72cd876d097e6da026b592b02 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -6,7 +6,7 @@
 #include <xcb/xcb_event.h>
 #include "settings.h"
 #include "helpers.h"
-#include "utils.h"
+#include "misc.h"
 #include "window.h"
 #include "types.h"
 #include "bspwm.h"
@@ -167,6 +167,34 @@ void rotate_tree(node_t *n, rotate_t rot)
     rotate_tree(n->second_child, rot);
 }
 
+void magnetise_tree(node_t *n, corner_t corner)
+{
+    if (n == NULL || is_leaf(n)) 
+        return;
+
+    PUTS("magnetise tree");
+
+    switch (n->split_type) {
+        case TYPE_HORIZONTAL:
+            if (corner == TOP_LEFT || corner == TOP_RIGHT)
+                change_split_ratio(n, CHANGE_DECREASE);
+            else
+                change_split_ratio(n, CHANGE_INCREASE);
+            break;
+        case TYPE_VERTICAL:
+            if (corner == TOP_LEFT || corner == BOTTOM_LEFT)
+                change_split_ratio(n, CHANGE_DECREASE);
+            else
+                change_split_ratio(n, CHANGE_INCREASE);
+            break;
+        default:
+            break;
+    }
+
+    magnetise_tree(n->first_child, corner);
+    magnetise_tree(n->second_child, corner);
+}
+
 void dump_tree(desktop_t *d, node_t *n, char *rsp, int depth)
 {
     if (n == NULL)
@@ -178,11 +206,9 @@ void dump_tree(desktop_t *d, node_t *n, char *rsp, int depth)
         strcat(rsp, "  ");
 
     if (is_leaf(n))
-        /* sprintf(line, "0x%X [%i %i %u %u]", n->client->window, n->rectangle.x, n->rectangle.y, n->rectangle.width, n->rectangle.height); */ 
-        sprintf(line, "C %X (%s%s) [%i %i %u %u]", n->client->window, (n->client->floating ? "f" : "-"), (n->client->transient ? "t" : "-"), n->client->rectangle.x, n->client->rectangle.y, n->client->rectangle.width, n->client->rectangle.height); 
+        sprintf(line, "%s %X %s%s%s%s%s", n->client->class_name, n->client->window, (n->client->floating ? "f" : "-"), (n->client->transient ? "t" : "-"), (n->client->fullscreen ? "F" : "-"), (n->client->urgent ? "u" : "-"), (n->client->locked ? "l" : "-")); 
     else
-        /* sprintf(line, "%s %.2f [%i %i %u %u]", (n->split_type == TYPE_HORIZONTAL ? "H" : "V"), n->split_ratio, n->rectangle.x, n->rectangle.y, n->rectangle.width, n->rectangle.height); */
-        sprintf(line, "%s %.2f [%i %i %u %u]", (n->split_type == TYPE_HORIZONTAL ? "H" : "V"), n->split_ratio, n->rectangle.x, n->rectangle.y, n->rectangle.width, n->rectangle.height);
+        sprintf(line, "%s %.2f", (n->split_type == TYPE_HORIZONTAL ? "H" : "V"), n->split_ratio);
 
     strcat(rsp, line);
 
@@ -195,6 +221,13 @@ void dump_tree(desktop_t *d, node_t *n, char *rsp, int depth)
     dump_tree(d, n->second_child, rsp, depth + 1);
 }
 
+void refresh_current(void) {
+    if (desk->focus == NULL)
+        ewmh_update_active_window();
+    else
+        focus_node(desk, desk->focus, true);
+}
+
 void list_desktops(char *rsp)
 {
     desktop_t *d = desk_head;
@@ -228,31 +261,34 @@ void apply_layout(desktop_t *d, node_t *n, xcb_rectangle_t rect)
     if (is_leaf(n)) {
         if (n->client->fullscreen)
             return;
+
+        if (n == d->root || (d->layout == LAYOUT_MONOCLE && !is_floating(n->client)))
+            n->client->border_width = 0;
+        else
+            n->client->border_width = border_width;
+
         xcb_rectangle_t r;
         if (is_tiled(n->client)) {
             if (d->layout == LAYOUT_TILED)
                 r = rect;
             else if (d->layout == LAYOUT_MONOCLE)
                 r = root_rect;
-            int bleed = window_gap + 2 * border_width;
-            r.width = (bleed < r.width ? r.width - bleed : MIN_WIDTH);
-            r.height = (bleed < r.height ? r.height - bleed : MIN_HEIGHT);
+            int bleed = window_gap + 2 * n->client->border_width;
+            r.width = (bleed < r.width ? r.width - bleed : 1);
+            r.height = (bleed < r.height ? r.height - bleed : 1);
+            n->client->tiled_rectangle = r;
         } else {
-            r = n->client->rectangle;
+            r = n->client->floating_rectangle;
         }
 
-        r.width = MAX(r.width, MIN_WIDTH);
-        r.height = MAX(r.height, MIN_HEIGHT);
-
         window_move_resize(n->client->window, r.x, r.y, r.width, r.height);
-        window_border_width(n->client->window, border_width);
-        draw_triple_border(n, (n == d->focus ? active_border_color_pxl : normal_border_color_pxl));
+        window_border_width(n->client->window, n->client->border_width);
+        window_draw_border(n, n == d->focus);
 
         if (d->layout == LAYOUT_MONOCLE && n == d->focus)
             window_raise(n->client->window);
 
     } else {
-
         xcb_rectangle_t first_rect;
         xcb_rectangle_t second_rect;
 
@@ -282,7 +318,7 @@ void insert_node(desktop_t *d, node_t *n)
     if (d == NULL || n == NULL)
         return;
 
-    PUTS("insert node\n");
+    PRINTF("insert node %X\n", n->client->window);
 
     node_t *focus = d->focus;
 
@@ -292,12 +328,16 @@ void insert_node(desktop_t *d, node_t *n)
         node_t *dad = make_node();
         node_t *fopar = focus->parent;
         n->parent = dad;
+        n->born_as = split_mode;
         switch (split_mode) {
             case MODE_AUTOMATIC:
                 if (fopar == NULL) {
                     dad->first_child = n;
                     dad->second_child = focus;
-                    dad->split_type = TYPE_VERTICAL;
+                    if (focus->rectangle.width > focus->rectangle.height)
+                        dad->split_type = TYPE_VERTICAL;
+                    else
+                        dad->split_type = TYPE_HORIZONTAL;
                     focus->parent = dad;
                     d->root = dad;
                 } else {
@@ -362,49 +402,56 @@ void insert_node(desktop_t *d, node_t *n)
                 split_mode = MODE_AUTOMATIC;
                 break;
         }
+        if (focus->vacant)
+            update_vacant_state(fopar);
     }
-
-    num_clients++;
-    ewmh_update_client_list();
 }
 
 void focus_node(desktop_t *d, node_t *n, bool is_mapped)
 {
-    if (d == NULL || n == NULL || desk->focus == n)
-        return;
-
-    if (desk->focus != NULL && desk->focus->client->fullscreen)
+    if (n == NULL)
         return;
 
-    PRINTF("focus_node %x\n", n->client->window);
+    PRINTF("focus node %X\n", n->client->window);
 
     split_mode = MODE_AUTOMATIC;
-
-    select_desktop(d);
+    n->client->urgent = false;
 
     if (is_mapped) {
         if (d->focus != n) {
-            draw_triple_border(d->focus, normal_border_color_pxl);
-            draw_triple_border(n, active_border_color_pxl);
+            window_draw_border(d->focus, false);
+            window_draw_border(n, true);
         }
         xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME);
     }
 
     if (!is_tiled(n->client) || d->layout == LAYOUT_MONOCLE)
         window_raise(n->client->window);
+    else if (is_tiled(n->client))
+        window_lower(n->client->window);
 
-    d->last_focus = d->focus;
-    d->focus = n;
+    if (d->focus != n) {
+        d->last_focus = d->focus;
+        d->focus = n;
+    }
 
     ewmh_update_active_window();
 }
 
+void update_current(void)
+{
+    if (desk->focus == NULL)
+        ewmh_update_active_window();
+    else
+        focus_node(desk, desk->focus, true);
+}
+
 void unlink_node(desktop_t *d, node_t *n)
 {
     if (d == NULL || n == NULL)
         return;
 
-    PUTS("unlink node\n");
+    PRINTF("unlink node %X\n", n->client->window);
 
     node_t *p = n->parent;
 
@@ -415,10 +462,16 @@ void unlink_node(desktop_t *d, node_t *n)
     } else {
         node_t *b;
         node_t *g = p->parent;
-        if (is_first_child(n))
+        bool n_first_child = is_first_child(n);
+        if (n_first_child) {
             b = p->second_child;
-        else
+            if (n->born_as == MODE_AUTOMATIC)
+                rotate_tree(b, ROTATE_COUNTER_CLOCKWISE);
+        } else {
             b = p->first_child;
+            if (n->born_as == MODE_AUTOMATIC)
+                rotate_tree(b, ROTATE_CLOCKWISE);
+        }
         b->parent = g;
         if (g != NULL) {
             if (is_first_child(p))
@@ -432,17 +485,18 @@ void unlink_node(desktop_t *d, node_t *n)
         n->parent = NULL;
         free(p);
 
-        PUTS("unlink: parent is free\n");
-
-        if (n == d->focus) {
-            if (d->last_focus != NULL && d->last_focus != n)
+        if (n == d->last_focus) {
+            d->last_focus = NULL;
+        } else if (n == d->focus) {
+            if (d->last_focus != NULL)
                 d->focus = d->last_focus;
             else
-                d->focus = (is_first_child(b) ? second_extrema(b) : first_extrema(b));
+                d->focus = (n_first_child ? first_extrema(b) : second_extrema(b));
             d->last_focus = NULL;
         }
-    }
 
+        update_vacant_state(b->parent);
+    }
 }
 
 void remove_node(desktop_t *d, node_t *n)
@@ -450,7 +504,7 @@ void remove_node(desktop_t *d, node_t *n)
     if (d == NULL || n == NULL)
         return;
 
-    PUTS("remove node\n");
+    PRINTF("remove node %X\n", n->client->window);
 
     unlink_node(d, n);
     free(n->client);
@@ -459,8 +513,8 @@ void remove_node(desktop_t *d, node_t *n)
     num_clients--;
     ewmh_update_client_list();
 
-    if (desk == d && d->focus != NULL)
-        xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, d->focus->client->window, XCB_CURRENT_TIME);
+    if (desk == d)
+        update_current();
 }
 
 void swap_nodes(node_t *n1, node_t *n2)
@@ -468,21 +522,23 @@ void swap_nodes(node_t *n1, node_t *n2)
     if (n1 == NULL || n2 == NULL || n1 == n2)
         return;
 
-    PUTS("swap nodes\n");
+    PUTS("swap nodes");
 
     /* (n1 and n2 are leaves) */
     node_t *pn1 = n1->parent;
     node_t *pn2 = n2->parent;
+    bool n1_first_child = is_first_child(n1);
+    bool n2_first_child = is_first_child(n2);
 
     if (pn1 != NULL) {
-        if (is_first_child(n1))
+        if (n1_first_child)
             pn1->first_child = n2;
         else
             pn1->second_child = n2;
     }
 
     if (pn2 != NULL) {
-        if (is_first_child(n2))
+        if (n2_first_child)
             pn2->first_child = n1;
         else
             pn2->second_child = n1;
@@ -497,10 +553,25 @@ void transfer_node(desktop_t *ds, desktop_t *dd, node_t *n)
     if (n == NULL || ds == NULL || dd == NULL || dd == ds)
         return;
 
-    PUTS("transfer node\n");
+    PRINTF("transfer node %X\n", n->client->window);
 
     unlink_node(ds, n);
+
+    if (ds == desk) {
+        window_hide(n->client->window);
+    }
+
     insert_node(dd, n);
+
+    if (dd == desk) {
+        window_show(n->client->window);
+        focus_node(dd, n, true);
+    } else {
+        focus_node(dd, n, false);
+    }
+
+    if (ds == desk || dd == desk)
+        update_current();
 }
 
 void select_desktop(desktop_t *d)
@@ -508,78 +579,68 @@ void select_desktop(desktop_t *d)
     if (d == NULL || d == desk)
         return;
 
-    PUTS("select desktop\n");
-
-    if (d->focus != NULL)
-        xcb_map_window(dpy, d->focus->client->window);
+    PRINTF("select desktop %s\n", d->name);
 
     node_t *n = first_extrema(d->root);
 
     while (n != NULL) {
-        if (n != d->focus)
-            xcb_map_window(dpy, n->client->window);
+        window_show(n->client->window);
         n = next_leaf(n);
     }
 
     n = first_extrema(desk->root);
+
     while (n != NULL) {
-        if (n != desk->focus)
-            xcb_unmap_window(dpy, n->client->window);
+        window_hide(n->client->window);
         n = next_leaf(n);
     }
 
-    if (desk->focus != NULL)
-        xcb_unmap_window(dpy, desk->focus->client->window);
-
     last_desk = desk;
     desk = d;
 
-    if (d->focus != NULL)
-        xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, d->focus->client->window, XCB_CURRENT_TIME);
-
+    update_current();
     ewmh_update_current_desktop();
 }
 
+void cycle_desktop(cycle_dir_t dir)
+{
+    if (dir == CYCLE_NEXT)
+        select_desktop((desk->next == NULL ? desk_head : desk->next));
+    else if (dir == CYCLE_PREV)
+        select_desktop((desk->prev == NULL ? desk_tail : desk->prev));
+}
+
 void cycle_leaf(desktop_t *d, node_t *n, cycle_dir_t dir, skip_client_t skip)
 {
     if (n == NULL)
         return;
 
-    PUTS("cycle leaf\n");
+    PUTS("cycle leaf");
 
-    node_t *f = (dir == DIR_PREV ? prev_leaf(n) : next_leaf(n));
+    node_t *f = (dir == CYCLE_PREV ? prev_leaf(n) : next_leaf(n));
+    if (f == NULL)
+        f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root));
 
-    while (f != NULL) {
+    while (f != n) {
         bool tiled = is_tiled(f->client);
-        if (skip == SKIP_NONE || (skip == SKIP_TILED && !tiled) || (skip == SKIP_FLOATING && tiled)) {
+        if (skip == SKIP_NONE || (skip == SKIP_TILED && !tiled) || (skip == SKIP_FLOATING && tiled)
+                || (skip == SKIP_CLASS_DIFFER && strcmp(f->client->class_name, n->client->class_name) == 0)
+                || (skip == SKIP_CLASS_EQUAL && strcmp(f->client->class_name, n->client->class_name) != 0)) {
             focus_node(d, f, true);
             return;
         }
-        f = (dir == DIR_PREV ? prev_leaf(f) : next_leaf(f));
+        f = (dir == CYCLE_PREV ? prev_leaf(f) : next_leaf(f));
+        if (f == NULL)
+            f = (dir == CYCLE_PREV ? second_extrema(d->root) : first_extrema(d->root));
     }
 }
 
-void toggle_floating(node_t *n)
-{
-    if (n == NULL || n->client->transient)
-        return;
-
-    PUTS("toggle floating\n");
-
-    client_t *c = n->client;
-    c->floating = !c->floating;
-    n->vacant = !n->vacant;
-    update_vacant_state(n->parent);
-    if (c->floating)
-        window_raise(c->window);
-}
-
 void update_vacant_state(node_t *n)
 {
     if (n == NULL)
         return;
 
-    PUTS("update vacant state\n");
+    PUTS("update vacant state");
 
     /* n is not a leaf */
     node_t *p = n;
@@ -611,13 +672,3 @@ void add_desktop(char *name)
     ewmh_update_number_of_desktops();
     ewmh_update_desktop_names();
 }
-
-void alternate_desktop(void)
-{
-    if (last_desk == NULL)
-        return;
-    desktop_t *tmp = desk;
-    desk = last_desk;
-    last_desk = tmp;
-    select_desktop(desk);
-}