aboutsummaryrefslogtreecommitdiff
path: root/sway/commands
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands')
-rw-r--r--sway/commands/bar/binding_mode_indicator.c12
-rw-r--r--sway/commands/bar/pango_markup.c13
-rw-r--r--sway/commands/bar/workspace_buttons.c12
-rw-r--r--sway/commands/bar/wrap_scroll.c14
-rw-r--r--sway/commands/border.c2
-rw-r--r--sway/commands/create_output.c4
-rw-r--r--sway/commands/floating.c14
-rw-r--r--sway/commands/focus_follows_mouse.c11
-rw-r--r--sway/commands/gaps.c151
-rw-r--r--sway/commands/input.c1
-rw-r--r--sway/commands/input/pointer_accel.c9
-rw-r--r--sway/commands/input/scroll_factor.c32
-rw-r--r--sway/commands/input/xkb_capslock.c10
-rw-r--r--sway/commands/input/xkb_numlock.c10
-rw-r--r--sway/commands/resize.c111
-rw-r--r--sway/commands/seat/fallback.c13
-rw-r--r--sway/commands/smart_gaps.c10
-rw-r--r--sway/commands/sticky.c17
-rw-r--r--sway/commands/swap.c25
-rw-r--r--sway/commands/workspace.c137
-rw-r--r--sway/commands/ws_auto_back_and_forth.c4
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);
}