diff options
Diffstat (limited to 'sway/commands.c')
-rw-r--r-- | sway/commands.c | 108 |
1 files changed, 80 insertions, 28 deletions
diff --git a/sway/commands.c b/sway/commands.c index 0d4aa104..b52eb200 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -125,23 +125,42 @@ struct cmd_results *add_color(const char *name, char *buffer, const char *color) return NULL; } -/* Keep alphabetized */ +/** + * handlers that can run in either config or command context + * Keep alphabetized + */ static struct cmd_handler handlers[] = { { "bindcode", cmd_bindcode }, { "bindsym", cmd_bindsym }, { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, - { "exit", cmd_exit }, { "include", cmd_include }, { "input", cmd_input }, - { "kill", cmd_kill }, { "output", cmd_output }, - { "reload", cmd_reload }, { "seat", cmd_seat }, - { "set", cmd_set }, { "workspace", cmd_workspace }, }; +/** + * Commands that can *only* run in the config loading context + * Keep alphabetized + */ +static struct cmd_handler config_handlers[] = { + { "set", cmd_set }, +}; + +/** + * Commands that can *not* run in the config loading context + * Keep alphabetized + */ +static struct cmd_handler command_handlers[] = { + { "exit", cmd_exit }, + { "focus", cmd_focus }, + { "kill", cmd_kill }, + { "layout", cmd_layout }, + { "reload", cmd_reload }, +}; + static int handler_compare(const void *_a, const void *_b) { const struct cmd_handler *a = _a; const struct cmd_handler *b = _b; @@ -179,24 +198,48 @@ static struct cmd_handler *find_handler(char *line, enum cmd_status block) { struct cmd_handler *res = NULL; wlr_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); + bool config_loading = config->reading || !config->active; + if (block == CMD_BLOCK_INPUT) { - res = bsearch(&d, input_handlers, + // input commands can run in either context + return bsearch(&d, input_handlers, sizeof(input_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); } else if (block == CMD_BLOCK_SEAT) { - res = bsearch(&d, seat_handlers, + // seat commands can run in either context + return bsearch(&d, seat_handlers, sizeof(seat_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); - } else { - res = bsearch(&d, handlers, - sizeof(handlers) / sizeof(struct cmd_handler), + } + + if (!config_loading) { + res = bsearch(&d, command_handlers, + sizeof(command_handlers) / sizeof(struct cmd_handler), sizeof(struct cmd_handler), handler_compare); + + if (res) { + return res; + } + } + + if (config->reading) { + res = bsearch(&d, config_handlers, + sizeof(config_handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + + if (res) { + return res; + } } + res = bsearch(&d, handlers, + sizeof(handlers) / sizeof(struct cmd_handler), + sizeof(struct cmd_handler), handler_compare); + return res; } -struct cmd_results *handle_command(char *_exec) { +struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) { // 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 // error string we could e.g. concatenate all errors there.) @@ -207,6 +250,16 @@ struct cmd_results *handle_command(char *_exec) { char *cmd; list_t *containers = NULL; + if (seat == NULL) { + // passing a NULL seat means we just pick the default seat + seat = sway_input_manager_get_default_seat(input_manager); + if (!sway_assert(seat, "could not find a seat to run the command on")) { + return NULL; + } + } + + config->handler_context.seat = seat; + head = exec; do { // Extract criteria (valid for this command list only). @@ -276,23 +329,22 @@ struct cmd_results *handle_command(char *_exec) { if (!has_criteria) { // without criteria, the command acts upon the focused // container - struct sway_seat *seat = config->handler_context.seat; - if (!seat) { - seat = sway_input_manager_get_default_seat(input_manager); + config->handler_context.current_container = + sway_seat_get_focus_inactive(seat, &root_container); + if (!sway_assert(config->handler_context.current_container, + "could not get focus-inactive for root container")) { + return NULL; } - if (seat) { - config->handler_context.current_container = seat->focus; - struct cmd_results *res = handler->handle(argc-1, argv+1); - if (res->status != CMD_SUCCESS) { - free_argv(argc, argv); - if (results) { - free_cmd_results(results); - } - results = res; - goto cleanup; + struct cmd_results *res = handler->handle(argc-1, argv+1); + if (res->status != CMD_SUCCESS) { + free_argv(argc, argv); + if (results) { + free_cmd_results(results); } - free_cmd_results(res); + results = res; + goto cleanup; } + free_cmd_results(res); } else { for (int i = 0; i < containers->length; ++i) { config->handler_context.current_container = containers->items[i]; @@ -319,13 +371,13 @@ cleanup: return results; } -// this is like handle_command above, except: +// this is like execute_command above, except: // 1) it ignores empty commands (empty lines) // 2) it does variable substitution // 3) it doesn't split commands (because the multiple commands are supposed to // be chained together) -// 4) handle_command handles all state internally while config_command has some -// state handled outside (notably the block mode, in read_config) +// 4) execute_command handles all state internally while config_command has +// some state handled outside (notably the block mode, in read_config) struct cmd_results *config_command(char *exec, enum cmd_status block) { struct cmd_results *results = NULL; int argc; |