mirror of
https://github.com/vale981/bspwm
synced 2025-03-04 09:21:42 -05:00
Generalize a few node descriptors
- `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.
This commit is contained in:
parent
a54ab707cf
commit
d87e6c0f77
8 changed files with 107 additions and 31 deletions
14
doc/bspwm.1
14
doc/bspwm.1
|
@ -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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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}
|
||||
|
|
19
src/query.c
19
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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
50
src/tree.c
50
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;
|
||||
|
|
|
@ -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);
|
||||
|
|
36
src/window.c
36
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue