diff options
author | 2020-12-12 00:11:58 +0100 | |
---|---|---|
committer | 2021-02-25 09:48:39 -0500 | |
commit | 1afedcb94c0517b5434e2220e63b997cf01427bd (patch) | |
tree | 3fae6d855a165e7364540a1474508caa8ae1b708 | |
parent | focus: beyond fullscreen when focused explicitly (diff) | |
download | sway-1afedcb94c0517b5434e2220e63b997cf01427bd.tar.gz sway-1afedcb94c0517b5434e2220e63b997cf01427bd.tar.zst sway-1afedcb94c0517b5434e2220e63b997cf01427bd.zip |
Fix for_window criteria and mouse button bindings
Previously, the special case handling of scratchpad and unmark commands
was (probably accidentally) limited to criteria directly handled in the
execute_command function. This would exclude: 1. for_window criteria, as
these are handled externally for views and 2. and mouse bindings which
select target the node currently under the mouse cursor.
As a concrete example `for_window [app_id="foobar"] move scratchpad,
scratchpad show` would show (or hide due to the toggling functionality)
another window from the scratchpad, instead of showing the window with
app_id "foobar".
This commit replaces the "using_criteria" flag with "node_overridden"
with the more general notion of signifying that the node (and
container/workspace) in the current command handler context of the sway
config is not defined by the currently focused node, but instead
overridden by other means, i.e., criteria or mouse position.
-rw-r--r-- | include/sway/config.h | 2 | ||||
-rw-r--r-- | sway/commands.c | 23 | ||||
-rw-r--r-- | sway/commands/scratchpad.c | 9 | ||||
-rw-r--r-- | sway/commands/unmark.c | 2 |
4 files changed, 21 insertions, 15 deletions
diff --git a/include/sway/config.h b/include/sway/config.h index 59f22ae2..2a1df2b6 100644 --- a/include/sway/config.h +++ b/include/sway/config.h | |||
@@ -559,7 +559,7 @@ struct sway_config { | |||
559 | struct sway_node *node; | 559 | struct sway_node *node; |
560 | struct sway_container *container; | 560 | struct sway_container *container; |
561 | struct sway_workspace *workspace; | 561 | struct sway_workspace *workspace; |
562 | bool using_criteria; | 562 | bool node_overridden; // True if the node is selected by means other than focus |
563 | struct { | 563 | struct { |
564 | int argc; | 564 | int argc; |
565 | char **argv; | 565 | char **argv; |
diff --git a/sway/commands.c b/sway/commands.c index ede6c60c..b09a04c7 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -174,10 +174,11 @@ static const struct cmd_handler *find_core_handler(char *line) { | |||
174 | handlers, sizeof(handlers)); | 174 | handlers, sizeof(handlers)); |
175 | } | 175 | } |
176 | 176 | ||
177 | static void set_config_node(struct sway_node *node) { | 177 | static void set_config_node(struct sway_node *node, bool node_overridden) { |
178 | config->handler_context.node = node; | 178 | config->handler_context.node = node; |
179 | config->handler_context.container = NULL; | 179 | config->handler_context.container = NULL; |
180 | config->handler_context.workspace = NULL; | 180 | config->handler_context.workspace = NULL; |
181 | config->handler_context.node_overridden = node_overridden; | ||
181 | 182 | ||
182 | if (node == NULL) { | 183 | if (node == NULL) { |
183 | return; | 184 | return; |
@@ -202,6 +203,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, | |||
202 | char *cmd; | 203 | char *cmd; |
203 | char matched_delim = ';'; | 204 | char matched_delim = ';'; |
204 | list_t *containers = NULL; | 205 | list_t *containers = NULL; |
206 | bool using_criteria = false; | ||
205 | 207 | ||
206 | if (seat == NULL) { | 208 | if (seat == NULL) { |
207 | // passing a NULL seat means we just pick the default seat | 209 | // passing a NULL seat means we just pick the default seat |
@@ -225,7 +227,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, | |||
225 | for (; isspace(*head); ++head) {} | 227 | for (; isspace(*head); ++head) {} |
226 | // Extract criteria (valid for this command list only). | 228 | // Extract criteria (valid for this command list only). |
227 | if (matched_delim == ';') { | 229 | if (matched_delim == ';') { |
228 | config->handler_context.using_criteria = false; | 230 | using_criteria = false; |
229 | if (*head == '[') { | 231 | if (*head == '[') { |
230 | char *error = NULL; | 232 | char *error = NULL; |
231 | struct criteria *criteria = criteria_parse(head, &error); | 233 | struct criteria *criteria = criteria_parse(head, &error); |
@@ -239,7 +241,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, | |||
239 | containers = criteria_get_containers(criteria); | 241 | containers = criteria_get_containers(criteria); |
240 | head += strlen(criteria->raw); | 242 | head += strlen(criteria->raw); |
241 | criteria_destroy(criteria); | 243 | criteria_destroy(criteria); |
242 | config->handler_context.using_criteria = true; | 244 | using_criteria = true; |
243 | // Skip leading whitespace | 245 | // Skip leading whitespace |
244 | for (; isspace(*head); ++head) {} | 246 | for (; isspace(*head); ++head) {} |
245 | } | 247 | } |
@@ -278,11 +280,14 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, | |||
278 | argv[i] = do_var_replacement(argv[i]); | 280 | argv[i] = do_var_replacement(argv[i]); |
279 | } | 281 | } |
280 | 282 | ||
281 | if (!config->handler_context.using_criteria) { | 283 | |
282 | // The container or workspace which this command will run on. | 284 | if (!using_criteria) { |
283 | struct sway_node *node = con ? &con->node : | 285 | if (con) { |
284 | seat_get_focus_inactive(seat, &root->node); | 286 | set_config_node(&con->node, true); |
285 | set_config_node(node); | 287 | } else { |
288 | set_config_node(seat_get_focus_inactive(seat, &root->node), | ||
289 | false); | ||
290 | } | ||
286 | struct cmd_results *res = handler->handle(argc-1, argv+1); | 291 | struct cmd_results *res = handler->handle(argc-1, argv+1); |
287 | list_add(res_list, res); | 292 | list_add(res_list, res); |
288 | if (res->status == CMD_INVALID) { | 293 | if (res->status == CMD_INVALID) { |
@@ -296,7 +301,7 @@ list_t *execute_command(char *_exec, struct sway_seat *seat, | |||
296 | struct cmd_results *fail_res = NULL; | 301 | struct cmd_results *fail_res = NULL; |
297 | for (int i = 0; i < containers->length; ++i) { | 302 | for (int i = 0; i < containers->length; ++i) { |
298 | struct sway_container *container = containers->items[i]; | 303 | struct sway_container *container = containers->items[i]; |
299 | set_config_node(&container->node); | 304 | set_config_node(&container->node, true); |
300 | struct cmd_results *res = handler->handle(argc-1, argv+1); | 305 | struct cmd_results *res = handler->handle(argc-1, argv+1); |
301 | if (res->status == CMD_SUCCESS) { | 306 | if (res->status == CMD_SUCCESS) { |
302 | free_cmd_results(res); | 307 | free_cmd_results(res); |
diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c index a1285df5..c995f2f0 100644 --- a/sway/commands/scratchpad.c +++ b/sway/commands/scratchpad.c | |||
@@ -105,12 +105,12 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { | |||
105 | return cmd_results_new(CMD_INVALID, "Scratchpad is empty"); | 105 | return cmd_results_new(CMD_INVALID, "Scratchpad is empty"); |
106 | } | 106 | } |
107 | 107 | ||
108 | if (config->handler_context.using_criteria) { | 108 | if (config->handler_context.node_overridden) { |
109 | struct sway_container *con = config->handler_context.container; | 109 | struct sway_container *con = config->handler_context.container; |
110 | 110 | ||
111 | // If the container is in a floating split container, | 111 | // If the container is in a floating split container, |
112 | // operate on the split container instead of the child. | 112 | // operate on the split container instead of the child. |
113 | if (container_is_floating_or_child(con)) { | 113 | if (con && container_is_floating_or_child(con)) { |
114 | while (con->pending.parent) { | 114 | while (con->pending.parent) { |
115 | con = con->pending.parent; | 115 | con = con->pending.parent; |
116 | } | 116 | } |
@@ -118,8 +118,9 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { | |||
118 | 118 | ||
119 | // If using criteria, this command is executed for every container which | 119 | // If using criteria, this command is executed for every container which |
120 | // matches the criteria. If this container isn't in the scratchpad, | 120 | // matches the criteria. If this container isn't in the scratchpad, |
121 | // we'll just silently return a success. | 121 | // we'll just silently return a success. The same is true if the |
122 | if (!con->scratchpad) { | 122 | // overridden node is not a container. |
123 | if (!con || !con->scratchpad) { | ||
123 | return cmd_results_new(CMD_SUCCESS, NULL); | 124 | return cmd_results_new(CMD_SUCCESS, NULL); |
124 | } | 125 | } |
125 | scratchpad_toggle_container(con); | 126 | scratchpad_toggle_container(con); |
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c index cedfcfb2..19274dfb 100644 --- a/sway/commands/unmark.c +++ b/sway/commands/unmark.c | |||
@@ -21,7 +21,7 @@ static void remove_all_marks_iterator(struct sway_container *con, void *data) { | |||
21 | struct cmd_results *cmd_unmark(int argc, char **argv) { | 21 | struct cmd_results *cmd_unmark(int argc, char **argv) { |
22 | // Determine the container | 22 | // Determine the container |
23 | struct sway_container *con = NULL; | 23 | struct sway_container *con = NULL; |
24 | if (config->handler_context.using_criteria) { | 24 | if (config->handler_context.node_overridden) { |
25 | con = config->handler_context.container; | 25 | con = config->handler_context.container; |
26 | } | 26 | } |
27 | 27 | ||