diff options
Diffstat (limited to 'sway/commands')
-rw-r--r-- | sway/commands/bar/binding_mode_indicator.c | 12 | ||||
-rw-r--r-- | sway/commands/bar/pango_markup.c | 13 | ||||
-rw-r--r-- | sway/commands/bar/workspace_buttons.c | 12 | ||||
-rw-r--r-- | sway/commands/bar/wrap_scroll.c | 14 | ||||
-rw-r--r-- | sway/commands/border.c | 2 | ||||
-rw-r--r-- | sway/commands/create_output.c | 4 | ||||
-rw-r--r-- | sway/commands/floating.c | 14 | ||||
-rw-r--r-- | sway/commands/focus_follows_mouse.c | 11 | ||||
-rw-r--r-- | sway/commands/gaps.c | 151 | ||||
-rw-r--r-- | sway/commands/input.c | 1 | ||||
-rw-r--r-- | sway/commands/input/pointer_accel.c | 9 | ||||
-rw-r--r-- | sway/commands/input/scroll_factor.c | 32 | ||||
-rw-r--r-- | sway/commands/input/xkb_capslock.c | 10 | ||||
-rw-r--r-- | sway/commands/input/xkb_numlock.c | 10 | ||||
-rw-r--r-- | sway/commands/resize.c | 111 | ||||
-rw-r--r-- | sway/commands/seat/fallback.c | 13 | ||||
-rw-r--r-- | sway/commands/smart_gaps.c | 10 | ||||
-rw-r--r-- | sway/commands/sticky.c | 17 | ||||
-rw-r--r-- | sway/commands/swap.c | 25 | ||||
-rw-r--r-- | sway/commands/workspace.c | 137 | ||||
-rw-r--r-- | sway/commands/ws_auto_back_and_forth.c | 4 |
21 files changed, 377 insertions, 235 deletions
diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c index f18b8d7c..b048b7b9 100644 --- a/sway/commands/bar/binding_mode_indicator.c +++ b/sway/commands/bar/binding_mode_indicator.c @@ -2,6 +2,7 @@ #include <strings.h> #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { struct cmd_results *error = NULL; @@ -13,17 +14,14 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "binding_mode_indicator", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->binding_mode_indicator = true; + config->current_bar->binding_mode_indicator = + parse_boolean(argv[0], config->current_bar->binding_mode_indicator); + if (config->current_bar->binding_mode_indicator) { wlr_log(WLR_DEBUG, "Enabling binding mode indicator on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->binding_mode_indicator = false; + } else { 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_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c index 857571fb..d57cc45c 100644 --- a/sway/commands/bar/pango_markup.c +++ b/sway/commands/bar/pango_markup.c @@ -2,6 +2,7 @@ #include <strings.h> #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { struct cmd_results *error = NULL; @@ -11,18 +12,14 @@ struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) { if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "pango_markup", "No bar defined."); } - if (strcasecmp("enabled", argv[0]) == 0) { - config->current_bar->pango_markup = true; + config->current_bar->pango_markup + = parse_boolean(argv[0], config->current_bar->pango_markup); + if (config->current_bar->pango_markup) { wlr_log(WLR_DEBUG, "Enabling pango markup for bar: %s", config->current_bar->id); - } else if (strcasecmp("disabled", argv[0]) == 0) { - config->current_bar->pango_markup = false; + } else { wlr_log(WLR_DEBUG, "Disabling pango markup for bar: %s", config->current_bar->id); - } else { - error = cmd_results_new(CMD_INVALID, "pango_markup", - "Invalid value %s", argv[0]); - return error; } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c index a4079b2a..cd001e20 100644 --- a/sway/commands/bar/workspace_buttons.c +++ b/sway/commands/bar/workspace_buttons.c @@ -2,6 +2,7 @@ #include <strings.h> #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { struct cmd_results *error = NULL; @@ -12,17 +13,14 @@ struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "workspace_buttons", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->workspace_buttons = true; + config->current_bar->workspace_buttons = + parse_boolean(argv[0], config->current_bar->workspace_buttons); + if (config->current_bar->workspace_buttons) { wlr_log(WLR_DEBUG, "Enabling workspace buttons on bar: %s", config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->workspace_buttons = false; + } else { wlr_log(WLR_DEBUG, "Disabling workspace buttons on bar: %s", config->current_bar->id); - } else { - return cmd_results_new(CMD_INVALID, "workspace_buttons", - "Invalid value %s", argv[0]); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c index 701de00a..04a4e6b8 100644 --- a/sway/commands/bar/wrap_scroll.c +++ b/sway/commands/bar/wrap_scroll.c @@ -2,6 +2,7 @@ #include <strings.h> #include "sway/commands.h" #include "log.h" +#include "util.h" struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { struct cmd_results *error = NULL; @@ -11,17 +12,14 @@ struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) { if (!config->current_bar) { return cmd_results_new(CMD_FAILURE, "wrap_scroll", "No bar defined."); } - if (strcasecmp("yes", argv[0]) == 0) { - config->current_bar->wrap_scroll = true; + config->current_bar->wrap_scroll = + parse_boolean(argv[0], config->current_bar->wrap_scroll); + if (config->current_bar->wrap_scroll) { wlr_log(WLR_DEBUG, "Enabling wrap scroll on bar: %s", - config->current_bar->id); - } else if (strcasecmp("no", argv[0]) == 0) { - config->current_bar->wrap_scroll = false; + config->current_bar->id); + } else { wlr_log(WLR_DEBUG, "Disabling wrap scroll on bar: %s", config->current_bar->id); - } else { - return cmd_results_new(CMD_INVALID, - "wrap_scroll", "Invalid value %s", argv[0]); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/border.c b/sway/commands/border.c index b6eab550..d51741d2 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c @@ -93,7 +93,7 @@ struct cmd_results *cmd_border(int argc, char **argv) { } if (container_is_floating(container)) { - container_set_geometry_from_floating_view(container); + container_set_geometry_from_content(container); } arrange_container(container); 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/floating.c b/sway/commands/floating.c index 81bb86f8..4b82921c 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -9,6 +9,7 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "list.h" +#include "util.h" struct cmd_results *cmd_floating(int argc, char **argv) { struct cmd_results *error = NULL; @@ -40,17 +41,8 @@ struct cmd_results *cmd_floating(int argc, char **argv) { } } - bool wants_floating; - if (strcasecmp(argv[0], "enable") == 0) { - wants_floating = true; - } else if (strcasecmp(argv[0], "disable") == 0) { - wants_floating = false; - } else if (strcasecmp(argv[0], "toggle") == 0) { - wants_floating = !container_is_floating(container); - } else { - return cmd_results_new(CMD_FAILURE, "floating", - "Expected 'floating <enable|disable|toggle>'"); - } + bool wants_floating = + parse_boolean(argv[0], container_is_floating(container)); container_set_floating(container, wants_floating); diff --git a/sway/commands/focus_follows_mouse.c b/sway/commands/focus_follows_mouse.c index 0b0e334c..d0d2cb8a 100644 --- a/sway/commands/focus_follows_mouse.c +++ b/sway/commands/focus_follows_mouse.c @@ -7,8 +7,15 @@ struct cmd_results *cmd_focus_follows_mouse(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "focus_follows_mouse", EXPECTED_EQUAL_TO, 1))) { return error; + } else if(strcmp(argv[0], "no") == 0) { + config->focus_follows_mouse = FOLLOWS_NO; + } else if(strcmp(argv[0], "yes") == 0) { + config->focus_follows_mouse = FOLLOWS_YES; + } else if(strcmp(argv[0], "always") == 0) { + config->focus_follows_mouse = FOLLOWS_ALWAYS; + } else { + return cmd_results_new(CMD_FAILURE, "focus_follows_mouse", + "Expected 'focus_follows_mouse no|yes|always'"); } - config->focus_follows_mouse = - parse_boolean(argv[0], config->focus_follows_mouse); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 3f0ef155..faaeab37 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -16,73 +16,128 @@ enum gaps_op { struct gaps_data { bool inner; + struct { + bool top; + bool right; + bool bottom; + bool left; + } outer; enum gaps_op operation; int amount; }; -// gaps inner|outer <px> +// Prevent negative outer gaps from moving windows out of the workspace. +static void prevent_invalid_outer_gaps(void) { + if (config->gaps_outer.top < -config->gaps_inner) { + config->gaps_outer.top = -config->gaps_inner; + } + if (config->gaps_outer.right < -config->gaps_inner) { + config->gaps_outer.right = -config->gaps_inner; + } + if (config->gaps_outer.bottom < -config->gaps_inner) { + config->gaps_outer.bottom = -config->gaps_inner; + } + if (config->gaps_outer.left < -config->gaps_inner) { + config->gaps_outer.left = -config->gaps_inner; + } +} + +// gaps inner|outer|horizontal|vertical|top|right|bottom|left <px> +static const char *expected_defaults = + "'gaps inner|outer|horizontal|vertical|top|right|bottom|left <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; } - 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; 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>'"); + "Expected %s", expected_defaults); } - if (inner) { + + bool valid = false; + if (!strcasecmp(argv[0], "inner")) { + valid = true; config->gaps_inner = (amount >= 0) ? amount : 0; } else { - config->gaps_outer = amount; - } - - // Prevent negative outer gaps from moving windows out of the workspace. - if (config->gaps_outer < -config->gaps_inner) { - config->gaps_outer = -config->gaps_inner; + if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") + || !strcasecmp(argv[0], "top")) { + valid = true; + config->gaps_outer.top = amount; + } + if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") + || !strcasecmp(argv[0], "right")) { + valid = true; + config->gaps_outer.right = amount; + } + if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "vertical") + || !strcasecmp(argv[0], "bottom")) { + valid = true; + config->gaps_outer.bottom = amount; + } + if (!strcasecmp(argv[0], "outer") || !strcasecmp(argv[0], "horizontal") + || !strcasecmp(argv[0], "left")) { + valid = true; + config->gaps_outer.left = amount; + } + } + if (!valid) { + return cmd_results_new(CMD_INVALID, "gaps", + "Expected %s", expected_defaults); } + prevent_invalid_outer_gaps(); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -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) { +static void apply_gaps_op(int *prop, enum gaps_op op, int amount) { + switch (op) { case GAPS_OP_SET: - *prop = data->amount; + *prop = amount; break; case GAPS_OP_ADD: - *prop += data->amount; + *prop += amount; break; case GAPS_OP_SUBTRACT: - *prop -= data->amount; + *prop -= amount; break; } +} + +static void configure_gaps(struct sway_workspace *ws, void *_data) { + // Apply operation to gaps + struct gaps_data *data = _data; + if (data->inner) { + apply_gaps_op(&ws->gaps_inner, data->operation, data->amount); + } + if (data->outer.top) { + apply_gaps_op(&(ws->gaps_outer.top), data->operation, data->amount); + } + if (data->outer.right) { + apply_gaps_op(&(ws->gaps_outer.right), data->operation, data->amount); + } + if (data->outer.bottom) { + apply_gaps_op(&(ws->gaps_outer.bottom), data->operation, data->amount); + } + if (data->outer.left) { + apply_gaps_op(&(ws->gaps_outer.left), data->operation, data->amount); + } + // Prevent invalid gaps configurations. if (ws->gaps_inner < 0) { ws->gaps_inner = 0; } - if (ws->gaps_outer < -ws->gaps_inner) { - ws->gaps_outer = -ws->gaps_inner; - } + prevent_invalid_outer_gaps(); arrange_workspace(ws); } -// gaps inner|outer current|all set|plus|minus <px> +// gaps inner|outer|horizontal|vertical|top|right|bottom|left current|all +// set|plus|minus <px> +static const char *expected_runtime = "'gaps inner|outer|horizontal|vertical|" + "top|right|bottom|left 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) { @@ -93,15 +148,24 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { "Can't run this command while there's no outputs connected."); } - struct gaps_data data; + struct gaps_data data = {0}; if (strcasecmp(argv[0], "inner") == 0) { data.inner = true; - } else if (strcasecmp(argv[0], "outer") == 0) { - data.inner = false; } else { + data.outer.top = !strcasecmp(argv[0], "outer") || + !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "top"); + data.outer.right = !strcasecmp(argv[0], "outer") || + !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "right"); + data.outer.bottom = !strcasecmp(argv[0], "outer") || + !strcasecmp(argv[0], "vertical") || !strcasecmp(argv[0], "bottom"); + data.outer.left = !strcasecmp(argv[0], "outer") || + !strcasecmp(argv[0], "horizontal") || !strcasecmp(argv[0], "left"); + } + if (!data.inner && !data.outer.top && !data.outer.right && + !data.outer.bottom && !data.outer.left) { return cmd_results_new(CMD_INVALID, "gaps", - "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + "Expected %s", expected_runtime); } bool all; @@ -111,7 +175,7 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { all = true; } else { return cmd_results_new(CMD_INVALID, "gaps", - "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + "Expected %s", expected_runtime); } if (strcasecmp(argv[2], "set") == 0) { @@ -122,14 +186,14 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { data.operation = GAPS_OP_SUBTRACT; } else { return cmd_results_new(CMD_INVALID, "gaps", - "Expected 'gaps inner|outer current|all set|plus|minus <px>'"); + "Expected %s", expected_runtime); } 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>'"); + "Expected %s", expected_runtime); } if (all) { @@ -141,8 +205,10 @@ static struct cmd_results *gaps_set_runtime(int argc, char **argv) { return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -// gaps inner|outer <px> - sets defaults for workspaces -// gaps inner|outer current|all set|plus|minus <px> - runtime only +// gaps inner|outer|<dir>|<side> <px> - sets defaults for workspaces +// gaps inner|outer|<dir>|<side> current|all set|plus|minus <px> - runtime only +// <dir> = horizontal|vertical +// <side> = top|right|bottom|left struct cmd_results *cmd_gaps(int argc, char **argv) { struct cmd_results *error = checkarg(argc, "gaps", EXPECTED_AT_LEAST, 2); if (error) { @@ -159,9 +225,8 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { } if (config_loading) { return cmd_results_new(CMD_INVALID, "gaps", - "Expected 'gaps inner|outer <px>'"); + "Expected %s", expected_defaults); } return cmd_results_new(CMD_INVALID, "gaps", - "Expected 'gaps inner|outer <px>' or " - "'gaps inner|outer current|all set|plus|minus <px>'"); + "Expected %s or %s", expected_runtime, expected_defaults); } diff --git a/sway/commands/input.c b/sway/commands/input.c index c50926a8..b5765c38 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -22,6 +22,7 @@ static struct cmd_handler input_handlers[] = { { "repeat_delay", input_cmd_repeat_delay }, { "repeat_rate", input_cmd_repeat_rate }, { "scroll_button", input_cmd_scroll_button }, + { "scroll_factor", input_cmd_scroll_factor }, { "scroll_method", input_cmd_scroll_method }, { "tap", input_cmd_tap }, { "tap_button_map", input_cmd_tap_button_map }, diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c index df487b1c..efd81ee6 100644 --- a/sway/commands/input/pointer_accel.c +++ b/sway/commands/input/pointer_accel.c @@ -1,8 +1,10 @@ +#include <math.h> #include <stdlib.h> #include <string.h> #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" +#include "util.h" struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { struct cmd_results *error = NULL; @@ -15,8 +17,11 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) { "pointer_accel", "No input device defined."); } - float pointer_accel = atof(argv[0]); - if (pointer_accel < -1 || pointer_accel > 1) { + float pointer_accel = parse_float(argv[0]); + if (isnan(pointer_accel)) { + return cmd_results_new(CMD_INVALID, "pointer_accel", + "Invalid pointer accel; expected float."); + } if (pointer_accel < -1 || pointer_accel > 1) { return cmd_results_new(CMD_INVALID, "pointer_accel", "Input out of range [-1, 1]"); } diff --git a/sway/commands/input/scroll_factor.c b/sway/commands/input/scroll_factor.c new file mode 100644 index 00000000..52d943b0 --- /dev/null +++ b/sway/commands/input/scroll_factor.c @@ -0,0 +1,32 @@ +#include <errno.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include "sway/config.h" +#include "sway/commands.h" +#include "sway/input/input-manager.h" +#include "util.h" + +struct cmd_results *input_cmd_scroll_factor(int argc, char **argv) { + struct cmd_results *error = NULL; + if ((error = checkarg(argc, "scroll_factor", EXPECTED_AT_LEAST, 1))) { + return error; + } + struct input_config *ic = config->handler_context.input_config; + if (!ic) { + return cmd_results_new(CMD_FAILURE, + "scroll_factor", "No input device defined."); + } + + float scroll_factor = parse_float(argv[0]); + if (isnan(scroll_factor)) { + return cmd_results_new(CMD_INVALID, "scroll_factor", + "Invalid scroll factor; expected float."); + } else if (scroll_factor < 0) { + return cmd_results_new(CMD_INVALID, "scroll_factor", + "Scroll factor cannot be negative."); + } + ic->scroll_factor = scroll_factor; + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); +} diff --git a/sway/commands/input/xkb_capslock.c b/sway/commands/input/xkb_capslock.c index 669b4ea9..a939c72f 100644 --- a/sway/commands/input/xkb_capslock.c +++ b/sway/commands/input/xkb_capslock.c @@ -3,6 +3,7 @@ #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" +#include "util.h" struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { struct cmd_results *error = NULL; @@ -15,14 +16,7 @@ struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) { "No input device defined."); } - if (strcasecmp(argv[0], "enabled") == 0) { - ic->xkb_capslock = 1; - } else if (strcasecmp(argv[0], "disabled") == 0) { - ic->xkb_capslock = 0; - } else { - return cmd_results_new(CMD_INVALID, "xkb_capslock", - "Expected 'xkb_capslock <enabled|disabled>'"); - } + ic->xkb_capslock = parse_boolean(argv[0], false); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c index 1367da44..2e962c5b 100644 --- a/sway/commands/input/xkb_numlock.c +++ b/sway/commands/input/xkb_numlock.c @@ -3,6 +3,7 @@ #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" +#include "util.h" struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { struct cmd_results *error = NULL; @@ -15,14 +16,7 @@ struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) { "No input device defined."); } - if (strcasecmp(argv[0], "enabled") == 0) { - ic->xkb_numlock = 1; - } else if (strcasecmp(argv[0], "disabled") == 0) { - ic->xkb_numlock = 0; - } else { - return cmd_results_new(CMD_INVALID, "xkb_numlock", - "Expected 'xkb_numlock <enabled|disabled>'"); - } + ic->xkb_numlock = parse_boolean(argv[0], false); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/resize.c b/sway/commands/resize.c index 8635b309..a90d578e 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -404,13 +404,10 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, con->width += grow_width; con->height += grow_height; - if (con->view) { - struct sway_view *view = con->view; - view->x += grow_x; - view->y += grow_y; - view->width += grow_width; - view->height += grow_height; - } + con->content_x += grow_x; + con->content_y += grow_y; + con->content_width += grow_width; + con->content_height += grow_height; arrange_container(con); @@ -499,7 +496,7 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, } if (height->unit == RESIZE_UNIT_PX) { resize_tiled(con, height->amount - con->height, - RESIZE_AXIS_HORIZONTAL); + RESIZE_AXIS_VERTICAL); } } @@ -511,25 +508,46 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, */ static struct cmd_results *resize_set_floating(struct sway_container *con, struct resize_amount *width, struct resize_amount *height) { - int min_width, max_width, min_height, max_height; + int min_width, max_width, min_height, max_height, grow_width = 0, grow_height = 0; calculate_constraints(&min_width, &max_width, &min_height, &max_height); - width->amount = fmax(min_width, fmin(width->amount, max_width)); - height->amount = fmax(min_height, fmin(height->amount, max_height)); - int grow_width = width->amount - con->width; - int grow_height = height->amount - con->height; - con->x -= grow_width / 2; - con->y -= grow_height / 2; - con->width = width->amount; - con->height = height->amount; - - if (con->view) { - struct sway_view *view = con->view; - view->x -= grow_width / 2; - view->y -= grow_height / 2; - view->width += grow_width; - view->height += grow_height; + + if (width->amount) { + if (width->unit == RESIZE_UNIT_PPT || + width->unit == RESIZE_UNIT_DEFAULT) { + // Convert to px + width->amount = con->workspace->width * width->amount / 100; + width->unit = RESIZE_UNIT_PX; + } + if (width->unit == RESIZE_UNIT_PX) { + width->amount = fmax(min_width, fmin(width->amount, max_width)); + grow_width = width->amount - con->width; + + con->x -= grow_width / 2; + con->width = width->amount; + } } + if (height->amount) { + if (height->unit == RESIZE_UNIT_PPT || + height->unit == RESIZE_UNIT_DEFAULT) { + // Convert to px + height->amount = con->workspace->height * height->amount / 100; + height->unit = RESIZE_UNIT_PX; + } + if (height->unit == RESIZE_UNIT_PX) { + height->amount = fmax(min_height, fmin(height->amount, max_height)); + grow_height = height->amount - con->height; + + con->y -= grow_height / 2; + con->height = height->amount; + } + } + + con->content_x -= grow_width / 2; + con->content_y -= grow_height / 2; + con->content_width += grow_width; + con->content_height += grow_height; + arrange_container(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); @@ -538,34 +556,45 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, /** * resize set <args> * - * args: <width> [px|ppt] <height> [px|ppt] + * args: [width] <width> [px|ppt] + * : height <height> [px|ppt] + * : [width] <width> [px|ppt] [height] <height> [px|ppt] */ static struct cmd_results *cmd_resize_set(int argc, char **argv) { struct cmd_results *error; - if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { + if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 1))) { return error; } - const char *usage = "Expected 'resize set <width> <height>'"; + const char *usage = "Expected 'resize set [width] <width> [px|ppt]' or " + "'resize set height <height> [px|ppt]' or " + "'resize set [width] <width> [px|ppt] [height] <height> [px|ppt]'"; // Width - struct resize_amount width; - int num_consumed_args = parse_resize_amount(argc, argv, &width); - argc -= num_consumed_args; - argv += num_consumed_args; - if (width.unit == RESIZE_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, "resize", usage); + struct resize_amount width = {0}; + if (argc >= 2 && !strcmp(argv[0], "width") && strcmp(argv[1], "height")) { + argc--; argv++; } - if (!argc) { - return cmd_results_new(CMD_INVALID, "resize", usage); + if (strcmp(argv[0], "height")) { + int num_consumed_args = parse_resize_amount(argc, argv, &width); + argc -= num_consumed_args; + argv += num_consumed_args; + if (width.unit == RESIZE_UNIT_INVALID) { + return cmd_results_new(CMD_INVALID, "resize set", usage); + } } // Height - struct resize_amount height; - num_consumed_args = parse_resize_amount(argc, argv, &height); - argc -= num_consumed_args; - argv += num_consumed_args; - if (height.unit == RESIZE_UNIT_INVALID) { - return cmd_results_new(CMD_INVALID, "resize", usage); + struct resize_amount height = {0}; + if (argc) { + if (argc >= 2 && !strcmp(argv[0], "height")) { + argc--; argv++; + } + int num_consumed_args = parse_resize_amount(argc, argv, &height); + argc -= num_consumed_args; + argv += num_consumed_args; + if (width.unit == RESIZE_UNIT_INVALID) { + return cmd_results_new(CMD_INVALID, "resize set", usage); + } } // If 0, don't resize that dimension diff --git a/sway/commands/seat/fallback.c b/sway/commands/seat/fallback.c index 11f5a08c..a0ddf3ef 100644 --- a/sway/commands/seat/fallback.c +++ b/sway/commands/seat/fallback.c @@ -3,6 +3,7 @@ #include "sway/config.h" #include "sway/commands.h" #include "sway/input/input-manager.h" +#include "util.h" struct cmd_results *seat_cmd_fallback(int argc, char **argv) { struct cmd_results *error = NULL; @@ -16,16 +17,8 @@ struct cmd_results *seat_cmd_fallback(int argc, char **argv) { } struct seat_config *new_config = new_seat_config(current_seat_config->name); - - if (strcasecmp(argv[0], "true") == 0) { - new_config->fallback = 1; - } else if (strcasecmp(argv[0], "false") == 0) { - new_config->fallback = 0; - } else { - free_seat_config(new_config); - return cmd_results_new(CMD_INVALID, "fallback", - "Expected 'fallback <true|false>'"); - } + + new_config->fallback = parse_boolean(argv[0], false); if (!config->validating) { apply_seat_config(new_config); diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index 273905df..f14b6760 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c @@ -6,6 +6,7 @@ #include "sway/tree/container.h" #include "log.h" #include "stringop.h" +#include "util.h" struct cmd_results *cmd_smart_gaps(int argc, char **argv) { struct cmd_results *error = checkarg(argc, "smart_gaps", EXPECTED_AT_LEAST, 1); @@ -14,14 +15,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { return error; } - if (strcmp(argv[0], "on") == 0) { - config->smart_gaps = true; - } else if (strcmp(argv[0], "off") == 0) { - config->smart_gaps = false; - } else { - return cmd_results_new(CMD_INVALID, "smart_gaps", - "Expected 'smart_gaps <on|off>' "); - } + config->smart_gaps = parse_boolean(argv[0], config->smart_gaps); arrange_root(); diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c index f18322b7..7cd358a4 100644 --- a/sway/commands/sticky.c +++ b/sway/commands/sticky.c @@ -9,6 +9,7 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "list.h" +#include "util.h" struct cmd_results *cmd_sticky(int argc, char **argv) { struct cmd_results *error = NULL; @@ -26,21 +27,9 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { "Can't set sticky on a tiled container"); } - bool wants_sticky; - if (strcasecmp(argv[0], "enable") == 0) { - wants_sticky = true; - } else if (strcasecmp(argv[0], "disable") == 0) { - wants_sticky = false; - } else if (strcasecmp(argv[0], "toggle") == 0) { - wants_sticky = !container->is_sticky; - } else { - return cmd_results_new(CMD_FAILURE, "sticky", - "Expected 'sticky <enable|disable|toggle>'"); - } - - container->is_sticky = wants_sticky; + container->is_sticky = parse_boolean(argv[0], container->is_sticky); - if (wants_sticky) { + if (container->is_sticky) { // move container to active workspace struct sway_workspace *active_workspace = output_get_active_workspace(container->workspace->output); diff --git a/sway/commands/swap.c b/sway/commands/swap.c index 23e8d583..08860264 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -144,19 +144,18 @@ static void container_swap(struct sway_container *con1, } } -static bool test_con_id(struct sway_container *container, void *con_id) { - return container->node.id == (size_t)con_id; +static bool test_con_id(struct sway_container *container, void *data) { + size_t *con_id = data; + return container->node.id == *con_id; } -static bool test_id(struct sway_container *container, void *id) { -#ifdef HAVE_XWAYLAND - xcb_window_t *wid = id; +#if HAVE_XWAYLAND +static bool test_id(struct sway_container *container, void *data) { + xcb_window_t *wid = data; return (container->view && container->view->type == SWAY_VIEW_XWAYLAND && container->view->wlr_xwayland_surface->window_id == *wid); -#else - return false; -#endif } +#endif static bool test_mark(struct sway_container *container, void *mark) { if (container->marks->length) { @@ -181,19 +180,19 @@ struct cmd_results *cmd_swap(int argc, char **argv) { } struct sway_container *current = config->handler_context.container; - struct sway_container *other; + struct sway_container *other = NULL; char *value = join_args(argv + 3, argc - 3); if (strcasecmp(argv[2], "id") == 0) { -#ifdef HAVE_XWAYLAND +#if HAVE_XWAYLAND xcb_window_t id = strtol(value, NULL, 0); - other = root_find_container(test_id, (void *)&id); + other = root_find_container(test_id, &id); #endif } else if (strcasecmp(argv[2], "con_id") == 0) { size_t con_id = atoi(value); - other = root_find_container(test_con_id, (void *)con_id); + other = root_find_container(test_con_id, &con_id); } else if (strcasecmp(argv[2], "mark") == 0) { - other = root_find_container(test_mark, (void *)value); + other = root_find_container(test_mark, value); } else { free(value); return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 5abbb676..92118ecf 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -21,18 +21,105 @@ 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 = INT_MIN; + wsc->gaps_outer.top = INT_MIN; + wsc->gaps_outer.right = INT_MIN; + wsc->gaps_outer.bottom = INT_MIN; + wsc->gaps_outer.left = INT_MIN; list_add(config->workspace_configs, wsc); return wsc; } void free_workspace_config(struct workspace_config *wsc) { free(wsc->workspace); - free(wsc->output); + free_flat_list(wsc->outputs); free(wsc); } +static void prevent_invalid_outer_gaps(struct workspace_config *wsc) { + if (wsc->gaps_outer.top != INT_MIN && + wsc->gaps_outer.top < -wsc->gaps_inner) { + wsc->gaps_outer.top = -wsc->gaps_inner; + } + if (wsc->gaps_outer.right != INT_MIN && + wsc->gaps_outer.right < -wsc->gaps_inner) { + wsc->gaps_outer.right = -wsc->gaps_inner; + } + if (wsc->gaps_outer.bottom != INT_MIN && + wsc->gaps_outer.bottom < -wsc->gaps_inner) { + wsc->gaps_outer.bottom = -wsc->gaps_inner; + } + if (wsc->gaps_outer.left != INT_MIN && + wsc->gaps_outer.left < -wsc->gaps_inner) { + wsc->gaps_outer.left = -wsc->gaps_inner; + } +} + +static struct cmd_results *cmd_workspace_gaps(int argc, char **argv, + int gaps_location) { + const char *expected = "Expected 'workspace <name> gaps " + "inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; + struct cmd_results *error = NULL; + 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"); + } + + char *end; + int amount = strtol(argv[gaps_location + 2], &end, 10); + if (strlen(end)) { + free(end); + return cmd_results_new(CMD_FAILURE, "workspace gaps", expected); + } + + bool valid = false; + char *type = argv[gaps_location + 1]; + if (!strcasecmp(type, "inner")) { + valid = true; + wsc->gaps_inner = (amount >= 0) ? amount : 0; + } else { + if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") + || !strcasecmp(type, "top")) { + valid = true; + wsc->gaps_outer.top = amount; + } + if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") + || !strcasecmp(type, "right")) { + valid = true; + wsc->gaps_outer.right = amount; + } + if (!strcasecmp(type, "outer") || !strcasecmp(type, "vertical") + || !strcasecmp(type, "bottom")) { + valid = true; + wsc->gaps_outer.bottom = amount; + } + if (!strcasecmp(type, "outer") || !strcasecmp(type, "horizontal") + || !strcasecmp(type, "left")) { + valid = true; + wsc->gaps_outer.left = amount; + } + } + if (!valid) { + return cmd_results_new(CMD_INVALID, "workspace gaps", expected); + } + + // Prevent invalid gaps configurations. + if (wsc->gaps_inner != INT_MIN && wsc->gaps_inner < 0) { + wsc->gaps_inner = 0; + } + prevent_invalid_outer_gaps(wsc); + + return error; +} + struct cmd_results *cmd_workspace(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "workspace", EXPECTED_AT_LEAST, 1))) { @@ -55,56 +142,24 @@ 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 = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, gaps_location + 3))) { + if ((error = cmd_workspace_gaps(argc, argv, gaps_location))) { 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>'"); - } - *prop = val; - - // Prevent invalid gaps configurations. - if (wsc->gaps_inner < 0) { - wsc->gaps_inner = 0; - } - if (wsc->gaps_outer < -wsc->gaps_inner) { - wsc->gaps_outer = -wsc->gaps_inner; - } - } else { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); diff --git a/sway/commands/ws_auto_back_and_forth.c b/sway/commands/ws_auto_back_and_forth.c index 2485db35..adb851c2 100644 --- a/sway/commands/ws_auto_back_and_forth.c +++ b/sway/commands/ws_auto_back_and_forth.c @@ -1,12 +1,14 @@ #include <string.h> #include <strings.h> #include "sway/commands.h" +#include "util.h" struct cmd_results *cmd_ws_auto_back_and_forth(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "workspace_auto_back_and_forth", EXPECTED_EQUAL_TO, 1))) { return error; } - config->auto_back_and_forth = !strcasecmp(argv[0], "yes"); + config->auto_back_and_forth = + parse_boolean(argv[0], config->auto_back_and_forth); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } |