- `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.
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\" Source: Bspwm 0.9.9-25-g8f41d79
+.\" Source: Bspwm 0.9.9-26-ga54ab70
.\" Language: English
.\"
.\" 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
.\" -----------------------------------------------------------------
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.PP
\fICYCLE_DIR\fR
.RS 4
.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\&.
-Selects the window under the pointer\&.
+Selects the leaf under the pointer\&.
-Selects the biggest window\&.
+Selects the biggest leaf\&.
-Selects the smallest window\&.
+Selects the smallest leaf\&.
Selects the window in the given (spacial) direction relative to the reference node.
'CYCLE_DIR'::
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.
'PATH'::
Selects the node at the given path.
Selects the currently focused node.
pointed::
Selects the currently focused node.
pointed::
- Selects the window under the pointer.
+ Selects the leaf under the pointer.
- Selects the biggest window.
+ Selects the biggest leaf.
- Selects the smallest window.
+ Selects the smallest leaf.
<node_id>::
Selects the node with the given ID.
<node_id>::
Selects the node with the given ID.
super + y
bspc node newest.marked.local -n newest.!automatic.local
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
+ bspc node -s biggest.window
super + {p,b,comma,period}
bspc node -f @{parent,brother,first,second}
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
- 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}
# focus the next/previous desktop in the current monitor
super + bracket{left,right}
} else if (streq("pointed", desc)) {
xcb_window_t win = XCB_NONE;
query_pointer(&win, NULL);
} 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;
return SELECTOR_OK;
} else {
return SELECTOR_INVALID;
+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) {
bool locate_window(xcb_window_t win, coordinates_t *loc)
{
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
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);
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);
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);
+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) {
node_t *next_leaf(node_t *n, node_t *r)
{
if (n == NULL) {
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};
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);
continue;
}
unsigned int f_area = node_area(d, f);
monitor_t *m = ref->monitor;
desktop_t *d = ref->desktop;
node_t *n = ref->node;
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) { \
#define HANDLE_BOUNDARIES(m, d, n) \
while (n == NULL) { \
while (n != ref->node) {
coordinates_t loc = {m, d, n};
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;
}
*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;
HANDLE_BOUNDARIES(m, d, n);
if (ref->node == NULL && d == ref->desktop) {
break;
node_t *first_extrema(node_t *n);
node_t *second_extrema(node_t *n);
node_t *first_focusable_leaf(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);
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);
if (qpr != NULL) {
if (win != NULL) {
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;