diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands.c | 61 | ||||
-rw-r--r-- | sway/commands/create_output.c | 4 | ||||
-rw-r--r-- | sway/commands/workspace.c | 13 | ||||
-rw-r--r-- | sway/commands/ws_auto_back_and_forth.c | 2 | ||||
-rw-r--r-- | sway/desktop/output.c | 9 | ||||
-rw-r--r-- | sway/ipc-json.c | 22 | ||||
-rw-r--r-- | sway/sway.5.scd | 8 | ||||
-rw-r--r-- | sway/tree/output.c | 7 | ||||
-rw-r--r-- | sway/tree/workspace.c | 61 |
9 files changed, 136 insertions, 51 deletions
diff --git a/sway/commands.c b/sway/commands.c index 37c7169a..4b86c2fa 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -353,12 +353,14 @@ struct cmd_results *config_command(char *exec) { struct cmd_results *results = NULL; int argc; char **argv = split_args(exec, &argc); + + // Check for empty lines if (!argc) { results = cmd_results_new(CMD_SUCCESS, NULL, NULL); goto cleanup; } - // Start block + // Check for the start of a block if (argc > 1 && strcmp(argv[argc - 1], "{") == 0) { char *block = join_args(argv, argc - 1); results = cmd_results_new(CMD_BLOCK, block, NULL); @@ -366,22 +368,54 @@ struct cmd_results *config_command(char *exec) { goto cleanup; } - // Endblock + // Check for the end of a block if (strcmp(argv[argc - 1], "}") == 0) { results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); goto cleanup; } - wlr_log(WLR_INFO, "handling config command '%s'", exec); + + // Make sure the command is not stored in a variable + if (*argv[0] == '$') { + argv[0] = do_var_replacement(argv[0]); + char *temp = join_args(argv, argc); + free_argv(argc, argv); + argv = split_args(temp, &argc); + free(temp); + if (!argc) { + results = cmd_results_new(CMD_SUCCESS, NULL, NULL); + goto cleanup; + } + } + + // Determine the command handler + wlr_log(WLR_INFO, "Config command: %s", exec); struct cmd_handler *handler = find_handler(argv[0], NULL, 0); - if (!handler) { + if (!handler || !handler->handle) { char *input = argv[0] ? argv[0] : "(empty)"; - results = cmd_results_new(CMD_INVALID, input, "Unknown/invalid command"); + char *error = handler + ? "This command is shimmed, but unimplemented" + : "Unknown/invalid command"; + results = cmd_results_new(CMD_INVALID, input, error); goto cleanup; } - int i; - // Var replacement, for all but first argument of set - // TODO commands - for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { + + // Do variable replacement + if (handler->handle == cmd_set && argc > 1 && *argv[1] == '$') { + // Escape the variable name so it does not get replaced by one shorter + char *temp = calloc(1, strlen(argv[1]) + 2); + temp[0] = '$'; + strcpy(&temp[1], argv[1]); + free(argv[1]); + argv[1] = temp; + } + char *command = do_var_replacement(join_args(argv, argc)); + wlr_log(WLR_INFO, "After replacement: %s", command); + free_argv(argc, argv); + argv = split_args(command, &argc); + free(command); + + // Strip quotes and unescape the string + for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) { if (handler->handle != cmd_exec && handler->handle != cmd_exec_always && handler->handle != cmd_bindsym && handler->handle != cmd_bindcode @@ -389,14 +423,11 @@ struct cmd_results *config_command(char *exec) { && (*argv[i] == '\"' || *argv[i] == '\'')) { strip_quotes(argv[i]); } - argv[i] = do_var_replacement(argv[i]); unescape_string(argv[i]); } - if (handler->handle) { - results = handler->handle(argc-1, argv+1); - } else { - results = cmd_results_new(CMD_INVALID, argv[0], "This command is shimmed, but unimplemented"); - } + + // Run command + results = handler->handle(argc - 1, argv + 1); cleanup: free_argv(argc, argv); diff --git a/sway/commands/create_output.c b/sway/commands/create_output.c index 1c2464ea..3f870acb 100644 --- a/sway/commands/create_output.c +++ b/sway/commands/create_output.c @@ -1,7 +1,7 @@ #include <wlr/config.h> #include <wlr/backend/multi.h> #include <wlr/backend/wayland.h> -#ifdef WLR_HAS_X11_BACKEND +#if WLR_HAS_X11_BACKEND #include <wlr/backend/x11.h> #endif #include "sway/commands.h" @@ -18,7 +18,7 @@ static void create_output(struct wlr_backend *backend, void *data) { wlr_wl_output_create(backend); *done = true; } -#ifdef WLR_HAS_X11_BACKEND +#if WLR_HAS_X11_BACKEND else if (wlr_backend_is_x11(backend)) { wlr_x11_output_create(backend); *done = true; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 168494d2..92118ecf 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -21,6 +21,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { return NULL; } wsc->workspace = strdup(ws_name); + wsc->outputs = create_list(); wsc->gaps_inner = INT_MIN; wsc->gaps_outer.top = INT_MIN; wsc->gaps_outer.right = INT_MIN; @@ -32,7 +33,7 @@ static struct workspace_config *workspace_config_find_or_create(char *ws_name) { void free_workspace_config(struct workspace_config *wsc) { free(wsc->workspace); - free(wsc->output); + free_flat_list(wsc->outputs); free(wsc); } @@ -141,18 +142,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } } if (output_location >= 0) { - if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { + if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, + output_location + 2))) { return error; } - char *ws_name = join_args(argv, argc - 2); + char *ws_name = join_args(argv, output_location); struct workspace_config *wsc = workspace_config_find_or_create(ws_name); free(ws_name); if (!wsc) { return cmd_results_new(CMD_FAILURE, "workspace output", "Unable to allocate workspace output"); } - free(wsc->output); - wsc->output = strdup(argv[output_location + 1]); + for (int i = output_location + 1; i < argc; ++i) { + list_add(wsc->outputs, strdup(argv[i])); + } } else if (gaps_location >= 0) { if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { return error; diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c index 3449d4cc..adb851c2 100644 --- a/sway/commands/ws_auto_back_and_forth.c +++ b/sway/commands/ws_auto_back_and_forth.c @@ -9,6 +9,6 @@ struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { return error; } config->auto_back_and_forth = - !parse_boolean(argv[0], config->auto_back_and_forth); + parse_boolean(argv[0], config->auto_back_and_forth); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/desktop/output.c b/sway/desktop/output.c index d48ddef3..c53a9c73 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -469,15 +469,6 @@ void output_damage_box(struct sway_output *output, struct wlr_box *_box) { wlr_output_damage_add_box(output->damage, &box); } -static void output_damage_whole_container_iterator(struct sway_container *con, - void *data) { - if (!sway_assert(con->view, "expected a view")) { - return; - } - struct sway_output *output = data; - output_damage_view(output, con->view, true); -} - void output_damage_whole_container(struct sway_output *output, struct sway_container *con) { // Pad the box by 1px, because the width is a double and might be a fraction diff --git a/sway/ipc-json.c b/sway/ipc-json.c index 4583558c..4d9a87d8 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -12,6 +12,7 @@ #include "sway/input/seat.h" #include <wlr/types/wlr_box.h> #include <wlr/types/wlr_output.h> +#include <xkbcommon/xkbcommon.h> #include "wlr-layer-shell-unstable-v1-protocol.h" static const char *ipc_json_layout_description(enum sway_container_layout l) { @@ -503,6 +504,27 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) { json_object_object_add(object, "type", json_object_new_string(describe_device_type(device))); + if (device->wlr_device->type == WLR_INPUT_DEVICE_KEYBOARD) { + struct wlr_keyboard *keyboard = device->wlr_device->keyboard; + struct xkb_keymap *keymap = keyboard->keymap; + struct xkb_state *state = keyboard->xkb_state; + xkb_layout_index_t num_layouts = xkb_keymap_num_layouts(keymap); + xkb_layout_index_t layout_idx; + for (layout_idx = 0; layout_idx < num_layouts; layout_idx++) { + bool is_active = + xkb_state_layout_index_is_active(state, + layout_idx, + XKB_STATE_LAYOUT_EFFECTIVE); + if (is_active) { + const char *layout = + xkb_keymap_layout_get_name(keymap, layout_idx); + json_object_object_add(object, "xkb_active_layout_name", + json_object_new_string(layout)); + break; + } + } + } + return object; } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 8f6b35f1..1a11015f 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -573,8 +573,12 @@ The default colors are: Specifies that workspace _name_ should have the given gaps settings when it is created. -*workspace* <name> output <output> - Specifies that workspace _name_ should be shown on the specified _output_. +*workspace* <name> output <outputs...> + Specifies that workspace _name_ should be shown on the specified _outputs_. + Multiple outputs can be listed and the first available will be used. If the + workspace gets placed on an output further down the list and an output that + is higher on the list becomes available, the workspace will be move to the + higher priority output. *workspace\_auto\_back\_and\_forth* yes|no When _yes_, repeating a workspace switch command will switch back to the diff --git a/sway/tree/output.c b/sway/tree/output.c index 2704920d..3c4614a8 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -31,6 +31,13 @@ static void restore_workspaces(struct sway_output *output) { j--; } } + + if (other->workspaces->length == 0) { + char *next = workspace_next_name(other->wlr_output->name); + struct sway_workspace *ws = workspace_create(other, next); + free(next); + ipc_event_workspace(NULL, ws, "init"); + } } // Saved workspaces diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 93ce50de..4be63311 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -33,14 +33,15 @@ struct workspace_config *workspace_find_config(const char *ws_name) { struct sway_output *workspace_get_initial_output(const char *name) { // Check workspace configs for a workspace<->output pair struct workspace_config *wsc = workspace_find_config(name); - if (wsc && wsc->output) { - struct sway_output *output = output_by_name(wsc->output); - if (!output) { - output = output_by_identifier(wsc->output); - } - - if (output) { - return output; + if (wsc) { + for (int i = 0; i < wsc->outputs->length; i++) { + struct sway_output *output = output_by_name(wsc->outputs->items[i]); + if (!output) { + output = output_by_identifier(wsc->outputs->items[i]); + } + if (output) { + return output; + } } } // Otherwise put it on the focused output @@ -85,7 +86,6 @@ struct sway_workspace *workspace_create(struct sway_output *output, ws->floating = create_list(); ws->tiling = create_list(); ws->output_priority = create_list(); - workspace_output_add_priority(ws, output); ws->gaps_outer = config->gaps_outer; ws->gaps_inner = config->gaps_inner; @@ -110,9 +110,17 @@ struct sway_workspace *workspace_create(struct sway_output *output, // Since default outer gaps can be smaller than the negation of // workspace specific inner gaps, check outer gaps again prevent_invalid_outer_gaps(ws); + + // Add output priorities + for (int i = 0; i < wsc->outputs->length; ++i) { + list_add(ws->output_priority, strdup(wsc->outputs->items[i])); + } } } + // If not already added, add the output to the lowest priority + workspace_output_add_priority(ws, output); + output_add_workspace(output, ws); output_sort_workspaces(output); @@ -134,8 +142,7 @@ void workspace_destroy(struct sway_workspace *workspace) { free(workspace->name); free(workspace->representation); - list_foreach(workspace->output_priority, free); - list_free(workspace->output_priority); + free_flat_list(workspace->output_priority); list_free(workspace->floating); list_free(workspace->tiling); list_free(workspace->current.floating); @@ -177,8 +184,19 @@ static bool workspace_valid_on_output(const char *output_name, char identifier[128]; struct sway_output *output = output_by_name(output_name); output_get_identifier(identifier, sizeof(identifier), output); - - return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0 || strcasecmp(identifier, output_name) == 0; + + if (!wsc) { + return true; + } + + for (int i = 0; i < wsc->outputs->length; i++) { + if (strcmp(wsc->outputs->items[i], output_name) == 0 || + strcmp(wsc->outputs->items[i], identifier) == 0) { + return true; + } + } + + return false; } static void workspace_name_from_binding(const struct sway_binding * binding, @@ -281,10 +299,19 @@ char *workspace_next_name(const char *output_name) { for (int i = 0; i < config->workspace_configs->length; ++i) { // Unlike with bindings, this does not guarantee order const struct workspace_config *wsc = config->workspace_configs->items[i]; - if (wsc->output && strcmp(wsc->output, output_name) == 0 - && workspace_by_name(wsc->workspace) == NULL) { - free(target); - target = strdup(wsc->workspace); + if (workspace_by_name(wsc->workspace)) { + continue; + } + bool found = false; + for (int j = 0; j < wsc->outputs->length; ++j) { + if (strcmp(wsc->outputs->items[j], output_name) == 0) { + found = true; + free(target); + target = strdup(wsc->workspace); + break; + } + } + if (found) { break; } } |