]> git.lizzy.rs Git - bspwm.git/commitdiff
Add node modifiers: {descendant,ancestor}_of
authorBastien Dejean <nihilhill@gmail.com>
Mon, 9 May 2016 14:55:31 +0000 (16:55 +0200)
committerBastien Dejean <nihilhill@gmail.com>
Mon, 9 May 2016 14:55:31 +0000 (16:55 +0200)
Fixes #473.

doc/bspwm.1
doc/bspwm.1.asciidoc
messages.c
parse.c
query.c
query.h
tree.c
tree.h
types.h

index c7f6e500a25808adfee10b000b3aa7a4b69714bb..5946f76dcb7ff6f191c26992e04f4b9d8d212e6b 100644 (file)
@@ -4,10 +4,10 @@
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
 .\"      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|<node_id>)[\&.[!]focused][\&.[!]automatic][\&.[!]local][\&.[!]leaf][\&.[!]window][\&.[!]STATE][\&.[!]FLAG][\&.[!]LAYER][\&.[!]same_class]
+NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|<node_id>)[\&.[!]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
 <node_id>
@@ -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
index cef3f9fd5581148f9d3616aaba69721186993a40..93a85223e67589c27348f23d4b54229ae85f66a4 100644 (file)
@@ -66,7 +66,7 @@ Node
 Select a node.
 
 ----
-NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|<node_id>)[.[!]focused][.[!]automatic][.[!]local][.[!]leaf][.[!]window][.[!]STATE][.[!]FLAG][.[!]LAYER][.[!]same_class]
+NODE_SEL := (DIR|CYCLE_DIR|PATH|last|older|newer|focused|pointed|biggest|<node_id>)[.[!]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.
 
 <node_id>::
        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*::
index 58beee132b1a87cf656ba3b22a04dac4dadd239b..7022b3840a6cb3c17b9dc0e517d7db722c172573 100644 (file)
@@ -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, &deg)) {
-                               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 1b41259bde775bab89b0618825cb9d43f6403b46..04b8ed4b8a6f1785b376e9718d180191b7b02a2a 100644 (file)
--- 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 c5d2ca055f75a8c4a6699bafcd8be4cd281d30be..d156519eb5f68560fc4fafbb52b82acf7fbcb955 100644 (file)
--- 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 5841668a4db28efe85059d12a9c08e3cb7ea2fde..e6be90254960ead4441bd9b73c1be84fe85988e9 100644 (file)
--- 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 5d14968f9b7b8db3364e0f7f287643767c0d1da5..aa2a5a45121b715df53f2851650c9439760ac55b 100644 (file)
--- 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 78ae47ffc5682cf92fb36c0499db4b249bf02279..6e91fa06dbd9d211ec593a28bfb1cf34efb5397c 100644 (file)
--- 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 2f8a568802533199648a9aacd0b8fdca55d70a24..027ff11f08d2217315dfd92f18afd0d94b76a891 100644 (file)
--- 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;