]> git.lizzy.rs Git - bspwm.git/commitdiff
Generalize a few node descriptors
authorBastien Dejean <nihilhill@gmail.com>
Tue, 28 Jul 2020 09:14:28 +0000 (11:14 +0200)
committerBastien Dejean <nihilhill@gmail.com>
Tue, 28 Jul 2020 09:14:28 +0000 (11:14 +0200)
- `next` and `prev` might now return any node in the context of a
  depth-first in-order tree traversal.
- `biggest`, `smallest` and `pointed` now return leaves instead of
  windows. In particular, `pointed` can now be used to get the id of a
  pointed receptacle.

Fixes #1113.

doc/bspwm.1
doc/bspwm.1.asciidoc
examples/sxhkdrc
src/query.c
src/query.h
src/tree.c
src/tree.h
src/window.c

index 9c3e99fa29b55f7636317ffab111778bf00b1642..b5171bebcc5797c9bc73ac63f32858ac47707a49 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: bspwm
 .\"    Author: [see the "Author" section]
 .\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\"      Date: 07/27/2020
+.\"      Date: 07/28/2020
 .\"    Manual: Bspwm Manual
-.\"    Source: Bspwm 0.9.9-25-g8f41d79
+.\"    Source: Bspwm 0.9.9-26-ga54ab70
 .\"  Language: English
 .\"
-.TH "BSPWM" "1" "07/27/2020" "Bspwm 0\&.9\&.9\-25\-g8f41d79" "Bspwm Manual"
+.TH "BSPWM" "1" "07/28/2020" "Bspwm 0\&.9\&.9\-26\-ga54ab70" "Bspwm Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -135,7 +135,7 @@ Selects the window in the given (spacial) direction relative to the reference no
 .PP
 \fICYCLE_DIR\fR
 .RS 4
-Selects the window in the given (cyclic) direction relative to the reference node\&.
+Selects the node in the given (cyclic) direction relative to the reference node within a depth\-first in\-order traversal of the tree\&.
 .RE
 .PP
 \fIPATH\fR
@@ -180,17 +180,17 @@ Selects the currently focused node\&.
 .PP
 pointed
 .RS 4
-Selects the window under the pointer\&.
+Selects the leaf under the pointer\&.
 .RE
 .PP
 biggest
 .RS 4
-Selects the biggest window\&.
+Selects the biggest leaf\&.
 .RE
 .PP
 smallest
 .RS 4
-Selects the smallest window\&.
+Selects the smallest leaf\&.
 .RE
 .PP
 <node_id>
index 0923f94a4798971a1ed0ef530812bf7701806487..9d2a42b12c9fb8b30fc054f151a46272a0b46f78 100644 (file)
@@ -98,7 +98,7 @@ Descriptors
        Selects the window in the given (spacial) direction relative to the reference node.
 
 'CYCLE_DIR'::
-       Selects the window in the given (cyclic) direction relative to the reference node.
+       Selects the node in the given (cyclic) direction relative to the reference node within a depth-first in-order traversal of the tree.
 
 'PATH'::
        Selects the node at the given path.
@@ -125,13 +125,13 @@ focused::
        Selects the currently focused node.
 
 pointed::
-       Selects the window under the pointer.
+       Selects the leaf under the pointer.
 
 biggest::
-       Selects the biggest window.
+       Selects the biggest leaf.
 
 smallest::
-       Selects the smallest window.
+       Selects the smallest leaf.
 
 <node_id>::
        Selects the node with the given ID.
index 0e5ea5a2b59204e7db2816718098cf5c6d42eb63..7528afbf4c45188a15f521a1653988cf647e1f71 100644 (file)
@@ -34,9 +34,9 @@ super + m
 super + y
        bspc node newest.marked.local -n newest.!automatic.local
 
-# swap the current node and the biggest node
+# swap the current node and the biggest window
 super + g
-       bspc node -s biggest
+       bspc node -s biggest.window
 
 #
 # state/flags
