mirror of
https://github.com/swaywm/sway.git
synced 2024-11-11 13:04:11 +01:00
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.
This commit is contained in:
parent
082488a81c
commit
cb66bbea42
@ -4,6 +4,8 @@
|
|||||||
#include <wlr/util/edges.h>
|
#include <wlr/util/edges.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
struct sway_container;
|
||||||
|
|
||||||
typedef struct cmd_results *sway_cmd(int argc, char **argv);
|
typedef struct cmd_results *sway_cmd(int argc, char **argv);
|
||||||
|
|
||||||
struct cmd_handler {
|
struct cmd_handler {
|
||||||
@ -50,8 +52,13 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers,
|
|||||||
int handlers_size);
|
int handlers_size);
|
||||||
/**
|
/**
|
||||||
* Parse and executes a command.
|
* Parse and executes a command.
|
||||||
|
*
|
||||||
|
* If the command string contains criteria then the command will be executed on
|
||||||
|
* all matching containers. Otherwise, it'll run on the `con` container. If
|
||||||
|
* `con` is NULL then it'll run on the currently focused container.
|
||||||
*/
|
*/
|
||||||
struct cmd_results *execute_command(char *command, struct sway_seat *seat);
|
struct cmd_results *execute_command(char *command, struct sway_seat *seat,
|
||||||
|
struct sway_container *con);
|
||||||
/**
|
/**
|
||||||
* Parse and handles a command during config file loading.
|
* Parse and handles a command during config file loading.
|
||||||
*
|
*
|
||||||
|
@ -237,7 +237,8 @@ static void set_config_node(struct sway_node *node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
|
struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
|
||||||
|
struct sway_container *con) {
|
||||||
// Even though this function will process multiple commands we will only
|
// Even though this function will process multiple commands we will only
|
||||||
// return the last error, if any (for now). (Since we have access to an
|
// return the last error, if any (for now). (Since we have access to an
|
||||||
// error string we could e.g. concatenate all errors there.)
|
// 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) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the container or workspace which this command will run on.
|
||||||
|
// Ignored if the command string contains criteria.
|
||||||
|
struct sway_node *node;
|
||||||
|
if (con) {
|
||||||
|
node = &con->node;
|
||||||
|
} else {
|
||||||
|
node = seat_get_focus_inactive(seat, &root->node);
|
||||||
|
}
|
||||||
|
|
||||||
config->handler_context.seat = seat;
|
config->handler_context.seat = seat;
|
||||||
|
|
||||||
head = exec;
|
head = exec;
|
||||||
@ -318,9 +328,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!config->handler_context.using_criteria) {
|
if (!config->handler_context.using_criteria) {
|
||||||
// without criteria, the command acts upon the focused
|
set_config_node(node);
|
||||||
// container
|
|
||||||
set_config_node(seat_get_focus_inactive(seat, &root->node));
|
|
||||||
struct cmd_results *res = handler->handle(argc-1, argv+1);
|
struct cmd_results *res = handler->handle(argc-1, argv+1);
|
||||||
if (res->status != CMD_SUCCESS) {
|
if (res->status != CMD_SUCCESS) {
|
||||||
free_argv(argc, argv);
|
free_argv(argc, argv);
|
||||||
|
@ -321,7 +321,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
|
|||||||
}
|
}
|
||||||
|
|
||||||
config->handler_context.seat = seat;
|
config->handler_context.seat = seat;
|
||||||
struct cmd_results *results = execute_command(binding->command, NULL);
|
struct cmd_results *results = execute_command(binding->command, NULL, NULL);
|
||||||
if (results->status == CMD_SUCCESS) {
|
if (results->status == CMD_SUCCESS) {
|
||||||
ipc_event_binding(binding_copy);
|
ipc_event_binding(binding_copy);
|
||||||
} else {
|
} else {
|
||||||
|
@ -401,7 +401,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||||||
} else {
|
} else {
|
||||||
if (view->container->parent) {
|
if (view->container->parent) {
|
||||||
arrange_container(view->container->parent);
|
arrange_container(view->container->parent);
|
||||||
} else {
|
} else if (view->container->workspace) {
|
||||||
arrange_workspace(view->container->workspace);
|
arrange_workspace(view->container->workspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||||||
} else {
|
} else {
|
||||||
if (view->container->parent) {
|
if (view->container->parent) {
|
||||||
arrange_container(view->container->parent);
|
arrange_container(view->container->parent);
|
||||||
} else {
|
} else if (view->container->workspace) {
|
||||||
arrange_workspace(view->container->workspace);
|
arrange_workspace(view->container->workspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +394,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
|||||||
} else {
|
} else {
|
||||||
if (view->container->parent) {
|
if (view->container->parent) {
|
||||||
arrange_container(view->container->parent);
|
arrange_container(view->container->parent);
|
||||||
} else {
|
} else if (view->container->workspace) {
|
||||||
arrange_workspace(view->container->workspace);
|
arrange_workspace(view->container->workspace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -580,7 +580,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
|
|||||||
switch (client->current_command) {
|
switch (client->current_command) {
|
||||||
case IPC_COMMAND:
|
case IPC_COMMAND:
|
||||||
{
|
{
|
||||||
struct cmd_results *results = execute_command(buf, NULL);
|
struct cmd_results *results = execute_command(buf, NULL, NULL);
|
||||||
transaction_commit_dirty();
|
transaction_commit_dirty();
|
||||||
char *json = cmd_results_to_json(results);
|
char *json = cmd_results_to_json(results);
|
||||||
int length = strlen(json);
|
int length = strlen(json);
|
||||||
|
@ -429,7 +429,7 @@ int main(int argc, char **argv) {
|
|||||||
wlr_log(WLR_DEBUG, "Running deferred commands");
|
wlr_log(WLR_DEBUG, "Running deferred commands");
|
||||||
while (config->cmd_queue->length) {
|
while (config->cmd_queue->length) {
|
||||||
char *line = config->cmd_queue->items[0];
|
char *line = config->cmd_queue->items[0];
|
||||||
struct cmd_results *res = execute_command(line, NULL);
|
struct cmd_results *res = execute_command(line, NULL, NULL);
|
||||||
if (res->status != CMD_SUCCESS) {
|
if (res->status != CMD_SUCCESS) {
|
||||||
wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
|
wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
|
||||||
}
|
}
|
||||||
|
@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void view_execute_criteria(struct sway_view *view) {
|
void view_execute_criteria(struct sway_view *view) {
|
||||||
struct sway_seat *seat = input_manager_current_seat(input_manager);
|
|
||||||
struct sway_node *prior_focus = seat_get_focus(seat);
|
|
||||||
list_t *criterias = criteria_for_view(view, CT_COMMAND);
|
list_t *criterias = criteria_for_view(view, CT_COMMAND);
|
||||||
for (int i = 0; i < criterias->length; i++) {
|
for (int i = 0; i < criterias->length; i++) {
|
||||||
struct criteria *criteria = criterias->items[i];
|
struct criteria *criteria = criterias->items[i];
|
||||||
@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) {
|
|||||||
}
|
}
|
||||||
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||||
criteria->raw, view, criteria->cmdlist);
|
criteria->raw, view, criteria->cmdlist);
|
||||||
seat_set_focus_container(seat, view->container);
|
|
||||||
list_add(view->executed_criteria, criteria);
|
list_add(view->executed_criteria, criteria);
|
||||||
struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
|
struct cmd_results *res = execute_command(
|
||||||
if (res->status != CMD_SUCCESS) {
|
criteria->cmdlist, NULL, view->container);
|
||||||
wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error);
|
|
||||||
}
|
|
||||||
free_cmd_results(res);
|
free_cmd_results(res);
|
||||||
}
|
}
|
||||||
list_free(criterias);
|
list_free(criterias);
|
||||||
seat_set_focus(seat, prior_focus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sway_workspace *select_workspace(struct sway_view *view) {
|
static struct sway_workspace *select_workspace(struct sway_view *view) {
|
||||||
|
Loading…
Reference in New Issue
Block a user