X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Ftree.c;h=bf5d3965f8e6ebe49f447d2dd496e769c10d79dc;hb=93c6de166d161f04e2cb57a957363f6245c9dbd1;hp=8d1585f6ed6a757ac97742b0a7d8c613f9aaa5f5;hpb=412da35b7372918ed17dfc947321de03d4f4f84c;p=bspwm.git diff --git a/src/tree.c b/src/tree.c index 8d1585f..bf5d396 100644 --- a/src/tree.c +++ b/src/tree.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "bspwm.h" #include "desktop.h" #include "ewmh.h" @@ -47,17 +48,22 @@ void arrange(monitor_t *m, desktop_t *d) layout_t l = d->layout; - if (single_monocle && tiled_count(d->root) <= 1) { + if (single_monocle && tiled_count(d->root, true) <= 1) { l = LAYOUT_MONOCLE; } xcb_rectangle_t rect = m->rectangle; - if (!paddingless_monocle || l != LAYOUT_MONOCLE) { - rect.x += m->padding.left + d->padding.left; - rect.y += m->padding.top + d->padding.top; - 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; + rect.x += m->padding.left + d->padding.left; + rect.y += m->padding.top + d->padding.top; + 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) { + 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) { @@ -78,13 +84,6 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectang n->rectangle = rect; - if (pointer_follows_focus && mon->desk->focus == n) { - xcb_rectangle_t r = rect; - r.width -= d->window_gap; - r.height -= d->window_gap; - center_pointer(r); - } - if (n->presel != NULL) { draw_presel_feedback(m, d, n); } @@ -328,14 +327,21 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) presel_dir(m, d, f, (rect.width >= rect.height ? DIR_EAST : DIR_SOUTH)); } } - if (f->presel == NULL && p != NULL && p->vacant) { - f = p; - p = f->parent; - } n->parent = c; - c->birth_rotation = f->birth_rotation; if (f->presel == NULL) { - if (p == NULL) { + bool single_tiled = f->client != NULL && IS_TILED(f->client) && tiled_count(d->root, true) == 1; + if (p == NULL || automatic_scheme != SCHEME_SPIRAL || single_tiled) { + if (p != NULL) { + if (is_first_child(f)) { + p->first_child = c; + } else { + p->second_child = c; + } + } else { + d->root = c; + } + c->parent = p; + f->parent = c; if (initial_polarity == FIRST_CHILD) { c->first_child = n; c->second_child = f; @@ -343,13 +349,19 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) c->first_child = f; c->second_child = n; } - if (m->rectangle.width > m->rectangle.height) { - c->split_type = TYPE_VERTICAL; + if (p == NULL || automatic_scheme == SCHEME_LONGEST_SIDE || single_tiled) { + if (f->rectangle.width > f->rectangle.height) { + c->split_type = TYPE_VERTICAL; + } else { + c->split_type = TYPE_HORIZONTAL; + } } else { - c->split_type = TYPE_HORIZONTAL; + if (p->split_type == TYPE_HORIZONTAL) { + c->split_type = TYPE_VERTICAL; + } else { + c->split_type = TYPE_HORIZONTAL; + } } - f->parent = c; - d->root = c; } else { node_t *g = p->parent; c->parent = g; @@ -375,7 +387,6 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) c->second_child = n; rot = 270; } - n->birth_rotation = rot; if (!n->vacant) { rotate_tree(p, rot); } @@ -391,7 +402,6 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) c->split_ratio = f->presel->split_ratio; c->parent = p; f->parent = c; - f->birth_rotation = 0; switch (f->presel->split_dir) { case DIR_WEST: c->split_type = TYPE_VERTICAL; @@ -418,6 +428,7 @@ node_t *insert_node(monitor_t *m, desktop_t *d, node_t *n, node_t *f) d->root = c; } cancel_presel(m, d, f); + set_marked(m, d, n, false); } } @@ -439,7 +450,10 @@ void insert_receptacle(monitor_t *m, desktop_t *d, node_t *n) bool activate_node(monitor_t *m, desktop_t *d, node_t *n) { if (n == NULL && d->root != NULL) { - n = history_last_node(d, NULL); + n = d->focus; + if (n == NULL) { + n = history_last_node(d, NULL); + } if (n == NULL) { n = first_focusable_leaf(d->root); } @@ -465,7 +479,7 @@ bool activate_node(monitor_t *m, desktop_t *d, node_t *n) } d->focus = n; - history_add(m, d, n); + history_add(m, d, n, false); put_status(SBSC_MASK_REPORT); @@ -478,26 +492,31 @@ bool activate_node(monitor_t *m, desktop_t *d, node_t *n) return true; } -void transfer_sticky_nodes(monitor_t *m, desktop_t *ds, desktop_t *dd, node_t *n) +void transfer_sticky_nodes(monitor_t *ms, desktop_t *ds, monitor_t *md, desktop_t *dd, node_t *n) { if (n == NULL) { return; } else if (n->sticky) { - transfer_node(m, ds, n, m, dd, dd->focus); + sticky_still = false; + transfer_node(ms, ds, n, md, dd, dd->focus, false); + sticky_still = true; } else { /* we need references to the children because n might be freed after * the first recursive call */ node_t *first_child = n->first_child; node_t *second_child = n->second_child; - transfer_sticky_nodes(m, ds, dd, first_child); - transfer_sticky_nodes(m, ds, dd, second_child); + transfer_sticky_nodes(ms, ds, md, dd, first_child); + transfer_sticky_nodes(ms, ds, md, dd, second_child); } } bool focus_node(monitor_t *m, desktop_t *d, node_t *n) { if (m == NULL) { - m = history_last_monitor(NULL); + m = mon; + if (m == NULL) { + m = history_last_monitor(NULL); + } if (m == NULL) { m = mon_head; } @@ -508,7 +527,10 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n) } if (d == NULL) { - d = history_last_desktop(m, NULL); + d = m->desk; + if (d == NULL) { + d = history_last_desktop(m, NULL); + } if (d == NULL) { d = m->desk_head; } @@ -518,8 +540,13 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n) return false; } + bool guess = (n == NULL); + if (n == NULL && d->root != NULL) { - n = history_last_node(d, NULL); + n = d->focus; + if (n == NULL) { + n = history_last_node(d, NULL); + } if (n == NULL) { n = first_focusable_leaf(d->root); } @@ -533,10 +560,13 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n) clear_input_focus(); } - if (m->sticky_count > 0 && d != m->desk) { - sticky_still = false; - transfer_sticky_nodes(m, m->desk, d, m->desk->root); - sticky_still = true; + if (m->sticky_count > 0 && m->desk != NULL && d != m->desk) { + if (guess && m->desk->focus != NULL && m->desk->focus->sticky) { + n = m->desk->focus; + } + + transfer_sticky_nodes(m, m->desk, m, d, m->desk->root); + if (n == NULL && d->focus != NULL) { n = d->focus; } @@ -578,7 +608,7 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n) d->focus = n; ewmh_update_active_window(); - history_add(m, d, n); + history_add(m, d, n, true); put_status(SBSC_MASK_REPORT); @@ -605,7 +635,7 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n) void hide_node(desktop_t *d, node_t *n) { - if (n == NULL) { + if (n == NULL || (!hide_sticky && n->sticky)) { return; } else { if (!n->hidden) { @@ -653,10 +683,9 @@ node_t *make_node(uint32_t id) node_t *n = calloc(1, sizeof(node_t)); n->id = id; n->parent = n->first_child = n->second_child = NULL; - n->vacant = n->hidden = n->sticky = n->private = n->locked = false; + n->vacant = n->hidden = n->sticky = n->private = n->locked = n->marked = false; n->split_ratio = split_ratio; n->split_type = TYPE_VERTICAL; - n->birth_rotation = 0; n->constraints = (constraints_t) {MIN_WIDTH, MIN_HEIGHT}; n->presel = NULL; n->client = NULL; @@ -952,11 +981,41 @@ node_t *find_by_id_in(node_t *r, uint32_t id) } } +void find_any_node(coordinates_t *ref, coordinates_t *dst, node_select_t *sel) +{ + for (monitor_t *m = mon_head; m != NULL; m = m->next) { + for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { + if (find_any_node_in(m, d, d->root, ref, dst, sel)) { + return; + } + } + } +} + +bool find_any_node_in(monitor_t *m, desktop_t *d, node_t *n, coordinates_t *ref, coordinates_t *dst, node_select_t *sel) +{ + if (n == NULL) { + return false; + } else { + coordinates_t loc = {m, d, n}; + if (node_matches(&loc, ref, sel)) { + *dst = loc; + return true; + } else { + if (find_any_node_in(m, d, n->first_child, ref, dst, sel)) { + return true; + } else { + return find_any_node_in(m, d, n->second_child, ref, dst, sel); + } + } + } +} + /* Based on https://github.com/ntrrgc/right-window */ -void find_nearest_neighbor(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t sel) +void find_nearest_neighbor(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t *sel) { xcb_rectangle_t rect = get_rectangle(ref->monitor, ref->desktop, ref->node); - double md = UINT32_MAX, mr = UINT32_MAX; + uint32_t md = UINT32_MAX, mr = UINT32_MAX; for (monitor_t *m = mon_head; m != NULL; m = m->next) { desktop_t *d = m->desk; @@ -990,23 +1049,29 @@ unsigned int node_area(desktop_t *d, node_t *n) return area(get_rectangle(NULL, d, n)); } -int tiled_count(node_t *n) +int tiled_count(node_t *n, bool include_receptacles) { if (n == NULL) { return 0; } int cnt = 0; for (node_t *f = first_extrema(n); f != NULL; f = next_leaf(f, n)) { - if (!f->hidden && f->client != NULL && IS_TILED(f->client)) { + if (!f->hidden && ((include_receptacles && f->client == NULL) || + (f->client != NULL && IS_TILED(f->client)))) { cnt++; } } return cnt; } -void find_biggest(coordinates_t *ref, coordinates_t *dst, node_select_t sel) +void find_by_area(area_peak_t ap, coordinates_t *ref, coordinates_t *dst, node_select_t *sel) { - unsigned int b_area = 0; + unsigned int p_area; + if (ap == AREA_BIGGEST) { + p_area = 0; + } else { + p_area = UINT_MAX; + } for (monitor_t *m = mon_head; m != NULL; m = m->next) { for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { @@ -1016,9 +1081,9 @@ void find_biggest(coordinates_t *ref, coordinates_t *dst, node_select_t sel) continue; } unsigned int f_area = node_area(d, f); - if (f_area > b_area) { + if ((ap == AREA_BIGGEST && f_area > p_area) || (ap == AREA_SMALLEST && f_area < p_area)) { *dst = loc; - b_area = f_area; + p_area = f_area; } } } @@ -1060,24 +1125,6 @@ void rotate_tree_rec(node_t *n, int deg) rotate_tree_rec(n->second_child, deg); } -void rotate_brother(node_t *n) -{ - rotate_tree(brother_tree(n), n->birth_rotation); -} - -void unrotate_tree(node_t *n, int rot) -{ - if (rot == 0) { - return; - } - rotate_tree(n, 360 - rot); -} - -void unrotate_brother(node_t *n) -{ - unrotate_tree(brother_tree(n), n->birth_rotation); -} - void flip_tree(node_t *n, flip_t flp) { if (n == NULL || is_leaf(n)) { @@ -1151,10 +1198,6 @@ void unlink_node(monitor_t *m, desktop_t *d, node_t *n) node_t *b = brother_tree(n); node_t *g = p->parent; - if (!n->vacant) { - unrotate_tree(b, n->birth_rotation); - } - b->parent = g; if (g != NULL) { @@ -1167,7 +1210,23 @@ void unlink_node(monitor_t *m, desktop_t *d, node_t *n) d->root = b; } - b->birth_rotation = p->birth_rotation; + if (!n->vacant && removal_adjustment) { + if (automatic_scheme == SCHEME_LONGEST_SIDE || g == NULL) { + if (p != NULL) { + if (p->rectangle.width > p->rectangle.height) { + b->split_type = TYPE_VERTICAL; + } else { + b->split_type = TYPE_HORIZONTAL; + } + } + } else if (automatic_scheme == SCHEME_ALTERNATE) { + if (g->split_type == TYPE_HORIZONTAL) { + b->split_type = TYPE_VERTICAL; + } else { + b->split_type = TYPE_HORIZONTAL; + } + } + } free(p); n->parent = NULL; @@ -1251,7 +1310,7 @@ void free_node(node_t *n) free_node(second_child); } -bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop_t *d2, node_t *n2) +bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop_t *d2, node_t *n2, bool follow) { if (n1 == NULL || n2 == NULL || n1 == n2 || is_descendant(n1, n2) || is_descendant(n2, n1) || (d1 != d2 && ((m1->sticky_count > 0 && sticky_count(n1) > 0) || @@ -1265,8 +1324,6 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop node_t *pn2 = n2->parent; bool n1_first_child = is_first_child(n1); bool n2_first_child = is_first_child(n2); - int br1 = n1->birth_rotation; - int br2 = n2->birth_rotation; bool n1_held_focus = is_descendant(d1->focus, n1); bool n2_held_focus = is_descendant(d2->focus, n2); node_t *last_d1_focus = d1->focus; @@ -1290,8 +1347,6 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop n1->parent = pn2; n2->parent = pn1; - n1->birth_rotation = br2; - n2->birth_rotation = br1; propagate_flags_upward(m2, d2, n1); propagate_flags_upward(m1, d1, n2); @@ -1321,22 +1376,31 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop ewmh_set_wm_desktop(n1, d2); ewmh_set_wm_desktop(n2, d1); - history_swap_nodes(m1, d1, n1, m2, d2, n2); + history_remove(d1, n1, true); + history_remove(d2, n2, true); + + bool d1_was_focused = (d1 == mon->desk); + bool d2_was_focused = (d2 == mon->desk); if (m1->desk != d1 && m2->desk == d2) { show_node(d2, n1); - hide_node(d2, n2); + if (!follow || !d2_was_focused || !n2_held_focus) { + hide_node(d2, n2); + } } else if (m1->desk == d1 && m2->desk != d2) { - hide_node(d1, n1); + if (!follow || !d1_was_focused || !n1_held_focus) { + hide_node(d1, n1); + } show_node(d1, n2); } - bool d1_was_focused = (d1 == mon->desk); - bool d2_was_focused = (d2 == mon->desk); - if (n1_held_focus) { if (d1_was_focused) { - focus_node(m2, d2, last_d1_focus); + if (follow) { + focus_node(m2, d2, last_d1_focus); + } else { + focus_node(m1, d1, d1->focus); + } } else { activate_node(m1, d1, d1->focus); } @@ -1346,7 +1410,11 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop if (n2_held_focus) { if (d2_was_focused) { - focus_node(m1, d1, last_d2_focus); + if (follow) { + focus_node(m1, d1, last_d2_focus); + } else { + focus_node(m2, d2, d2->focus); + } } else { activate_node(m2, d2, d2->focus); } @@ -1367,13 +1435,13 @@ bool swap_nodes(monitor_t *m1, desktop_t *d1, node_t *n1, monitor_t *m2, desktop return true; } -bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desktop_t *dd, node_t *nd) +bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desktop_t *dd, node_t *nd, bool follow) { if (ns == NULL || ns == nd || is_child(ns, nd) || is_descendant(nd, ns)) { return false; } - if (sticky_still && ds != dd && ms->sticky_count > 0 && sticky_count(ns) > 0) { + if (sticky_still && ms->sticky_count > 0 && sticky_count(ns) > 0 && dd != md->desk) { return false; } @@ -1382,16 +1450,19 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk bool held_focus = is_descendant(ds->focus, ns); /* avoid ending up with a dangling pointer (because of unlink_node) */ node_t *last_ds_focus = is_child(ns, ds->focus) ? NULL : ds->focus; + bool ds_was_focused = (ds == mon->desk); - if (held_focus && ds == mon->desk) { + if (held_focus && ds_was_focused) { clear_input_focus(); } unlink_node(ms, ds, ns); insert_node(md, dd, ns, nd); - if (md != ms && (ns->client == NULL || monitor_from_client(ns->client) != md)) { - adapt_geometry(&ms->rectangle, &md->rectangle, ns); + if (md != ms) { + if (ns->client == NULL || monitor_from_client(ns->client) != md) { + adapt_geometry(&ms->rectangle, &md->rectangle, ns); + } } if (ds != dd) { @@ -1405,12 +1476,12 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk } } - history_transfer_node(md, dd, ns); + history_remove(ds, ns, true); stack(dd, ns, false); if (ds == dd) { if (held_focus) { - if (ds == mon->desk) { + if (ds_was_focused) { focus_node(ms, ds, last_ds_focus); } else { activate_node(ms, ds, last_ds_focus); @@ -1420,19 +1491,29 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk } } else { if (held_focus) { - if (ds == mon->desk) { - focus_node(md, dd, last_ds_focus); + if (follow) { + if (ds_was_focused) { + focus_node(md, dd, last_ds_focus); + } + activate_node(ms, ds, ds->focus); + } else { + if (ds_was_focused) { + focus_node(ms, ds, ds->focus); + } else { + activate_node(ms, ds, ds->focus); + } } - activate_node(ms, ds, ds->focus); } - if (dd->focus == ns) { - if (dd == mon->desk) { - focus_node(md, dd, held_focus ? last_ds_focus : ns); + if (!held_focus || !follow || !ds_was_focused) { + if (dd->focus == ns) { + if (dd == mon->desk) { + focus_node(md, dd, held_focus ? last_ds_focus : ns); + } else { + activate_node(md, dd, held_focus ? last_ds_focus : ns); + } } else { - activate_node(md, dd, held_focus ? last_ds_focus : ns); + draw_border(ns, is_descendant(ns, dd->focus), (md == mon)); } - } else { - draw_border(ns, is_descendant(ns, dd->focus), (md == mon)); } } @@ -1445,7 +1526,7 @@ bool transfer_node(monitor_t *ms, desktop_t *ds, node_t *ns, monitor_t *md, desk return true; } -bool find_closest_node(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, node_select_t sel) +bool find_closest_node(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, node_select_t *sel) { monitor_t *m = ref->monitor; desktop_t *d = ref->desktop; @@ -1484,7 +1565,7 @@ bool find_closest_node(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, void circulate_leaves(monitor_t *m, desktop_t *d, node_t *n, circulate_dir_t dir) { - if (tiled_count(n) < 2) { + if (tiled_count(n, false) < 2) { return; } node_t *p = d->focus->parent; @@ -1495,7 +1576,7 @@ void circulate_leaves(monitor_t *m, desktop_t *d, node_t *n, circulate_dir_t dir e = prev_leaf(e, n); } for (node_t *s = e, *f = prev_tiled_leaf(s, n); f != NULL; s = prev_tiled_leaf(f, n), f = prev_tiled_leaf(s, n)) { - swap_nodes(m, d, f, m, d, s); + swap_nodes(m, d, f, m, d, s, false); } } else { node_t *e = first_extrema(n); @@ -1503,7 +1584,7 @@ void circulate_leaves(monitor_t *m, desktop_t *d, node_t *n, circulate_dir_t dir e = next_leaf(e, n); } for (node_t *f = e, *s = next_tiled_leaf(f, n); s != NULL; f = next_tiled_leaf(s, n), s = next_tiled_leaf(f, n)) { - swap_nodes(m, d, f, m, d, s); + swap_nodes(m, d, f, m, d, s, false); } } if (p != NULL) { @@ -1537,10 +1618,7 @@ void set_vacant_local(monitor_t *m, desktop_t *d, node_t *n, bool value) n->vacant = value; if (value) { - unrotate_brother(n); cancel_presel(m, d, n); - } else { - rotate_brother(n); } } @@ -1838,7 +1916,7 @@ void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value) } if (d != m->desk) { - transfer_node(m, d, n, m, m->desk, m->desk->focus); + transfer_node(m, d, n, m, m->desk, m->desk->focus, false); } n->sticky = value; @@ -1895,6 +1973,21 @@ void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value) } } +void set_marked(monitor_t *m, desktop_t *d, node_t *n, bool value) +{ + if (n == NULL || n->marked == value) { + return; + } + + n->marked = value; + + put_status(SBSC_MASK_NODE_FLAG, "node_flag 0x%08X 0x%08X 0x%08X marked %s\n", m->id, d->id, n->id, ON_OFF_STR(value)); + + if (n == m->desk->focus) { + put_status(SBSC_MASK_REPORT); + } +} + void set_urgent(monitor_t *m, desktop_t *d, node_t *n, bool value) { if (value && mon->desk->focus == n) { @@ -1915,13 +2008,6 @@ void set_urgent(monitor_t *m, desktop_t *d, node_t *n, bool value) put_status(SBSC_MASK_REPORT); } -/* Returns true if a contains b */ -bool contains(xcb_rectangle_t a, xcb_rectangle_t b) -{ - return (a.x <= b.x && (a.x + a.width) >= (b.x + b.width) && - a.y <= b.y && (a.y + a.height) >= (b.y + b.height)); -} - xcb_rectangle_t get_rectangle(monitor_t *m, desktop_t *d, node_t *n) { if (n == NULL) {