@@ -62,9 +62,9 @@ super + {_,shift + }{h,j,k,l}
 super + {p,b,comma,period}
        bspc node -f @{parent,brother,first,second}
 
-# focus the next/previous node in the current desktop
+# focus the next/previous window in the current desktop
 super + {_,shift + }c
-       bspc node -f {next,prev}.local
+       bspc node -f {next,prev}.local.!hidden.window
 
 # focus the next/previous desktop in the current monitor
 super + bracket{left,right}
index c3a6077bd986e30bca842187d0c99aa860cb7afa..23ae367387a600bdfe1ff1e5e3ff1ccaeedeaa4a 100644 (file)
@@ -570,7 +570,7 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
        } else if (streq("pointed", desc)) {
                xcb_window_t win = XCB_NONE;
                query_pointer(&win, NULL);
-               if (locate_window(win, dst) && node_matches(dst, ref, &sel)) {
+               if (locate_leaf(win, dst) && node_matches(dst, ref, &sel)) {
                        return SELECTOR_OK;
                } else {
                        return SELECTOR_INVALID;
@@ -882,6 +882,23 @@ end:
        return SELECTOR_OK;
 }
 
+bool locate_leaf(xcb_window_t win, coordinates_t *loc)
+{
+       for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+               for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+                       for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+                               if (n->id == win) {
+                                       loc->monitor = m;
+                                       loc->desktop = d;
+                                       loc->node = n;
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
+
 bool locate_window(xcb_window_t win, coordinates_t *loc)
 {
        for (monitor_t *m = mon_head; m != NULL; m = m->next) {
index 9d87e5b9d9678bda2c27006bc1957a532f5f7c4e..a6bca75f6cfaafecf94fb627395b7be02075c763 100644 (file)
@@ -77,6 +77,7 @@ monitor_select_t make_monitor_select(void);
 int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
 int desktop_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
 int monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
+bool locate_leaf(xcb_window_t win, coordinates_t *loc);
 bool locate_window(xcb_window_t win, coordinates_t *loc);
 bool locate_desktop(char *name, coordinates_t *loc);
 bool locate_monitor(char *name, coordinates_t *loc);
index 127da6d617f5f2c97f26493f9531f29109b65167..c9f55bd3bea97f372395579075754e4178c49fb2 100644 (file)
@@ -841,6 +841,48 @@ node_t *first_focusable_leaf(node_t *n)
        return NULL;
 }
 
+node_t *next_node(node_t *n)
+{
+       if (n == NULL) {
+               return NULL;
+       }
+
+       if (n->second_child != NULL) {
+               return first_extrema(n->second_child);
+       } else {
+               node_t *p = n;
+               while (p != NULL && is_second_child(p)) {
+                       p = p->parent;
+               }
+               if (is_first_child(p)) {
+                       return p->parent;
+               } else {
+                       return NULL;
+               }
+       }
+}
+
+node_t *prev_node(node_t *n)
+{
+       if (n == NULL) {
+               return NULL;
+       }
+
+       if (n->first_child != NULL) {
+               return second_extrema(n->first_child);
+       } else {
+               node_t *p = n;
+               while (p != NULL && is_first_child(p)) {
+                       p = p->parent;
+               }
+               if (is_second_child(p)) {
+                       return p->parent;
+               } else {
+                       return NULL;
+               }
+       }
+}
+
 node_t *next_leaf(node_t *n, node_t *r)
 {
        if (n == NULL) {
@@ -1097,7 +1139,7 @@ void find_by_area(area_peak_t ap, coordinates_t *ref, coordinates_t *dst, node_s
                for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
                        for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
                                coordinates_t loc = {m, d, f};
-                               if (f->client == NULL || f->vacant || !node_matches(&loc, ref, sel)) {
+                               if (f->vacant || !node_matches(&loc, ref, sel)) {
                                        continue;
                                }
                                unsigned int f_area = node_area(d, f);
@@ -1618,7 +1660,7 @@ bool find_closest_node(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir,
        monitor_t *m = ref->monitor;
        desktop_t *d = ref->desktop;
        node_t *n = ref->node;
-       n = (dir == CYCLE_PREV ? prev_leaf(n, d->root) : next_leaf(n, d->root));
+       n = (dir == CYCLE_PREV ? prev_node(n) : next_node(n));
 
 #define HANDLE_BOUNDARIES(m, d, n)  \
        while (n == NULL) { \
@@ -1639,11 +1681,11 @@ bool find_closest_node(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir,
 
        while (n != ref->node) {
                coordinates_t loc = {m, d, n};
-               if (n->client != NULL && !n->hidden && node_matches(&loc, ref, sel)) {
+               if (node_matches(&loc, ref, sel)) {
                        *dst = loc;
                        return true;
                }
-               n = (dir == CYCLE_PREV ? prev_leaf(n, d->root) : next_leaf(n, d->root));
+               n = (dir == CYCLE_PREV ? prev_node(n) : next_node(n));
                HANDLE_BOUNDARIES(m, d, n);
                if (ref->node == NULL && d == ref->desktop) {
                        break;
index c4d1d0bcd99f7d3f528c3effbaca5cfd93d7f0e8..5a83a01ca180708badc29ca071c31dddc3c3e23b 100644 (file)
@@ -56,6 +56,8 @@ node_t *brother_tree(node_t *n);
 node_t *first_extrema(node_t *n);
 node_t *second_extrema(node_t *n);
 node_t *first_focusable_leaf(node_t *n);
+node_t *next_node(node_t *n);
+node_t *prev_node(node_t *n);
 node_t *next_leaf(node_t *n, node_t *r);
 node_t *prev_leaf(node_t *n, node_t *r);
 node_t *next_tiled_leaf(node_t *n, node_t *r);
index 1f5738f16c14ad89faf7c6ba5c3f856b95d00280..9b85016a573fe387b1e79843b4d8394535700044 100644 (file)
@@ -733,18 +733,32 @@ void query_pointer(xcb_window_t *win, xcb_point_t *pt)
 
        if (qpr != NULL) {
                if (win != NULL) {
-                       *win = qpr->child;
-                       xcb_point_t pt = {qpr->root_x, qpr->root_y};
-                       for (stacking_list_t *s = stack_tail; s != NULL; s = s->prev) {
-                               if (!s->node->client->shown || s->node->hidden) {
-                                       continue;
+                       if (qpr->child == XCB_NONE) {
+                               xcb_point_t mpt = (xcb_point_t) {qpr->root_x, qpr->root_y};
+                               monitor_t *m = monitor_from_point(mpt);
+                               if (m != NULL) {
+                                       desktop_t *d = m->desk;
+                                       for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+                                               if (n->client == NULL && is_inside(mpt, get_rectangle(m, d, n))) {
+                                                       *win = n->id;
+                                                       break;
+                                               }
+                                       }
                                }
-                               xcb_rectangle_t rect = get_rectangle(NULL, NULL, s->node);
-                               if (is_inside(pt, rect)) {
-                                       if (s->node->id == qpr->child || is_presel_window(qpr->child)) {
-                                               *win = s->node->id;
+                       } else {
+                               *win = qpr->child;
+                               xcb_point_t pt = {qpr->root_x, qpr->root_y};
+                               for (stacking_list_t *s = stack_tail; s != NULL; s = s->prev) {
+                                       if (!s->node->client->shown || s->node->hidden) {
+                                               continue;
+                                       }
+                                       xcb_rectangle_t rect = get_rectangle(NULL, NULL, s->node);
+                                       if (is_inside(pt, rect)) {
+                                               if (s->node->id == qpr->child || is_presel_window(qpr->child)) {
+                                                       *win = s->node->id;
+                                               }
+                                               break;
                                        }
-                                       break;
                                }
                        }
                }