From e471298d0adfb8d3bb64dbcfacb156bd3981cdb0 Mon Sep 17 00:00:00 2001 From: Bastien Dejean Date: Mon, 9 May 2016 16:55:31 +0200 Subject: [PATCH] Add node modifiers: {descendant,ancestor}_of Fixes #473. --- doc/bspwm.1 | 38 ++++--- doc/bspwm.1.asciidoc | 30 +++--- messages.c | 251 ++++++++++++++++++++++++------------------- parse.c | 2 + query.c | 66 +++++++----- query.h | 8 +- tree.c | 32 +++--- tree.h | 2 +- types.h | 2 + 9 files changed, 242 insertions(+), 189 deletions(-) diff --git a/doc/bspwm.1 b/doc/bspwm.1 index c7f6e50..5946f76 100644 --- a/doc/bspwm.1 +++ b/doc/bspwm.1 @@ -4,10 +4,10 @@ .\" Generator: DocBook XSL Stylesheets v1.78.1 .\" Date: 05/09/2016 .\" Manual: Bspwm Manual -.\" Source: Bspwm 0.9.1-54-gcdc20bb +.\" Source: Bspwm 0.9.1-56-gbbc3406 .\" Language: English .\" -.TH "BSPWM" "1" "05/09/2016" "Bspwm 0\&.9\&.1\-54\-gcdc20bb" "Bspwm Manual" +.TH "BSPWM" "1" "05/09/2016" "Bspwm 0\&.9\&.1\-56\-gbbc3406" "Bspwm Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -94,7 +94,7 @@ Select a node\&. .RS 4 .\} .nf -NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|)[\&.[!]focused][\&.[!]automatic][\&.[!]local][\&.[!]leaf][\&.[!]window][\&.[!]STATE][\&.[!]FLAG][\&.[!]LAYER][\&.[!]same_class] +NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|)[\&.[!]focused][\&.[!]automatic][\&.[!]local][\&.[!]leaf][\&.[!]window][\&.[!]STATE][\&.[!]FLAG][\&.[!]LAYER][\&.[!]same_class][\&.[!]descendant_of][\&.[!]ancestor_of] STATE := tiled|pseudo_tiled|floating|fullscreen @@ -120,12 +120,12 @@ JUMP := first|1|second|2|brother|parent|DIR .PP \fIDIR\fR .RS 4 -Selects the window in the given (spacial) direction relative to the active node\&. +Selects the window in the given (spacial) direction relative to the reference node\&. .RE .PP \fICYCLE_DIR\fR .RS 4 -Selects the window in the given (cyclic) direction\&. +Selects the window in the given (cyclic) direction relative to the reference node\&. .RE .PP \fIPATH\fR @@ -135,17 +135,17 @@ Selects the node at the given path\&. .PP last .RS 4 -Selects the previously focused node\&. +Selects the previously focused node relative to the reference node\&. .RE .PP older .RS 4 -Selects the node older than the focused node in the history\&. +Selects the node older than the reference node in the history\&. .RE .PP newer .RS 4 -Selects the node newer than the focused node in the history\&. +Selects the node newer than the reference node in the history\&. .RE .PP focused @@ -160,7 +160,7 @@ Selects the window under the pointer\&. .PP biggest .RS 4 -Selects the biggest window on the current desktop\&. +Selects the biggest window\&. .RE .PP @@ -177,7 +177,7 @@ Selects the node with the given ID\&. \fBPath Jumps\fR .RS 4 .sp -The initial node is the focused node (or the root if the path starts with \fI/\fR) of the focused desktop (or the selected desktop if the path has a \fIDESKTOP_SEL\fR prefix)\&. +The initial node is the focused node (or the root if the path starts with \fI/\fR) of the reference desktop (or the selected desktop if the path has a \fIDESKTOP_SEL\fR prefix)\&. .PP 1|first .RS 4 @@ -245,7 +245,17 @@ Only consider windows in or not in the given state\&. .PP [!]same_class .RS 4 -Only consider windows that have or don\(cqt have the same class as the current window\&. +Only consider windows that have or don\(cqt have the same class as the reference window\&. +.RE +.PP +[!]descendant_of +.RS 4 +Only consider nodes that are or aren\(cqt descendants of the reference node\&. +.RE +.PP +[!]ancestor_of +.RS 4 +Only consider nodes that are or aren\(cqt ancestors of the reference node\&. .RE .PP [!](hidden|sticky|private|locked|urgent) @@ -793,17 +803,17 @@ query \fICOMMANDS\fR [\fIOPTIONS\fR] \fBCommands\fR .RS 4 .PP -\fB\-N\fR, \fB\-\-nodes\fR +\fB\-N\fR, \fB\-\-nodes\fR [\fINODE_SEL\fR] .RS 4 List the IDs of the matching nodes\&. .RE .PP -\fB\-D\fR, \fB\-\-desktops\fR +\fB\-D\fR, \fB\-\-desktops\fR [\fIDESKTOP_SEL\fR] .RS 4 List the IDs of the matching desktops\&. .RE .PP -\fB\-M\fR, \fB\-\-monitors\fR +\fB\-M\fR, \fB\-\-monitors\fR [\fIMONITOR_SEL\fR] .RS 4 List the IDs of the matching monitors\&. .RE diff --git a/doc/bspwm.1.asciidoc b/doc/bspwm.1.asciidoc index cef3f9f..93a8522 100644 --- a/doc/bspwm.1.asciidoc +++ b/doc/bspwm.1.asciidoc @@ -66,7 +66,7 @@ Node Select a node. ---- -NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|)[.[!]focused][.[!]automatic][.[!]local][.[!]leaf][.[!]window][.[!]STATE][.[!]FLAG][.[!]LAYER][.[!]same_class] +NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|)[.[!]focused][.[!]automatic][.[!]local][.[!]leaf][.[!]window][.[!]STATE][.[!]FLAG][.[!]LAYER][.[!]same_class][.[!]descendant_of][.[!]ancestor_of] STATE := tiled|pseudo_tiled|floating|fullscreen @@ -83,22 +83,22 @@ Descriptors ^^^^^^^^^^^ 'DIR':: - Selects the window in the given (spacial) direction relative to the active node. + Selects the window in the given (spacial) direction relative to the reference node. 'CYCLE_DIR':: - Selects the window in the given (cyclic) direction. + Selects the window in the given (cyclic) direction relative to the reference node. 'PATH':: Selects the node at the given path. last:: - Selects the previously focused node. + Selects the previously focused node relative to the reference node. older:: - Selects the node older than the focused node in the history. + Selects the node older than the reference node in the history. newer:: - Selects the node newer than the focused node in the history. + Selects the node newer than the reference node in the history. focused:: Selects the currently focused node. @@ -107,7 +107,7 @@ pointed:: Selects the window under the pointer. biggest:: - Selects the biggest window on the current desktop. + Selects the biggest window. :: Selects the node with the given ID. @@ -115,7 +115,7 @@ biggest:: Path Jumps ^^^^^^^^^^ -The initial node is the focused node (or the root if the path starts with '/') of the focused desktop (or the selected desktop if the path has a 'DESKTOP_SEL' prefix). +The initial node is the focused node (or the root if the path starts with '/') of the reference desktop (or the selected desktop if the path has a 'DESKTOP_SEL' prefix). 1|first:: Jumps to the first child. @@ -154,7 +154,13 @@ Modifiers Only consider windows in or not in the given state. [!]same_class:: - Only consider windows that have or don't have the same class as the current window. + Only consider windows that have or don't have the same class as the reference window. + +[!]descendant_of:: + Only consider nodes that are or aren't descendants of the reference node. + +[!]ancestor_of:: + Only consider nodes that are or aren't ancestors of the reference node. [!](hidden|sticky|private|locked|urgent):: Only consider windows that have or don't have the given flag set. @@ -473,13 +479,13 @@ query 'COMMANDS' ['OPTIONS'] Commands ^^^^^^^^ -*-N*, *--nodes*:: +*-N*, *--nodes* ['NODE_SEL']:: List the IDs of the matching nodes. -*-D*, *--desktops*:: +*-D*, *--desktops* ['DESKTOP_SEL']:: List the IDs of the matching desktops. -*-M*, *--monitors*:: +*-M*, *--monitors* ['MONITOR_SEL']:: List the IDs of the matching monitors. *-T*, *--tree*:: diff --git a/messages.c b/messages.c index 58beee1..7022b38 100644 --- a/messages.c +++ b/messages.c @@ -123,11 +123,11 @@ void cmd_node(char **args, int num, FILE *rsp) } coordinates_t ref = {mon, mon->desk, mon->desk->focus}; - coordinates_t trg = ref; if ((*args)[0] != OPT_CHR) { int ret; - if ((ret = node_from_desc(*args, &ref, &trg)) == SELECTOR_OK) { + coordinates_t tmp = ref; + if ((ret = node_from_desc(*args, &tmp, &ref)) == SELECTOR_OK) { num--, args++; } else { handle_failure(ret, "node", *args, rsp); @@ -139,11 +139,11 @@ void cmd_node(char **args, int num, FILE *rsp) while (num > 0) { if (streq("-f", *args) || streq("--focus", *args)) { - coordinates_t dst = trg; + coordinates_t dst = ref; if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; int ret; - if ((ret = node_from_desc(*args, &trg, &dst)) != SELECTOR_OK) { + if ((ret = node_from_desc(*args, &ref, &dst)) != SELECTOR_OK) { handle_failure(ret, "node -f", *args, rsp); break; } @@ -153,11 +153,11 @@ void cmd_node(char **args, int num, FILE *rsp) break; } } else if (streq("-a", *args) || streq("--activate", *args)) { - coordinates_t dst = trg; + coordinates_t dst = ref; if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; int ret; - if ((ret = node_from_desc(*args, &trg, &dst)) != SELECTOR_OK) { + if ((ret = node_from_desc(*args, &ref, &dst)) != SELECTOR_OK) { handle_failure(ret, "node -a", *args, rsp); break; } @@ -174,10 +174,10 @@ void cmd_node(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = desktop_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (transfer_node(trg.monitor, trg.desktop, trg.node, dst.monitor, dst.desktop, dst.desktop->focus)) { - trg.monitor = dst.monitor; - trg.desktop = dst.desktop; + if ((ret = desktop_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (transfer_node(ref.monitor, ref.desktop, ref.node, dst.monitor, dst.desktop, dst.desktop->focus)) { + ref.monitor = dst.monitor; + ref.desktop = dst.desktop; } else { fail(rsp, ""); break; @@ -194,10 +194,10 @@ void cmd_node(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = monitor_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (transfer_node(trg.monitor, trg.desktop, trg.node, dst.monitor, dst.monitor->desk, dst.monitor->desk->focus)) { - trg.monitor = dst.monitor; - trg.desktop = dst.monitor->desk; + if ((ret = monitor_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (transfer_node(ref.monitor, ref.desktop, ref.node, dst.monitor, dst.monitor->desk, dst.monitor->desk->focus)) { + ref.monitor = dst.monitor; + ref.desktop = dst.monitor->desk; } else { fail(rsp, ""); break; @@ -214,10 +214,10 @@ void cmd_node(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = node_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (transfer_node(trg.monitor, trg.desktop, trg.node, dst.monitor, dst.desktop, dst.node)) { - trg.monitor = dst.monitor; - trg.desktop = dst.desktop; + if ((ret = node_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (transfer_node(ref.monitor, ref.desktop, ref.node, dst.monitor, dst.desktop, dst.node)) { + ref.monitor = dst.monitor; + ref.desktop = dst.desktop; } else { fail(rsp, ""); break; @@ -234,10 +234,10 @@ void cmd_node(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = node_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (swap_nodes(trg.monitor, trg.desktop, trg.node, dst.monitor, dst.desktop, dst.node)) { - trg.monitor = dst.monitor; - trg.desktop = dst.desktop; + if ((ret = node_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (swap_nodes(ref.monitor, ref.desktop, ref.node, dst.monitor, dst.desktop, dst.node)) { + ref.monitor = dst.monitor; + ref.desktop = dst.desktop; } else { fail(rsp, ""); break; @@ -254,7 +254,7 @@ void cmd_node(char **args, int num, FILE *rsp) } stack_layer_t lyr; if (parse_stack_layer(*args, &lyr)) { - if (!set_layer(trg.monitor, trg.desktop, trg.node, lyr)) { + if (!set_layer(ref.monitor, ref.desktop, ref.node, lyr)) { fail(rsp, ""); break; } @@ -275,11 +275,11 @@ void cmd_node(char **args, int num, FILE *rsp) (*args)++; } if (parse_client_state(*args, &cst)) { - if (alternate && trg.node != NULL && trg.node->client != NULL && - trg.node->client->state == cst) { - cst = trg.node->client->last_state; + if (alternate && ref.node != NULL && ref.node->client != NULL && + ref.node->client->state == cst) { + cst = ref.node->client->last_state; } - if (!set_state(trg.monitor, trg.desktop, trg.node, cst)) { + if (!set_state(ref.monitor, ref.desktop, ref.node, cst)) { fail(rsp, ""); break; } @@ -294,7 +294,7 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } @@ -313,14 +313,14 @@ void cmd_node(char **args, int num, FILE *rsp) } } if (streq("hidden", key)) { - set_hidden(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->hidden)); + set_hidden(ref.monitor, ref.desktop, ref.node, (a == ALTER_SET ? b : !ref.node->hidden)); changed = true; } else if (streq("sticky", key)) { - set_sticky(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->sticky)); + set_sticky(ref.monitor, ref.desktop, ref.node, (a == ALTER_SET ? b : !ref.node->sticky)); } else if (streq("private", key)) { - set_private(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->private)); + set_private(ref.monitor, ref.desktop, ref.node, (a == ALTER_SET ? b : !ref.node->private)); } else if (streq("locked", key)) { - set_locked(trg.monitor, trg.desktop, trg.node, (a == ALTER_SET ? b : !trg.node->locked)); + set_locked(ref.monitor, ref.desktop, ref.node, (a == ALTER_SET ? b : !ref.node->locked)); } else { fail(rsp, "node %s: Invalid key: '%s'.\n", *(args - 1), key); break; @@ -331,12 +331,12 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL || trg.node->vacant) { + if (ref.node == NULL || ref.node->vacant) { fail(rsp, ""); break; } if (streq("cancel", *args)) { - cancel_presel(trg.monitor, trg.desktop, trg.node); + cancel_presel(ref.monitor, ref.desktop, ref.node); } else { bool alternate = false; if ((*args)[0] == '~') { @@ -345,12 +345,12 @@ void cmd_node(char **args, int num, FILE *rsp) } direction_t dir; if (parse_direction(*args, &dir)) { - if (alternate && trg.node->presel != NULL && trg.node->presel->split_dir == dir) { - cancel_presel(trg.monitor, trg.desktop, trg.node); + if (alternate && ref.node->presel != NULL && ref.node->presel->split_dir == dir) { + cancel_presel(ref.monitor, ref.desktop, ref.node); } else { - presel_dir(trg.monitor, trg.desktop, trg.node, dir); - if (!IS_RECEPTACLE(trg.node)) { - draw_presel_feedback(trg.monitor, trg.desktop, trg.node); + presel_dir(ref.monitor, ref.desktop, ref.node, dir); + if (!IS_RECEPTACLE(ref.node)) { + draw_presel_feedback(ref.monitor, ref.desktop, ref.node); } } } else { @@ -364,7 +364,7 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL || trg.node->vacant) { + if (ref.node == NULL || ref.node->vacant) { fail(rsp, ""); break; } @@ -373,8 +373,8 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Invalid argument: '%s'.\n", *(args - 1), *args); break; } else { - presel_ratio(trg.monitor, trg.desktop, trg.node, rat); - draw_presel_feedback(trg.monitor, trg.desktop, trg.node); + presel_ratio(ref.monitor, ref.desktop, ref.node, rat); + draw_presel_feedback(ref.monitor, ref.desktop, ref.node); } } else if (streq("-v", *args) || streq("--move", *args)) { num--, args++; @@ -386,7 +386,7 @@ void cmd_node(char **args, int num, FILE *rsp) if (sscanf(*args, "%i", &dx) == 1) { num--, args++; if (sscanf(*args, "%i", &dy) == 1) { - if (!move_client(&trg, dx, dy)) { + if (!move_client(&ref, dx, dy)) { fail(rsp, ""); break; } @@ -411,7 +411,7 @@ void cmd_node(char **args, int num, FILE *rsp) if (sscanf(*args, "%i", &dx) == 1) { num--, args++; if (sscanf(*args, "%i", &dy) == 1) { - if (!resize_client(&trg, rh, dx, dy)) { + if (!resize_client(&ref, rh, dx, dy)) { fail(rsp, ""); break; } @@ -433,17 +433,17 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } if ((*args)[0] == '+' || (*args)[0] == '-') { int pix; if (sscanf(*args, "%i", &pix) == 1) { - int max = (trg.node->split_type == TYPE_HORIZONTAL ? trg.node->rectangle.height : trg.node->rectangle.width); - double rat = ((max * trg.node->split_ratio) + pix) / max; + int max = (ref.node->split_type == TYPE_HORIZONTAL ? ref.node->rectangle.height : ref.node->rectangle.width); + double rat = ((max * ref.node->split_ratio) + pix) / max; if (rat > 0 && rat < 1) { - set_ratio(trg.node, rat); + set_ratio(ref.node, rat); } else { fail(rsp, ""); break; @@ -455,7 +455,7 @@ void cmd_node(char **args, int num, FILE *rsp) } else { double rat; if (sscanf(*args, "%lf", &rat) == 1 && rat > 0 && rat < 1) { - set_ratio(trg.node, rat); + set_ratio(ref.node, rat); } else { fail(rsp, "node %s: Invalid argument: '%s'.\n", *(args - 1), *args); break; @@ -468,13 +468,13 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } flip_t flp; if (parse_flip(*args, &flp)) { - flip_tree(trg.node, flp); + flip_tree(ref.node, flp); changed = true; } else { fail(rsp, ""); @@ -486,31 +486,31 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } int deg; if (parse_degree(*args, °)) { - rotate_tree(trg.node, deg); + rotate_tree(ref.node, deg); changed = true; } else { fail(rsp, "node %s: Invalid argument: '%s'.\n", *(args - 1), *args); break; } } else if (streq("-E", *args) || streq("--equalize", *args)) { - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } - equalize_tree(trg.node); + equalize_tree(ref.node); changed = true; } else if (streq("-B", *args) || streq("--balance", *args)) { - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } - balance_tree(trg.node); + balance_tree(ref.node); changed = true; } else if (streq("-C", *args) || streq("--circulate", *args)) { num--, args++; @@ -518,42 +518,42 @@ void cmd_node(char **args, int num, FILE *rsp) fail(rsp, "node %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } circulate_dir_t cir; if (parse_circulate_direction(*args, &cir)) { - circulate_leaves(trg.monitor, trg.desktop, trg.node, cir); + circulate_leaves(ref.monitor, ref.desktop, ref.node, cir); changed = true; } else { fail(rsp, "node %s: Invalid argument: '%s'.\n", *(args - 1), *args); break; } } else if (streq("-i", *args) || streq("--insert-receptacle", *args)) { - insert_receptacle(trg.monitor, trg.desktop, trg.node); + insert_receptacle(ref.monitor, ref.desktop, ref.node); changed = true; } else if (streq("-c", *args) || streq("--close", *args)) { if (num > 1) { fail(rsp, "node %s: Trailing commands.\n", *args); break; } - if (trg.node == NULL || locked_count(trg.node) > 0) { + if (ref.node == NULL || locked_count(ref.node) > 0) { fail(rsp, ""); break; } - close_node(trg.node); + close_node(ref.node); break; } else if (streq("-k", *args) || streq("--kill", *args)) { if (num > 1) { fail(rsp, "node %s: Trailing commands.\n", *args); break; } - if (trg.node == NULL) { + if (ref.node == NULL) { fail(rsp, ""); break; } - kill_node(trg.monitor, trg.desktop, trg.node); + kill_node(ref.monitor, ref.desktop, ref.node); changed = true; break; } else { @@ -565,7 +565,7 @@ void cmd_node(char **args, int num, FILE *rsp) } if (changed) { - arrange(trg.monitor, trg.desktop); + arrange(ref.monitor, ref.desktop); } } @@ -577,11 +577,11 @@ void cmd_desktop(char **args, int num, FILE *rsp) } coordinates_t ref = {mon, mon->desk, NULL}; - coordinates_t trg = ref; if ((*args)[0] != OPT_CHR) { int ret; - if ((ret = desktop_from_desc(*args, &ref, &trg)) == SELECTOR_OK) { + coordinates_t tmp = ref; + if ((ret = desktop_from_desc(*args, &tmp, &ref)) == SELECTOR_OK) { num--, args++; } else { handle_failure(ret, "desktop", *args, rsp); @@ -593,22 +593,22 @@ void cmd_desktop(char **args, int num, FILE *rsp) while (num > 0) { if (streq("-f", *args) || streq("--focus", *args)) { - coordinates_t dst = trg; + coordinates_t dst = ref; if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; int ret; - if ((ret = desktop_from_desc(*args, &trg, &dst)) != SELECTOR_OK) { + if ((ret = desktop_from_desc(*args, &ref, &dst)) != SELECTOR_OK) { handle_failure(ret, "desktop -f", *args, rsp); break; } } focus_node(dst.monitor, dst.desktop, dst.desktop->focus); } else if (streq("-a", *args) || streq("--activate", *args)) { - coordinates_t dst = trg; + coordinates_t dst = ref; if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; int ret; - if ((ret = desktop_from_desc(*args, &trg, &dst)) != SELECTOR_OK) { + if ((ret = desktop_from_desc(*args, &ref, &dst)) != SELECTOR_OK) { handle_failure(ret, "desktop -a", *args, rsp); break; } @@ -623,15 +623,15 @@ void cmd_desktop(char **args, int num, FILE *rsp) fail(rsp, "desktop %s: Not enough arguments.\n", *(args - 1)); break; } - if (trg.monitor->desk_head == trg.monitor->desk_tail) { + if (ref.monitor->desk_head == ref.monitor->desk_tail) { fail(rsp, ""); break; } coordinates_t dst; int ret; - if ((ret = monitor_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (transfer_desktop(trg.monitor, dst.monitor, trg.desktop)) { - trg.monitor = dst.monitor; + if ((ret = monitor_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (transfer_desktop(ref.monitor, dst.monitor, ref.desktop)) { + ref.monitor = dst.monitor; } else { fail(rsp, ""); break; @@ -648,9 +648,9 @@ void cmd_desktop(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = desktop_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (swap_desktops(trg.monitor, trg.desktop, dst.monitor, dst.desktop)) { - trg.monitor = dst.monitor; + if ((ret = desktop_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (swap_desktops(ref.monitor, ref.desktop, dst.monitor, dst.desktop)) { + ref.monitor = dst.monitor; } else { fail(rsp, ""); break; @@ -667,22 +667,22 @@ void cmd_desktop(char **args, int num, FILE *rsp) } cycle_dir_t cyc; if (parse_cycle_direction(*args, &cyc)) { - desktop_t *d = trg.desktop; + desktop_t *d = ref.desktop; if (cyc == CYCLE_PREV) { if (d->prev == NULL) { while (d->next != NULL) { - swap_desktops(trg.monitor, d, trg.monitor, d->next); + swap_desktops(ref.monitor, d, ref.monitor, d->next); } } else { - swap_desktops(trg.monitor, d, trg.monitor, d->prev); + swap_desktops(ref.monitor, d, ref.monitor, d->prev); } } else { if (d->next == NULL) { while (d->prev != NULL) { - swap_desktops(trg.monitor, d, trg.monitor, d->prev); + swap_desktops(ref.monitor, d, ref.monitor, d->prev); } } else { - swap_desktops(trg.monitor, d, trg.monitor, d->next); + swap_desktops(ref.monitor, d, ref.monitor, d->next); } } } else { @@ -698,9 +698,9 @@ void cmd_desktop(char **args, int num, FILE *rsp) layout_t lyt; cycle_dir_t cyc; if (parse_cycle_direction(*args, &cyc)) { - change_layout(trg.monitor, trg.desktop, (trg.desktop->layout + 1) % 2); + change_layout(ref.monitor, ref.desktop, (ref.desktop->layout + 1) % 2); } else if (parse_layout(*args, &lyt)) { - change_layout(trg.monitor, trg.desktop, lyt); + change_layout(ref.monitor, ref.desktop, lyt); } else { fail(rsp, "desktop %s: Invalid argument: '%s'.\n", *(args - 1), *args); break; @@ -711,15 +711,15 @@ void cmd_desktop(char **args, int num, FILE *rsp) fail(rsp, "desktop %s: Not enough arguments.\n", *(args - 1)); break; } - rename_desktop(trg.monitor, trg.desktop, *args); + rename_desktop(ref.monitor, ref.desktop, *args); } else if (streq("-r", *args) || streq("--remove", *args)) { if (num > 1) { fail(rsp, "desktop %s: Trailing commands.\n", *args); break; } - if (trg.desktop->root == NULL && - trg.monitor->desk_head != trg.monitor->desk_tail) { - remove_desktop(trg.monitor, trg.desktop); + if (ref.desktop->root == NULL && + ref.monitor->desk_head != ref.monitor->desk_tail) { + remove_desktop(ref.monitor, ref.desktop); return; } else { fail(rsp, ""); @@ -733,7 +733,7 @@ void cmd_desktop(char **args, int num, FILE *rsp) } if (changed) { - arrange(trg.monitor, trg.desktop); + arrange(ref.monitor, ref.desktop); } } @@ -745,11 +745,11 @@ void cmd_monitor(char **args, int num, FILE *rsp) } coordinates_t ref = {mon, NULL, NULL}; - coordinates_t trg = ref; if ((*args)[0] != OPT_CHR) { int ret; - if ((ret = monitor_from_desc(*args, &ref, &trg)) == SELECTOR_OK) { + coordinates_t tmp = ref; + if ((ret = monitor_from_desc(*args, &tmp, &ref)) == SELECTOR_OK) { num--, args++; } else { handle_failure(ret, "monitor", *args, rsp); @@ -759,11 +759,11 @@ void cmd_monitor(char **args, int num, FILE *rsp) while (num > 0) { if (streq("-f", *args) || streq("--focus", *args)) { - coordinates_t dst = trg; + coordinates_t dst = ref; if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; int ret; - if ((ret = monitor_from_desc(*args, &trg, &dst)) != SELECTOR_OK) { + if ((ret = monitor_from_desc(*args, &ref, &dst)) != SELECTOR_OK) { handle_failure(ret, "monitor -f", *args, rsp); fail(rsp, ""); return; @@ -776,24 +776,24 @@ void cmd_monitor(char **args, int num, FILE *rsp) fail(rsp, "monitor %s: Not enough arguments.\n", *(args - 1)); return; } - desktop_t *d = trg.monitor->desk_head; + desktop_t *d = ref.monitor->desk_head; while (num > 0 && d != NULL) { - rename_desktop(trg.monitor, d, *args); + rename_desktop(ref.monitor, d, *args); d = d->next; num--, args++; } put_status(SBSC_MASK_REPORT); while (num > 0) { - add_desktop(trg.monitor, make_desktop(*args, XCB_NONE)); + add_desktop(ref.monitor, make_desktop(*args, XCB_NONE)); num--, args++; } while (d != NULL) { desktop_t *next = d->next; if (d == mon->desk) { - focus_node(trg.monitor, d->prev, d->prev->focus); + focus_node(ref.monitor, d->prev, d->prev->focus); } - merge_desktops(trg.monitor, d, mon, mon->desk); - remove_desktop(trg.monitor, d); + merge_desktops(ref.monitor, d, mon, mon->desk); + remove_desktop(ref.monitor, d); d = next; } } else if (streq("-a", *args) || streq("--add-desktops", *args)) { @@ -803,7 +803,7 @@ void cmd_monitor(char **args, int num, FILE *rsp) return; } while (num > 0) { - add_desktop(trg.monitor, make_desktop(*args, XCB_NONE)); + add_desktop(ref.monitor, make_desktop(*args, XCB_NONE)); num--, args++; } } else if (streq("-r", *args) || streq("--remove", *args)) { @@ -815,7 +815,7 @@ void cmd_monitor(char **args, int num, FILE *rsp) fail(rsp, ""); return; } - remove_monitor(trg.monitor); + remove_monitor(ref.monitor); return; } else if (streq("-o", *args) || streq("--order-desktops", *args)) { num--, args++; @@ -823,12 +823,12 @@ void cmd_monitor(char **args, int num, FILE *rsp) fail(rsp, "monitor %s: Not enough arguments.\n", *(args - 1)); return; } - desktop_t *d = trg.monitor->desk_head; + desktop_t *d = ref.monitor->desk_head; while (d != NULL && num > 0) { desktop_t *next = d->next; coordinates_t dst; - if (locate_desktop(*args, &dst) && dst.monitor == trg.monitor) { - swap_desktops(trg.monitor, d, dst.monitor, dst.desktop); + if (locate_desktop(*args, &dst) && dst.monitor == ref.monitor) { + swap_desktops(ref.monitor, d, dst.monitor, dst.desktop); if (next == dst.desktop) { next = d; } @@ -844,7 +844,7 @@ void cmd_monitor(char **args, int num, FILE *rsp) } xcb_rectangle_t r; if (parse_rectangle(*args, &r)) { - update_root(trg.monitor, &r); + update_root(ref.monitor, &r); } else { fail(rsp, "monitor %s: Invalid argument: '%s'.\n", *(args - 1), *args); return; @@ -855,7 +855,7 @@ void cmd_monitor(char **args, int num, FILE *rsp) fail(rsp, "monitor %s: Not enough arguments.\n", *(args - 1)); return; } - rename_monitor(trg.monitor, *args); + rename_monitor(ref.monitor, *args); } else if (streq("-s", *args) || streq("--swap", *args)) { num--, args++; if (num < 1) { @@ -864,8 +864,8 @@ void cmd_monitor(char **args, int num, FILE *rsp) } coordinates_t dst; int ret; - if ((ret = monitor_from_desc(*args, &trg, &dst)) == SELECTOR_OK) { - if (!swap_monitors(trg.monitor, dst.monitor)) { + if ((ret = monitor_from_desc(*args, &ref, &dst)) == SELECTOR_OK) { + if (!swap_monitors(ref.monitor, dst.monitor)) { fail(rsp, ""); return; } @@ -901,10 +901,37 @@ void cmd_query(char **args, int num, FILE *rsp) dom = DOMAIN_TREE, d++; } else if (streq("-M", *args) || streq("--monitors", *args)) { dom = DOMAIN_MONITOR, d++; + if (num > 1 && *(args + 1)[0] != OPT_CHR) { + num--, args++; + int ret; + coordinates_t tmp = ref; + if ((ret = monitor_from_desc(*args, &tmp, &ref)) != SELECTOR_OK) { + handle_failure(ret, "query -M", *args, rsp); + break; + } + } } else if (streq("-D", *args) || streq("--desktops", *args)) { dom = DOMAIN_DESKTOP, d++; + if (num > 1 && *(args + 1)[0] != OPT_CHR) { + num--, args++; + int ret; + coordinates_t tmp = ref; + if ((ret = desktop_from_desc(*args, &tmp, &ref)) != SELECTOR_OK) { + handle_failure(ret, "query -D", *args, rsp); + break; + } + } } else if (streq("-N", *args) || streq("--nodes", *args)) { dom = DOMAIN_NODE, d++; + if (num > 1 && *(args + 1)[0] != OPT_CHR) { + num--, args++; + int ret; + coordinates_t tmp = ref; + if ((ret = node_from_desc(*args, &tmp, &ref)) != SELECTOR_OK) { + handle_failure(ret, "query -N", *args, rsp); + break; + } + } } else if (streq("-m", *args) || streq("--monitor", *args)) { if (num > 1 && *(args + 1)[0] != OPT_CHR) { num--, args++; @@ -999,15 +1026,15 @@ void cmd_query(char **args, int num, FILE *rsp) } if (dom == DOMAIN_NODE) { - if (query_node_ids(trg, node_sel, rsp) < 1) { + if (query_node_ids(&ref, &trg, node_sel, rsp) < 1) { fail(rsp, ""); } } else if (dom == DOMAIN_DESKTOP) { - if (query_desktop_ids(trg, desktop_sel, rsp) < 1) { + if (query_desktop_ids(&ref, &trg, desktop_sel, rsp) < 1) { fail(rsp, ""); } } else if (dom == DOMAIN_MONITOR) { - if (query_monitor_ids(trg, monitor_sel, rsp) < 1) { + if (query_monitor_ids(&ref, &trg, monitor_sel, rsp) < 1) { fail(rsp, ""); } } else { diff --git a/parse.c b/parse.c index 1b41259..04b8ed4 100644 --- a/parse.c +++ b/parse.c @@ -447,6 +447,8 @@ bool parse_node_modifiers(char *desc, node_select_t *sel) GET_MOD(locked) GET_MOD(urgent) GET_MOD(same_class) + GET_MOD(descendant_of) + GET_MOD(ancestor_of) GET_MOD(below) GET_MOD(normal) GET_MOD(above) diff --git a/query.c b/query.c index c5d2ca0..d156519 100644 --- a/query.c +++ b/query.c @@ -212,54 +212,52 @@ void query_stack(FILE *rsp) fprintf(rsp, "]"); } -int query_node_ids(coordinates_t loc, node_select_t *sel, FILE *rsp) +int query_node_ids(coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp) { int count = 0; for (monitor_t *m = mon_head; m != NULL; m = m->next) { - if (loc.monitor != NULL && m != loc.monitor) { + if (trg->monitor != NULL && m != trg->monitor) { continue; } for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { - if (loc.desktop != NULL && d != loc.desktop) { + if (trg->desktop != NULL && d != trg->desktop) { continue; } - count += query_node_ids_in(d->root, d, m, loc, sel, rsp); + count += query_node_ids_in(d->root, d, m, ref, trg, sel, rsp); } } return count; } -int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t loc, node_select_t *sel, FILE *rsp) +int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp) { int count = 0; if (n == NULL) { return 0; } else { - coordinates_t ref = {mon, mon->desk, mon->desk->focus}; - coordinates_t trg = {m, d, n}; - if ((loc.node == NULL || n == loc.node) && - (sel == NULL || node_matches(&trg, &ref, *sel))) { + coordinates_t loc = {m, d, n}; + if ((trg->node == NULL || n == trg->node) && + (sel == NULL || node_matches(&loc, ref, *sel))) { fprintf(rsp, "0x%08X\n", n->id); count++; } - count += query_node_ids_in(n->first_child, d, m, loc, sel, rsp); - count += query_node_ids_in(n->second_child, d, m, loc, sel, rsp); + count += query_node_ids_in(n->first_child, d, m, ref, trg, sel, rsp); + count += query_node_ids_in(n->second_child, d, m, ref, trg, sel, rsp); } return count; } -int query_desktop_ids(coordinates_t loc, desktop_select_t *sel, FILE *rsp) +int query_desktop_ids(coordinates_t *ref, coordinates_t *trg, desktop_select_t *sel, FILE *rsp) { int count = 0; for (monitor_t *m = mon_head; m != NULL; m = m->next) { - if (loc.monitor != NULL && m != loc.monitor) { + if (trg->monitor != NULL && m != trg->monitor) { continue; } for (desktop_t *d = m->desk_head; d != NULL; d = d->next) { - coordinates_t ref = {mon, mon->desk, NULL}; - coordinates_t trg = {m, d, NULL}; - if ((loc.desktop != NULL && d != loc.desktop) || - (sel != NULL && !desktop_matches(&trg, &ref, *sel))) { + coordinates_t loc = {m, d, NULL}; + if ((trg->desktop != NULL && d != trg->desktop) || + (sel != NULL && !desktop_matches(&loc, ref, *sel))) { continue; } fprintf(rsp, "0x%08X\n", d->id); @@ -269,14 +267,13 @@ int query_desktop_ids(coordinates_t loc, desktop_select_t *sel, FILE *rsp) return count; } -int query_monitor_ids(coordinates_t loc, monitor_select_t *sel, FILE *rsp) +int query_monitor_ids(coordinates_t *ref, coordinates_t *trg, monitor_select_t *sel, FILE *rsp) { int count = 0; for (monitor_t *m = mon_head; m != NULL; m = m->next) { - coordinates_t ref = {mon, NULL, NULL}; - coordinates_t trg = {m, NULL, NULL}; - if ((loc.monitor != NULL && m != loc.monitor) || - (sel != NULL && !monitor_matches(&trg, &ref, *sel))) { + coordinates_t loc = {m, NULL, NULL}; + if ((trg->monitor != NULL && m != trg->monitor) || + (sel != NULL && !monitor_matches(&loc, ref, *sel))) { continue; } fprintf(rsp, "0x%08X\n", m->id); @@ -351,6 +348,8 @@ node_select_t make_node_select(void) .locked = OPTION_NONE, .urgent = OPTION_NONE, .same_class = OPTION_NONE, + .descendant_of = OPTION_NONE, + .ancestor_of = OPTION_NONE, .below = OPTION_NONE, .normal = OPTION_NONE, .above = OPTION_NONE @@ -390,8 +389,6 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) return SELECTOR_BAD_MODIFIERS; } - dst->monitor = ref->monitor; - dst->desktop = ref->desktop; dst->node = NULL; direction_t dir; @@ -406,7 +403,7 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) } else if (streq("last", desc)) { history_find_node(HISTORY_OLDER, ref, dst, sel); } else if (streq("biggest", desc)) { - dst->node = find_biggest(ref->monitor, ref->desktop, ref->node, sel); + find_biggest(ref, dst, sel); } else if (streq("pointed", desc)) { xcb_window_t win; query_pointer(&win, NULL); @@ -418,12 +415,11 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst) } else if (streq("focused", desc)) { coordinates_t loc = {mon, mon->desk, mon->desk->focus}; if (node_matches(&loc, ref, sel)) { - dst->monitor = mon; - dst->desktop = mon->desk; - dst->node = mon->desk->focus; + *dst = loc; } } else if (*desc == '@') { desc++; + *dst = *ref; if (colon != NULL) { *colon = '\0'; int ret; @@ -836,6 +832,20 @@ bool node_matches(coordinates_t *loc, coordinates_t *ref, node_select_t sel) return false; } + if (sel.descendant_of != OPTION_NONE && + !is_descendant(loc->node, ref->node) + ? sel.descendant_of == OPTION_TRUE + : sel.descendant_of == OPTION_FALSE) { + return false; + } + + if (sel.ancestor_of != OPTION_NONE && + !is_descendant(ref->node, loc->node) + ? sel.ancestor_of == OPTION_TRUE + : sel.ancestor_of == OPTION_FALSE) { + return false; + } + #define WSTATE(p, e) \ if (sel.p != OPTION_NONE && \ loc->node->client->state != e \ diff --git a/query.h b/query.h index 5841668..e6be902 100644 --- a/query.h +++ b/query.h @@ -52,10 +52,10 @@ void query_padding(padding_t p, FILE *rsp); void query_history(FILE *rsp); void query_coordinates(coordinates_t *loc, FILE *rsp); void query_stack(FILE *rsp); -int query_node_ids(coordinates_t loc, node_select_t *sel, FILE *rsp); -int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t loc, node_select_t *sel, FILE *rsp); -int query_desktop_ids(coordinates_t loc, desktop_select_t *sel, FILE *rsp); -int query_monitor_ids(coordinates_t loc, monitor_select_t *sel, FILE *rsp); +int query_node_ids(coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp); +int query_node_ids_in(node_t *n, desktop_t *d, monitor_t *m, coordinates_t *ref, coordinates_t *trg, node_select_t *sel, FILE *rsp); +int query_desktop_ids(coordinates_t *ref, coordinates_t *trg, desktop_select_t *sel, FILE *rsp); +int query_monitor_ids(coordinates_t *ref, coordinates_t *trg, monitor_select_t *sel, FILE *rsp); void print_modifier_mask(uint16_t m, FILE *rsp); void print_pointer_action(pointer_action_t a, FILE *rsp); node_select_t make_node_select(void); diff --git a/tree.c b/tree.c index 5d14968..aa2a5a4 100644 --- a/tree.c +++ b/tree.c @@ -968,29 +968,25 @@ int tiled_count(node_t *n) return cnt; } -node_t *find_biggest(monitor_t *m, desktop_t *d, node_t *n, node_select_t sel) +void find_biggest(coordinates_t *ref, coordinates_t *dst, node_select_t sel) { - if (d == NULL) { - return NULL; - } - - node_t *b = NULL; unsigned int b_area = 0; - coordinates_t ref = {m, d, n}; - 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)) { - continue; - } - unsigned int f_area = node_area(d, f); - if (f_area > b_area) { - b = f; - b_area = f_area; + 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 *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)) { + continue; + } + unsigned int f_area = node_area(d, f); + if (f_area > b_area) { + *dst = loc; + b_area = f_area; + } + } } } - - return b; } void rotate_tree(node_t *n, int deg) diff --git a/tree.h b/tree.h index 78ae47f..6e91fa0 100644 --- a/tree.h +++ b/tree.h @@ -66,7 +66,7 @@ node_t *find_by_id_in(node_t *r, uint32_t id); 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); -node_t *find_biggest(monitor_t *m, desktop_t *d, node_t *n, node_select_t sel); +void find_biggest(coordinates_t *ref, coordinates_t *dst, node_select_t sel); void rotate_tree(node_t *n, int deg); void rotate_brother(node_t *n); void unrotate_tree(node_t *n, int rot); diff --git a/types.h b/types.h index 2f8a568..027ff11 100644 --- a/types.h +++ b/types.h @@ -154,6 +154,8 @@ typedef struct { option_bool_t locked; option_bool_t urgent; option_bool_t same_class; + option_bool_t descendant_of; + option_bool_t ancestor_of; option_bool_t below; option_bool_t normal; option_bool_t above;