summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-09-23 08:38:15 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-09-23 08:39:11 +1000
commitcb66bbea42adeabd7bd87132a66589e14a46940f (patch)
tree43f409e1619b2deded320f0af7064e73e3969d30
parentMerge pull request #2677 from ggreer/pretty-fonts (diff)
downloadsway-cb66bbea42adeabd7bd87132a66589e14a46940f.tar.gz
sway-cb66bbea42adeabd7bd87132a66589e14a46940f.tar.zst
sway-cb66bbea42adeabd7bd87132a66589e14a46940f.zip
Allow running commands on containers without focusing them
This adds a `con` argument to `execute_command` which allows you to specify the container to execute the command on. In most cases it leaves it as `NULL` which makes it use the focused node. We only set it when executing `for_window` criteria such as when a view maps. This means we don't send unnecessary IPC focus events, and fixes a crash when the criteria command is `move scratchpad` (because we can't give focus to a hidden scratchpad container). Each of the shell map handlers now check to see if the view has a workspace. It won't have a workspace if criteria has moved it to the scratchpad.
-rw-r--r--include/sway/commands.h9
-rw-r--r--sway/commands.c16
-rw-r--r--sway/commands/bind.c2
-rw-r--r--sway/desktop/xdg_shell.c2
-rw-r--r--sway/desktop/xdg_shell_v6.c2
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/ipc-server.c2
-rw-r--r--sway/main.c2
-rw-r--r--sway/tree/view.c10
9 files changed, 28 insertions, 19 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 226cf932..1654eb48 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -4,6 +4,8 @@
4#include <wlr/util/edges.h> 4#include <wlr/util/edges.h>
5#include "config.h" 5#include "config.h"
6 6
7struct sway_container;
8
7typedef struct cmd_results *sway_cmd(int argc, char **argv); 9typedef struct cmd_results *sway_cmd(int argc, char **argv);
8 10
9struct cmd_handler { 11struct cmd_handler {
@@ -50,8 +52,13 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers,
50 int handlers_size); 52 int handlers_size);
51/** 53/**
52 * Parse and executes a command. 54 * Parse and executes a command.
55 *
56 * If the command string contains criteria then the command will be executed on
57 * all matching containers. Otherwise, it'll run on the `con` container. If
58 * `con` is NULL then it'll run on the currently focused container.
53 */ 59 */
54struct cmd_results *execute_command(char *command, struct sway_seat *seat); 60struct cmd_results *execute_command(char *command, struct sway_seat *seat,
61 struct sway_container *con);
55/** 62/**
56 * Parse and handles a command during config file loading. 63 * Parse and handles a command during config file loading.
57 * 64 *
diff --git a/sway/commands.c b/sway/commands.c
index 07169f1e..5b61f73a 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -237,7 +237,8 @@ static void set_config_node(struct sway_node *node) {
237 } 237 }
238} 238}
239 239
240struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { 240struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
241 struct sway_container *con) {
241 // Even though this function will process multiple commands we will only 242 // Even though this function will process multiple commands we will only
242 // return the last error, if any (for now). (Since we have access to an 243 // return the last error, if any (for now). (Since we have access to an
243 // error string we could e.g. concatenate all errors there.) 244 // error string we could e.g. concatenate all errors there.)
@@ -256,6 +257,15 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
256 } 257 }
257 } 258 }
258 259
260 // This is the container or workspace which this command will run on.
261 // Ignored if the command string contains criteria.
262 struct sway_node *node;
263 if (con) {
264 node = &con->node;
265 } else {
266 node = seat_get_focus_inactive(seat, &root->node);
267 }
268
259 config->handler_context.seat = seat; 269 config->handler_context.seat = seat;
260 270
261 head = exec; 271 head = exec;
@@ -318,9 +328,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
318 } 328 }
319 329
320 if (!config->handler_context.using_criteria) { 330 if (!config->handler_context.using_criteria) {
321 // without criteria, the command acts upon the focused 331 set_config_node(node);
322 // container
323 set_config_node(seat_get_focus_inactive(seat, &root->node));
324 struct cmd_results *res = handler->handle(argc-1, argv+1); 332 struct cmd_results *res = handler->handle(argc-1, argv+1);
325 if (res->status != CMD_SUCCESS) { 333 if (res->status != CMD_SUCCESS) {
326 free_argv(argc, argv); 334 free_argv(argc, argv);
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 047018e0..820c2a6a 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -321,7 +321,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
321 } 321 }
322 322
323 config->handler_context.seat = seat; 323 config->handler_context.seat = seat;
324 struct cmd_results *results = execute_command(binding->command, NULL); 324 struct cmd_results *results = execute_command(binding->command, NULL, NULL);
325 if (results->status == CMD_SUCCESS) { 325 if (results->status == CMD_SUCCESS) {
326 ipc_event_binding(binding_copy); 326 ipc_event_binding(binding_copy);
327 } else { 327 } else {
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 00448be7..6d1ccdd7 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -401,7 +401,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
401 } else { 401 } else {
402 if (view->container->parent) { 402 if (view->container->parent) {
403 arrange_container(view->container->parent); 403 arrange_container(view->container->parent);
404 } else { 404 } else if (view->container->workspace) {
405 arrange_workspace(view->container->workspace); 405 arrange_workspace(view->container->workspace);
406 } 406 }
407 } 407 }
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index d2c9a68b..95ca396c 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -398,7 +398,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
398 } else { 398 } else {
399 if (view->container->parent) { 399 if (view->container->parent) {
400 arrange_container(view->container->parent); 400 arrange_container(view->container->parent);
401 } else { 401 } else if (view->container->workspace) {
402 arrange_workspace(view->container->workspace); 402 arrange_workspace(view->container->workspace);
403 } 403 }
404 } 404 }
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 3619f202..a12ac854 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -394,7 +394,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
394 } else { 394 } else {
395 if (view->container->parent) { 395 if (view->container->parent) {
396 arrange_container(view->container->parent); 396 arrange_container(view->container->parent);
397 } else { 397 } else if (view->container->workspace) {
398 arrange_workspace(view->container->workspace); 398 arrange_workspace(view->container->workspace);
399 } 399 }
400 } 400 }
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 8ae265f6..99959c97 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -580,7 +580,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
580 switch (client->current_command) { 580 switch (client->current_command) {
581 case IPC_COMMAND: 581 case IPC_COMMAND:
582 { 582 {
583 struct cmd_results *results = execute_command(buf, NULL); 583 struct cmd_results *results = execute_command(buf, NULL, NULL);
584 transaction_commit_dirty(); 584 transaction_commit_dirty();
585 char *json = cmd_results_to_json(results); 585 char *json = cmd_results_to_json(results);
586 int length = strlen(json); 586 int length = strlen(json);
diff --git a/sway/main.c b/sway/main.c
index 3d7cd158..990f5f3a 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -429,7 +429,7 @@ int main(int argc, char **argv) {
429 wlr_log(WLR_DEBUG, "Running deferred commands"); 429 wlr_log(WLR_DEBUG, "Running deferred commands");
430 while (config->cmd_queue->length) { 430 while (config->cmd_queue->length) {
431 char *line = config->cmd_queue->items[0]; 431 char *line = config->cmd_queue->items[0];
432 struct cmd_results *res = execute_command(line, NULL); 432 struct cmd_results *res = execute_command(line, NULL, NULL);
433 if (res->status != CMD_SUCCESS) { 433 if (res->status != CMD_SUCCESS) {
434 wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error); 434 wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
435 } 435 }
diff --git a/sway/tree/view.c b/sway/tree/view.c
index f61f5c84..e370443c 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view,
391} 391}
392 392
393void view_execute_criteria(struct sway_view *view) { 393void view_execute_criteria(struct sway_view *view) {
394 struct sway_seat *seat = input_manager_current_seat(input_manager);
395 struct sway_node *prior_focus = seat_get_focus(seat);
396 list_t *criterias = criteria_for_view(view, CT_COMMAND); 394 list_t *criterias = criteria_for_view(view, CT_COMMAND);
397 for (int i = 0; i < criterias->length; i++) { 395 for (int i = 0; i < criterias->length; i++) {
398 struct criteria *criteria = criterias->items[i]; 396 struct criteria *criteria = criterias->items[i];
@@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) {
403 } 401 }
404 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'", 402 wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
405 criteria->raw, view, criteria->cmdlist); 403 criteria->raw, view, criteria->cmdlist);
406 seat_set_focus_container(seat, view->container);
407 list_add(view->executed_criteria, criteria); 404 list_add(view->executed_criteria, criteria);
408 struct cmd_results *res = execute_command(criteria->cmdlist, NULL); 405 struct cmd_results *res = execute_command(
409 if (res->status != CMD_SUCCESS) { 406 criteria->cmdlist, NULL, view->container);
410 wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error);
411 }
412 free_cmd_results(res); 407 free_cmd_results(res);
413 } 408 }
414 list_free(criterias); 409 list_free(criterias);
415 seat_set_focus(seat, prior_focus);
416} 410}
417 411
418static struct sway_workspace *select_workspace(struct sway_view *view) { 412static struct sway_workspace *select_workspace(struct sway_view *view) {