diff --git a/doc/bspwm.1 b/doc/bspwm.1
index 9c3e99f..b5171be 100644
--- a/doc/bspwm.1
+++ b/doc/bspwm.1
@@ -2,12 +2,12 @@
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot
-.\" 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
diff --git a/doc/bspwm.1.asciidoc b/doc/bspwm.1.asciidoc
index 0923f94..9d2a42b 100644
--- a/doc/bspwm.1.asciidoc
+++ b/doc/bspwm.1.asciidoc
@@ -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.
::
Selects the node with the given ID.
diff --git a/examples/sxhkdrc b/examples/sxhkdrc
index 0e5ea5a..7528afb 100644
--- a/examples/sxhkdrc
+++ b/examples/sxhkdrc
@@ -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}
diff --git a/src/query.c b/src/query.c
index c3a6077..23ae367 100644
--- a/src/query.c
+++ b/src/query.c
@@ -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) {
diff --git a/src/query.h b/src/query.h
index 9d87e5b..a6bca75 100644
--- a/src/query.h
+++ b/src/query.h
@@ -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);
diff --git a/src/tree.c b/src/tree.c
index 127da6d..c9f55bd 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -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;
diff --git a/src/tree.h b/src/tree.h
index c4d1d0b..5a83a01 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -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);
diff --git a/src/window.c b/src/window.c
index 1f5738f..9b85016 100644
--- a/src/window.c
+++ b/src/window.c
@@ -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;
- }
- 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;
+ 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;
+ }
+ }
+ }
+ } 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;
}
}
}