diff options
Diffstat (limited to 'sway/commands')
-rw-r--r-- | sway/commands/bar/binding_mode_indicator.c | 6 | ||||
-rw-r--r-- | sway/commands/gaps.c | 306 | ||||
-rw-r--r-- | sway/commands/hide_edge_borders.c | 16 | ||||
-rw-r--r-- | sway/commands/input.c | 1 | ||||
-rw-r--r-- | sway/commands/input/drag.c | 26 | ||||
-rw-r--r-- | sway/commands/layout.c | 3 | ||||
-rw-r--r-- | sway/commands/output/background.c | 18 | ||||
-rw-r--r-- | sway/commands/resize.c | 30 | ||||
-rw-r--r-- | sway/commands/smart_borders.c | 25 | ||||
-rw-r--r-- | sway/commands/workspace.c | 74 |
10 files changed, 305 insertions, 200 deletions
diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c index 0c48bee9..f18b8d7c 100644 --- a/sway/commands/bar/binding_mode_indicator.c +++ b/sway/commands/bar/binding_mode_indicator.c @@ -21,7 +21,9 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { config->current_bar->binding_mode_indicator = false; wlr_log(WLR_DEBUG, "Disabling binding mode indicator on bar: %s", config->current_bar->id); + } else { + return cmd_results_new(CMD_INVALID, "binding_mode_indicator", + "Invalid value %s", argv[0]); } - return cmd_results_new(CMD_INVALID, "binding_mode_indicator", - "Invalid value %s", argv[0]); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index d676e475..2e0876a9 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -1,4 +1,5 @@ #include <string.h> +#include <strings.h> #include "sway/commands.h" #include "sway/config.h" #include "sway/tree/arrange.h" @@ -13,172 +14,173 @@ enum gaps_op { GAPS_OP_SUBTRACT }; -enum gaps_scope { - GAPS_SCOPE_ALL, - GAPS_SCOPE_WORKSPACE, - GAPS_SCOPE_CURRENT +struct gaps_data { + bool inner; + enum gaps_op operation; + int amount; }; -struct cmd_results *cmd_gaps(int argc, char **argv) { - struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 1); - if (error) { +// gaps edge_gaps on|off|toggle +static struct cmd_results *gaps_edge_gaps(int argc, char **argv) { + struct cmd_results *error; + if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) { return error; } - if (strcmp(argv[0], "edge_gaps") == 0) { - if ((error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2))) { - return error; - } - - if (strcmp(argv[1], "on") == 0) { - config->edge_gaps = true; - } else if (strcmp(argv[1], "off") == 0) { - config->edge_gaps = false; - } else if (strcmp(argv[1], "toggle") == 0) { - if (!config->active) { - return cmd_results_new(CMD_INVALID, "gaps", - "Cannot toggle gaps while not running."); - } - config->edge_gaps = !config->edge_gaps; - } else { + if (strcmp(argv[1], "on") == 0) { + config->edge_gaps = true; + } else if (strcmp(argv[1], "off") == 0) { + config->edge_gaps = false; + } else if (strcmp(argv[1], "toggle") == 0) { + if (!config->active) { return cmd_results_new(CMD_INVALID, "gaps", - "gaps edge_gaps on|off|toggle"); + "Cannot toggle gaps while not running."); } - arrange_root(); + config->edge_gaps = !config->edge_gaps; } else { - int amount_idx = 0; // the current index in argv - enum gaps_op op = GAPS_OP_SET; - enum gaps_scope scope = GAPS_SCOPE_ALL; - bool inner = true; - - if (strcmp(argv[0], "inner") == 0) { - amount_idx++; - inner = true; - } else if (strcmp(argv[0], "outer") == 0) { - amount_idx++; - inner = false; - } + return cmd_results_new(CMD_INVALID, "gaps", + "gaps edge_gaps on|off|toggle"); + } + arrange_root(); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} - // If one of the long variants of the gaps command is used - // (which starts with inner|outer) check the number of args - if (amount_idx > 0) { // if we've seen inner|outer - if (argc > 2) { // check the longest variant - error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); - if (error) { - return error; - } - } else { // check the next longest format - error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); - if (error) { - return error; - } - } - } else { - error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 1); - if (error) { - return error; - } - } +// gaps inner|outer <px> +static struct cmd_results *gaps_set_defaults(int argc, char **argv) { + struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 2); + if (error) { + return error; + } - if (argc == 4) { - // Long format: all|workspace|current. - if (strcmp(argv[amount_idx], "all") == 0) { - amount_idx++; - scope = GAPS_SCOPE_ALL; - } else if (strcmp(argv[amount_idx], "workspace") == 0) { - amount_idx++; - scope = GAPS_SCOPE_WORKSPACE; - } else if (strcmp(argv[amount_idx], "current") == 0) { - amount_idx++; - scope = GAPS_SCOPE_CURRENT; - } - - // Long format: set|plus|minus - if (strcmp(argv[amount_idx], "set") == 0) { - amount_idx++; - op = GAPS_OP_SET; - } else if (strcmp(argv[amount_idx], "plus") == 0) { - amount_idx++; - op = GAPS_OP_ADD; - } else if (strcmp(argv[amount_idx], "minus") == 0) { - amount_idx++; - op = GAPS_OP_SUBTRACT; - } - } + bool inner; + if (strcasecmp(argv[0], "inner") == 0) { + inner = true; + } else if (strcasecmp(argv[0], "outer") == 0) { + inner = false; + } else { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer <px>'"); + } - char *end; - double val = strtod(argv[amount_idx], &end); - - if (strlen(end) && val == 0.0) { // invalid <amount> - // guess which variant of the command was attempted - if (argc == 1) { - return cmd_results_new(CMD_INVALID, "gaps", "gaps <amount>"); - } - if (argc == 2) { - return cmd_results_new(CMD_INVALID, "gaps", - "gaps inner|outer <amount>"); - } - return cmd_results_new(CMD_INVALID, "gaps", - "gaps inner|outer all|workspace|current set|plus|minus <amount>"); - } + char *end; + int amount = strtol(argv[1], &end, 10); + if (strlen(end) && strcasecmp(end, "px") != 0) { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer <px>'"); + } + if (amount < 0) { + amount = 0; + } - if (amount_idx == 0) { // gaps <amount> - config->gaps_inner = val; - config->gaps_outer = val; - arrange_root(); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - // Other variants. The middle-length variant (gaps inner|outer <amount>) - // just defaults the scope to "all" and defaults the op to "set". - - double total; - switch (op) { - case GAPS_OP_SUBTRACT: { - total = (inner ? config->gaps_inner : config->gaps_outer) - val; - if (total < 0) { - total = 0; - } - break; - } - case GAPS_OP_ADD: { - total = (inner ? config->gaps_inner : config->gaps_outer) + val; - break; - } - case GAPS_OP_SET: { - total = val; - break; - } - } + if (inner) { + config->gaps_inner = amount; + } else { + config->gaps_outer = amount; + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} - if (scope == GAPS_SCOPE_ALL) { - if (inner) { - config->gaps_inner = total; - } else { - config->gaps_outer = total; - } - arrange_root(); - } else { - if (scope == GAPS_SCOPE_WORKSPACE) { - struct sway_workspace *ws = config->handler_context.workspace; - ws->has_gaps = true; - if (inner) { - ws->gaps_inner = total; - } else { - ws->gaps_outer = total; - } - arrange_workspace(ws); - } else { - struct sway_container *c = config->handler_context.container; - c->has_gaps = true; - if (inner) { - c->gaps_inner = total; - } else { - c->gaps_outer = total; - } - arrange_workspace(c->workspace); - } - } +static void configure_gaps(struct sway_workspace *ws, void *_data) { + struct gaps_data *data = _data; + int *prop = data->inner ? &ws->gaps_inner : &ws->gaps_outer; + + switch (data->operation) { + case GAPS_OP_SET: + *prop = data->amount; + break; + case GAPS_OP_ADD: + *prop += data->amount; + break; + case GAPS_OP_SUBTRACT: + *prop -= data->amount; + break; + } + if (*prop < 0) { + *prop = 0; + } + arrange_workspace(ws); +} + +// gaps inner|outer current|all set|plus|minus <px> +static struct cmd_results *gaps_set_runtime(int argc, char **argv) { + struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_EQUAL_TO, 4); + if (error) { + return error; + } + + struct gaps_data data; + + if (strcasecmp(argv[0], "inner") == 0) { + data.inner = true; + } else if (strcasecmp(argv[0], "outer") == 0) { + data.inner = false; + } else { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + } + + bool all; + if (strcasecmp(argv[1], "current") == 0) { + all = false; + } else if (strcasecmp(argv[1], "all") == 0) { + all = true; + } else { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + } + + if (strcasecmp(argv[2], "set") == 0) { + data.operation = GAPS_OP_SET; + } else if (strcasecmp(argv[2], "plus") == 0) { + data.operation = GAPS_OP_ADD; + } else if (strcasecmp(argv[2], "minus") == 0) { + data.operation = GAPS_OP_SUBTRACT; + } else { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + } + + char *end; + data.amount = strtol(argv[3], &end, 10); + if (strlen(end) && strcasecmp(end, "px") != 0) { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + } + + if (all) { + root_for_each_workspace(configure_gaps, &data); + } else { + configure_gaps(config->handler_context.workspace, &data); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } + +// gaps edge_gaps on|off|toggle +// gaps inner|outer <px> - sets defaults for workspaces +// gaps inner|outer current|all set|plus|minus <px> - runtime only +struct cmd_results *cmd_gaps(int argc, char **argv) { + struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); + if (error) { + return error; + } + + if (strcmp(argv[0], "edge_gaps") == 0) { + return gaps_edge_gaps(argc, argv); + } + + if (argc == 2) { + return gaps_set_defaults(argc, argv); + } + if (argc == 4) { + if (config->active) { + return gaps_set_runtime(argc, argv); + } else { + return cmd_results_new(CMD_INVALID, "gaps", + "This syntax can only be used when sway is running"); + } + } + return cmd_results_new(CMD_INVALID, "gaps", + "Expected 'gaps inner|outer <px>' or " + "'gaps inner|outer current|all set|plus|minus <px>'"); +} diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c index 0a5c7f28..ea261fb1 100644 --- a/sway/commands/hide_edge_borders.c +++ b/sway/commands/hide_edge_borders.c @@ -1,15 +1,8 @@ #include "sway/commands.h" #include "sway/config.h" -#include "sway/tree/container.h" -#include "sway/tree/root.h" +#include "sway/tree/arrange.h" #include "sway/tree/view.h" -static void _configure_view(struct sway_container *con, void *data) { - if (con->view) { - view_autoconfigure(con->view); - } -} - struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "hide_edge_borders", EXPECTED_EQUAL_TO, 1))) { @@ -26,13 +19,16 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) { config->hide_edge_borders = E_BOTH; } else if (strcmp(argv[0], "smart") == 0) { config->hide_edge_borders = E_SMART; + } else if (strcmp(argv[0], "smart_no_gaps") == 0) { + config->hide_edge_borders = E_SMART_NO_GAPS; } else { return cmd_results_new(CMD_INVALID, "hide_edge_borders", "Expected 'hide_edge_borders " - "<none|vertical|horizontal|both|smart>'"); + "<none|vertical|horizontal|both|smart|smart_no_gaps>'"); } + config->saved_edge_borders = config->hide_edge_borders; - root_for_each_container(_configure_view, NULL); + arrange_root(); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input.c b/sway/commands/input.c index 9091da2a..2889d47d 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -9,6 +9,7 @@ static struct cmd_handler input_handlers[] = { { "accel_profile", input_cmd_accel_profile }, { "click_method", input_cmd_click_method }, + { "drag", input_cmd_drag }, { "drag_lock", input_cmd_drag_lock }, { "dwt", input_cmd_dwt }, { "events", input_cmd_events }, diff --git a/sway/commands/input/drag.c b/sway/commands/input/drag.c new file mode 100644 index 00000000..e325df29 --- /dev/null +++ b/sway/commands/input/drag.c @@ -0,0 +1,26 @@ +#include <string.h> +#include <strings.h> +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "util.h" + +struct cmd_results *input_cmd_drag(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "drag", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct input_config *ic = config->handler_context.input_config; + if (!ic) { + return cmd_results_new(CMD_FAILURE, + "drag", "No input device defined."); + } + + if (parse_boolean(argv[0], true)) { + ic->drag = LIBINPUT_CONFIG_DRAG_ENABLED; + } else { + ic->drag = LIBINPUT_CONFIG_DRAG_DISABLED; + } + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ef3ec1cb..c2ce2e78 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -138,15 +138,14 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } container->layout = new_layout; container_update_representation(container); - arrange_container(container); } else { if (old_layout != L_TABBED && old_layout != L_STACKED) { workspace->prev_split_layout = old_layout; } workspace->layout = new_layout; workspace_update_representation(workspace); - arrange_workspace(workspace); } + arrange_workspace(workspace); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index 9e370d43..30fb47c4 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c @@ -123,19 +123,13 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { } free(src); } else { - // Escape spaces and quotes in the final path for swaybg + // Escape double quotes in the final path for swaybg for (size_t i = 0; i < strlen(src); i++) { - switch (src[i]) { - case ' ': - case '\'': - case '\"': - src = realloc(src, strlen(src) + 2); - memmove(src + i + 1, src + i, strlen(src + i) + 1); - *(src + i) = '\\'; - i++; - break; - default: - break; + if (src[i] == '"') { + src = realloc(src, strlen(src) + 2); + memmove(src + i + 1, src + i, strlen(src + i) + 1); + *(src + i) = '\\'; + i++; } } diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 99e9dbda..1343b165 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -179,11 +179,11 @@ static void container_recursive_resize(struct sway_container *container, } } -static void resize_tiled(struct sway_container *parent, int amount, +static bool resize_tiled(struct sway_container *parent, int amount, enum resize_axis axis) { struct sway_container *focused = parent; if (!parent) { - return; + return false; } enum sway_container_layout parallel_layout = @@ -216,7 +216,7 @@ static void resize_tiled(struct sway_container *parent, int amount, } if (!parent) { // Can't resize in this direction - return; + return false; } // Implement up/down/left/right direction by zeroing one of the weights, @@ -248,22 +248,22 @@ static void resize_tiled(struct sway_container *parent, int amount, if (sibling_pos < parent_pos && minor_weight) { double pixels = -amount / minor_weight; if (major_weight && (sibling_size + pixels / 2) < min_sane) { - return; // Too small + return false; // Too small } else if (!major_weight && sibling_size + pixels < min_sane) { - return; // Too small + return false; // Too small } } else if (sibling_pos > parent_pos && major_weight) { double pixels = -amount / major_weight; if (minor_weight && (sibling_size + pixels / 2) < min_sane) { - return; // Too small + return false; // Too small } else if (!minor_weight && sibling_size + pixels < min_sane) { - return; // Too small + return false; // Too small } } } else { double pixels = amount; if (parent_size + pixels < min_sane) { - return; // Too small + return false; // Too small } } } @@ -317,9 +317,10 @@ static void resize_tiled(struct sway_container *parent, int amount, } else { arrange_workspace(parent->workspace); } + return true; } -void container_resize_tiled(struct sway_container *parent, +bool container_resize_tiled(struct sway_container *parent, enum wlr_edges edge, int amount) { enum resize_axis axis = RESIZE_AXIS_INVALID; switch (edge) { @@ -338,7 +339,7 @@ void container_resize_tiled(struct sway_container *parent, case WLR_EDGE_NONE: break; } - resize_tiled(parent, amount, axis); + return resize_tiled(parent, amount, axis); } /** @@ -395,6 +396,10 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, case RESIZE_AXIS_INVALID: return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction"); } + if (grow_x == 0 && grow_y == 0) { + return cmd_results_new(CMD_INVALID, "resize", + "Cannot resize any further"); + } con->x += grow_x; con->y += grow_y; con->width += grow_width; @@ -442,7 +447,10 @@ static struct cmd_results *resize_adjust_tiled(enum resize_axis axis, } } - resize_tiled(current, amount->amount, axis); + if (!resize_tiled(current, amount->amount, axis)) { + return cmd_results_new(CMD_INVALID, "resize", + "Cannot resize any further"); + } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/smart_borders.c b/sway/commands/smart_borders.c new file mode 100644 index 00000000..fcb4040e --- /dev/null +++ b/sway/commands/smart_borders.c @@ -0,0 +1,25 @@ +#include "sway/commands.h" +#include "sway/config.h" +#include "sway/tree/arrange.h" +#include "sway/tree/view.h" +#include "util.h" + +struct cmd_results *cmd_smart_borders(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "smart_borders", EXPECTED_EQUAL_TO, 1))) { + return error; + } + + enum edge_border_types saved = config->hide_edge_borders; + if (strcmp(argv[0], "no_gaps") == 0) { + config->hide_edge_borders = E_SMART_NO_GAPS; + } else { + config->hide_edge_borders = parse_boolean(argv[0], true) ? + E_SMART : config->saved_edge_borders; + } + config->saved_edge_borders = saved; + + arrange_root(); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index f026a39d..63f29641 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -10,6 +10,28 @@ #include "log.h" #include "stringop.h" +static struct workspace_config *workspace_config_find_or_create(char *ws_name) { + struct workspace_config *wsc = workspace_find_config(ws_name); + if (wsc) { + return wsc; + } + wsc = calloc(1, sizeof(struct workspace_config)); + if (!wsc) { + return NULL; + } + wsc->workspace = strdup(ws_name); + wsc->gaps_inner = -1; + wsc->gaps_outer = -1; + list_add(config->workspace_configs, wsc); + return wsc; +} + +void free_workspace_config(struct workspace_config *wsc) { + free(wsc->workspace); + free(wsc->output); + free(wsc); +} + struct cmd_results *cmd_workspace(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { @@ -17,6 +39,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } int output_location = -1; + int gaps_location = -1; for (int i = 0; i < argc; ++i) { if (strcasecmp(argv[i], "output") == 0) { @@ -24,25 +47,54 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { break; } } + for (int i = 0; i < argc; ++i) { + if (strcasecmp(argv[i], "gaps") == 0) { + gaps_location = i; + break; + } + } if (output_location >= 0) { if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, output_location + 2))) { return error; } - struct workspace_output *wso = calloc(1, sizeof(struct workspace_output)); - if (!wso) { + char *ws_name = join_args(argv, argc - 2); + 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"); } - wso->workspace = join_args(argv, argc - 2); - wso->output = strdup(argv[output_location + 1]); - int i = -1; - if ((i = list_seq_find(config->workspace_outputs, workspace_output_cmp_workspace, wso)) != -1) { - struct workspace_output *old = config->workspace_outputs->items[i]; - free(old); // workspaces can only be assigned to a single output - list_del(config->workspace_outputs, i); + free(wsc->output); + wsc->output = strdup(argv[output_location + 1]); + } else if (gaps_location >= 0) { + if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) { + return error; + } + char *ws_name = join_args(argv, argc - 3); + struct workspace_config *wsc = workspace_config_find_or_create(ws_name); + free(ws_name); + if (!wsc) { + return cmd_results_new(CMD_FAILURE, "workspace gaps", + "Unable to allocate workspace output"); + } + int *prop = NULL; + if (strcasecmp(argv[gaps_location + 1], "inner") == 0) { + prop = &wsc->gaps_inner; + } else if (strcasecmp(argv[gaps_location + 1], "outer") == 0) { + prop = &wsc->gaps_outer; + } else { + return cmd_results_new(CMD_FAILURE, "workspace gaps", + "Expected 'workspace <ws> gaps inner|outer <px>'"); + } + char *end; + int val = strtol(argv[gaps_location + 2], &end, 10); + + if (strlen(end)) { + free(end); + return cmd_results_new(CMD_FAILURE, "workspace gaps", + "Expected 'workspace <ws> gaps inner|outer <px>'"); } - wlr_log(WLR_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); - list_add(config->workspace_outputs, wso); + *prop = val >= 0 ? val : 0; } else { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); |