From 8d96affaf421b12137414bba2fbbb230f9abed51 Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Wed, 7 Mar 2018 14:14:48 +0100 Subject: [PATCH] Add monitor/desktop/node descriptor: `any` --- contrib/zsh_completion | 6 +++--- doc/bspwm.1 | 25 ++++++++++++++++++++----- doc/bspwm.1.asciidoc | 15 ++++++++++++--- src/desktop.c | 14 ++++++++++++++ src/desktop.h | 1 + src/monitor.c | 12 ++++++++++++ src/monitor.h | 1 + src/query.c | 6 ++++++ src/tree.c | 30 ++++++++++++++++++++++++++++++ src/tree.h | 2 ++ 10 files changed, 101 insertions(+), 11 deletions(-) diff --git a/contrib/zsh_completion b/contrib/zsh_completion index a32515f..673141e 100644 --- a/contrib/zsh_completion +++ b/contrib/zsh_completion @@ -134,12 +134,12 @@ _bspc() { dir=(north west south east) \ cycle_dir=(next prev) local -a jump=($dir first second brother parent 1 2) \ - node_desc=($dir $cycle_dir last newest older newer focused pointed biggest) \ + node_desc=($dir $cycle_dir any last newest older newer focused pointed biggest) \ node_mod=($node_state $flag $layer focused automatic local \ active leaf window same_class descendant_of ancestor_of) \ - desktop_desc=($cycle_dir last newest older newer focused) \ + desktop_desc=($cycle_dir any last newest older newer focused) \ desktop_mod=(focused occupied local urgent) \ - monitor_desc=($dir $cycle_dir primary last newest older newer focused pointed) \ + monitor_desc=($dir $cycle_dir any last newest older newer focused pointed primary) \ monitor_mod=(focused occupied) \ presel_dir=($dir cancel) local quote="${compstate[quote]}" context state state_descr line diff --git a/doc/bspwm.1 b/doc/bspwm.1 index ba2db7d..104223a 100644 --- a/doc/bspwm.1 +++ b/doc/bspwm.1 @@ -4,10 +4,10 @@ .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 03/07/2018 .\" Manual: Bspwm Manual -.\" Source: Bspwm 0.9.3-52-gf83f7ef +.\" Source: Bspwm 0.9.3-55-g7d639d1 .\" Language: English .\" -.TH "BSPWM" "1" "03/07/2018" "Bspwm 0\&.9\&.3\-52\-gf83f7ef" "Bspwm Manual" +.TH "BSPWM" "1" "03/07/2018" "Bspwm 0\&.9\&.3\-55\-g7d639d1" "Bspwm Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -100,7 +100,7 @@ Select a node\&. .RS 4 .\} .nf -NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|newest| +NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|any|last|newest| older|newer|focused|pointed| biggest|)[\&.[!]focused][\&.[!]automatic][\&.[!]local][\&.[!]active] [\&.[!]leaf][\&.[!]window][\&.[!]STATE][\&.[!]FLAG][\&.[!]LAYER] @@ -143,6 +143,11 @@ Selects the window in the given (cyclic) direction relative to the reference nod Selects the node at the given path\&. .RE .PP +any +.RS 4 +Selects the first node that matches the given selectors\&. +.RE +.PP last .RS 4 Selects the previously focused node relative to the reference node\&. @@ -302,7 +307,7 @@ Select a desktop\&. .RS 4 .\} .nf -DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|newest|older|newer| +DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|any|last|newest|older|newer| [MONITOR_SEL:](focused|^)| |)[\&.[!]occupied][\&.[!]focused][\&.[!]urgent][\&.[!]local] .fi @@ -323,6 +328,11 @@ DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|newest|older|newer| Selects the desktop in the given direction relative to the reference desktop\&. .RE .PP +any +.RS 4 +Selects the first desktop that matches the given selectors\&. +.RE +.PP last .RS 4 Selects the previously focused desktop relative to the reference desktop\&. @@ -402,7 +412,7 @@ Select a monitor\&. .RS 4 .\} .nf -MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|newest|older|newer| +MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|any|last|newest|older|newer| focused|pointed|primary|^| |)[\&.[!]occupied][\&.[!]focused] .fi @@ -428,6 +438,11 @@ Selects the monitor in the given (spacial) direction relative to the reference m Selects the monitor in the given (cyclic) direction relative to the reference monitor\&. .RE .PP +any +.RS 4 +Selects the first monitor that matches the given selectors\&. +.RE +.PP last .RS 4 Selects the previously focused monitor relative to the reference monitor\&. diff --git a/doc/bspwm.1.asciidoc b/doc/bspwm.1.asciidoc index acc2955..376ddf0 100644 --- a/doc/bspwm.1.asciidoc +++ b/doc/bspwm.1.asciidoc @@ -74,7 +74,7 @@ Node Select a node. ---- -NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|last|newest| +NODE_SEL := [NODE_SEL#](DIR|CYCLE_DIR|PATH|any|last|newest| older|newer|focused|pointed| biggest|)[.[!]focused][.[!]automatic][.[!]local][.[!]active] [.[!]leaf][.[!]window][.[!]STATE][.[!]FLAG][.[!]LAYER] @@ -103,6 +103,9 @@ Descriptors 'PATH':: Selects the node at the given path. +any:: + Selects the first node that matches the given selectors. + last:: Selects the previously focused node relative to the reference node. @@ -192,7 +195,7 @@ Desktop Select a desktop. ---- -DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|last|newest|older|newer| +DESKTOP_SEL := [DESKTOP_SEL#](CYCLE_DIR|any|last|newest|older|newer| [MONITOR_SEL:](focused|^)| |)[.[!]occupied][.[!]focused][.[!]urgent][.[!]local] ---- @@ -203,6 +206,9 @@ Descriptors 'CYCLE_DIR':: Selects the desktop in the given direction relative to the reference desktop. +any:: + Selects the first desktop that matches the given selectors. + last:: Selects the previously focused desktop relative to the reference desktop. @@ -248,7 +254,7 @@ Monitor Select a monitor. ---- -MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|last|newest|older|newer| +MONITOR_SEL := [MONITOR_SEL#](DIR|CYCLE_DIR|any|last|newest|older|newer| focused|pointed|primary|^| |)[.[!]occupied][.[!]focused] ---- @@ -262,6 +268,9 @@ Descriptors 'CYCLE_DIR':: Selects the monitor in the given (cyclic) direction relative to the reference monitor. +any:: + Selects the first monitor that matches the given selectors. + last:: Selects the previously focused monitor relative to the reference monitor. diff --git a/src/desktop.c b/src/desktop.c index ef94746..d99325f 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -116,6 +116,20 @@ bool find_closest_desktop(coordinates_t *ref, coordinates_t *dst, cycle_dir_t di return false; } +bool find_any_desktop(coordinates_t *ref, coordinates_t *dst, desktop_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) { + coordinates_t loc = {m, d, NULL}; + if (desktop_matches(&loc, ref, sel)) { + *dst = loc; + return true; + } + } + } + return false; +} + bool set_layout(monitor_t *m, desktop_t *d, layout_t l) { if (d->layout == l) { diff --git a/src/desktop.h b/src/desktop.h index 2374b94..dd544a4 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -30,6 +30,7 @@ void focus_desktop(monitor_t *m, desktop_t *d); bool activate_desktop(monitor_t *m, desktop_t *d); bool find_closest_desktop(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, desktop_select_t *sel); +bool find_any_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t *sel); bool set_layout(monitor_t *m, desktop_t *d, layout_t l); void handle_presel_feedbacks(monitor_t *m, desktop_t *d); bool transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d, bool follow); diff --git a/src/monitor.c b/src/monitor.c index f1b51f1..4b94cea 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -441,6 +441,18 @@ monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t *sel) return nearest; } +bool find_any_monitor(coordinates_t *ref, coordinates_t *dst, monitor_select_t *sel) +{ + for (monitor_t *m = mon_head; m != NULL; m = m->next) { + coordinates_t loc = {m, NULL, NULL}; + if (monitor_matches(&loc, ref, sel)) { + *dst = loc; + return true; + } + } + return false; +} + bool update_monitors(void) { xcb_randr_get_screen_resources_reply_t *sres = xcb_randr_get_screen_resources_reply(dpy, xcb_randr_get_screen_resources(dpy, root), NULL); diff --git a/src/monitor.h b/src/monitor.h index 60e2bef..33b64e5 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -46,6 +46,7 @@ bool is_inside_monitor(monitor_t *m, xcb_point_t pt); monitor_t *monitor_from_point(xcb_point_t pt); monitor_t *monitor_from_client(client_t *c); monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t *sel); +bool find_any_monitor(coordinates_t *ref, coordinates_t *dst, monitor_select_t *sel); bool update_monitors(void); #endif diff --git a/src/query.c b/src/query.c index 7f64de5..f1c9c91 100644 --- a/src/query.c +++ b/src/query.c @@ -507,6 +507,8 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) find_closest_node(ref, dst, cyc, &sel); } else if (parse_history_direction(desc, &hdi)) { history_find_node(hdi, ref, dst, &sel); + } else if (streq("any", desc)) { + find_any_node(ref, dst, &sel); } else if (streq("last", desc)) { history_find_node(HISTORY_OLDER, ref, dst, &sel); } else if (streq("newest", desc)) { @@ -643,6 +645,8 @@ int desktop_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) find_closest_desktop(ref, dst, cyc, &sel); } else if (parse_history_direction(desc, &hdi)) { history_find_desktop(hdi, ref, dst, &sel); + } else if (streq("any", desc)) { + find_any_desktop(ref, dst, &sel); } else if (streq("last", desc)) { history_find_desktop(HISTORY_OLDER, ref, dst, &sel); } else if (streq("newest", desc)) { @@ -761,6 +765,8 @@ int monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) dst->monitor = closest_monitor(ref->monitor, cyc, &sel); } else if (parse_history_direction(desc, &hdi)) { history_find_monitor(hdi, ref, dst, &sel); + } else if (streq("any", desc)) { + find_any_monitor(ref, dst, &sel); } else if (streq("last", desc)) { history_find_monitor(HISTORY_OLDER, ref, dst, &sel); } else if (streq("newest", desc)) { diff --git a/src/tree.c b/src/tree.c index 97274b8..2d0cc98 100644 --- a/src/tree.c +++ b/src/tree.c @@ -960,6 +960,36 @@ 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) { diff --git a/src/tree.h b/src/tree.h index 59f7212..05501f4 100644 --- a/src/tree.h +++ b/src/tree.h @@ -66,6 +66,8 @@ bool is_child(node_t *a, node_t *b); bool is_descendant(node_t *a, node_t *b); bool find_by_id(uint32_t id, coordinates_t *loc); 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); +bool find_any_node_in(monitor_t *m, desktop_t *d, node_t *n, coordinates_t *ref, coordinates_t *dst, node_select_t *sel); void find_nearest_neighbor(coordinates_t *ref, coordinates_t *dst, direction_t dir, node_select_t *sel); unsigned int node_area(desktop_t *d, node_t *n); int tiled_count(node_t *n); -- 2.44.0