aboutsummaryrefslogtreecommitdiff
path: root/sway
diff options
context:
space:
mode:
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c45
-rw-r--r--sway/commands/bar/binding_mode_indicator.c6
-rw-r--r--sway/commands/bind.c2
-rw-r--r--sway/commands/gaps.c306
-rw-r--r--sway/commands/input.c11
-rw-r--r--sway/commands/input/accel_profile.c13
-rw-r--r--sway/commands/input/click_method.c15
-rw-r--r--sway/commands/input/drag.c26
-rw-r--r--sway/commands/input/drag_lock.c12
-rw-r--r--sway/commands/input/dwt.c12
-rw-r--r--sway/commands/input/events.c17
-rw-r--r--sway/commands/input/left_handed.c10
-rw-r--r--sway/commands/input/map_from_region.c42
-rw-r--r--sway/commands/input/map_to_output.c10
-rw-r--r--sway/commands/input/middle_emulation.c13
-rw-r--r--sway/commands/input/natural_scroll.c10
-rw-r--r--sway/commands/input/pointer_accel.c11
-rw-r--r--sway/commands/input/repeat_delay.c11
-rw-r--r--sway/commands/input/repeat_rate.c11
-rw-r--r--sway/commands/input/scroll_button.c13
-rw-r--r--sway/commands/input/scroll_method.c17
-rw-r--r--sway/commands/input/tap.c14
-rw-r--r--sway/commands/input/tap_button_map.c13
-rw-r--r--sway/commands/input/xkb_capslock.c13
-rw-r--r--sway/commands/input/xkb_layout.c17
-rw-r--r--sway/commands/input/xkb_model.c17
-rw-r--r--sway/commands/input/xkb_numlock.c13
-rw-r--r--sway/commands/input/xkb_options.c17
-rw-r--r--sway/commands/input/xkb_rules.c17
-rw-r--r--sway/commands/input/xkb_variant.c17
-rw-r--r--sway/commands/layout.c3
-rw-r--r--sway/commands/move.c64
-rw-r--r--sway/commands/output/background.c18
-rw-r--r--sway/commands/resize.c30
-rw-r--r--sway/commands/workspace.c74
-rw-r--r--sway/config.c11
-rw-r--r--sway/config/bar.c26
-rw-r--r--sway/config/input.c62
-rw-r--r--sway/config/output.c4
-rw-r--r--sway/config/seat.c2
-rw-r--r--sway/debug-tree.c2
-rw-r--r--sway/desktop/transaction.c66
-rw-r--r--sway/desktop/xdg_shell.c2
-rw-r--r--sway/desktop/xdg_shell_v6.c2
-rw-r--r--sway/desktop/xwayland.c2
-rw-r--r--sway/input/cursor.c62
-rw-r--r--sway/input/input-manager.c22
-rw-r--r--sway/input/seat.c44
-rw-r--r--sway/ipc-json.c2
-rw-r--r--sway/ipc-server.c15
-rw-r--r--sway/main.c84
-rw-r--r--sway/meson.build3
-rw-r--r--sway/sway-bar.5.scd3
-rw-r--r--sway/sway-input.5.scd7
-rw-r--r--sway/sway.5.scd82
-rw-r--r--sway/tree/arrange.c3
-rw-r--r--sway/tree/container.c38
-rw-r--r--sway/tree/output.c30
-rw-r--r--sway/tree/root.c21
-rw-r--r--sway/tree/view.c29
-rw-r--r--sway/tree/workspace.c81
61 files changed, 831 insertions, 814 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 07169f1e..03761c52 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -55,22 +55,6 @@ struct cmd_results *checkarg(int argc, const char *name, enum expected_args type
return error;
}
-void apply_input_config(struct input_config *input) {
- int i;
- i = list_seq_find(config->input_configs, input_identifier_cmp, input->identifier);
- if (i >= 0) {
- // merge existing config
- struct input_config *ic = config->input_configs->items[i];
- merge_input_config(ic, input);
- free_input_config(input);
- input = ic;
- } else {
- list_add(config->input_configs, input);
- }
-
- input_manager_apply_input_config(input_manager, input);
-}
-
void apply_seat_config(struct seat_config *seat_config) {
int i;
i = list_seq_find(config->seat_configs, seat_name_cmp, seat_config->name);
@@ -237,7 +221,8 @@ static void set_config_node(struct sway_node *node) {
}
}
-struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
+struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
+ struct sway_container *con) {
// Even though this function will process multiple commands we will only
// return the last error, if any (for now). (Since we have access to an
// error string we could e.g. concatenate all errors there.)
@@ -256,6 +241,15 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
}
}
+ // This is the container or workspace which this command will run on.
+ // Ignored if the command string contains criteria.
+ struct sway_node *node;
+ if (con) {
+ node = &con->node;
+ } else {
+ node = seat_get_focus_inactive(seat, &root->node);
+ }
+
config->handler_context.seat = seat;
head = exec;
@@ -318,9 +312,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
}
if (!config->handler_context.using_criteria) {
- // without criteria, the command acts upon the focused
- // container
- set_config_node(seat_get_focus_inactive(seat, &root->node));
+ set_config_node(node);
struct cmd_results *res = handler->handle(argc-1, argv+1);
if (res->status != CMD_SUCCESS) {
free_argv(argc, argv);
@@ -399,14 +391,12 @@ struct cmd_results *config_command(char *exec) {
// Var replacement, for all but first argument of set
// TODO commands
for (i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
+ if (*argv[i] == '\"' || *argv[i] == '\'') {
+ strip_quotes(argv[i]);
+ }
argv[i] = do_var_replacement(argv[i]);
unescape_string(argv[i]);
}
- // Strip quotes for first argument.
- // TODO This part needs to be handled much better
- if (argc>1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
- strip_quotes(argv[1]);
- }
if (handler->handle) {
results = handler->handle(argc-1, argv+1);
} else {
@@ -430,11 +420,6 @@ struct cmd_results *config_subcommand(char **argv, int argc,
char *input = argv[0] ? argv[0] : "(empty)";
return cmd_results_new(CMD_INVALID, input, "Unknown/invalid command");
}
- // Strip quotes for first argument.
- // TODO This part needs to be handled much better
- if (argc > 1 && (*argv[1] == '\"' || *argv[1] == '\'')) {
- strip_quotes(argv[1]);
- }
if (handler->handle) {
return handler->handle(argc - 1, argv + 1);
}
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/bind.c b/sway/commands/bind.c
index 047018e0..820c2a6a 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -321,7 +321,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
}
config->handler_context.seat = seat;
- struct cmd_results *results = execute_command(binding->command, NULL);
+ struct cmd_results *results = execute_command(binding->command, NULL, NULL);
if (results->status == CMD_SUCCESS) {
ipc_event_binding(binding_copy);
} else {
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/input.c b/sway/commands/input.c
index 84888fbb..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 },
@@ -66,7 +67,15 @@ struct cmd_results *cmd_input(int argc, char **argv) {
input_handlers, sizeof(input_handlers));
}
- free_input_config(config->handler_context.input_config);
+ if (!res || res->status == CMD_SUCCESS) {
+ struct input_config *ic =
+ store_input_config(config->handler_context.input_config);
+
+ input_manager_apply_input_config(input_manager, ic);
+ } else {
+ free_input_config(config->handler_context.input_config);
+ }
+
config->handler_context.input_config = NULL;
return res;
diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c
index a4108ec3..f7016790 100644
--- a/sway/commands/input/accel_profile.c
+++ b/sway/commands/input/accel_profile.c
@@ -9,25 +9,20 @@ struct cmd_results *input_cmd_accel_profile(int argc, char **argv) {
if ((error = checkarg(argc, "accel_profile", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "accel_profile",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "adaptive") == 0) {
- new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
+ ic->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
} else if (strcasecmp(argv[0], "flat") == 0) {
- new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
+ ic->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "accel_profile",
"Expected 'accel_profile <adaptive|flat>'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c
index 5d0d8cc2..4d7e1c93 100644
--- a/sway/commands/input/click_method.c
+++ b/sway/commands/input/click_method.c
@@ -10,27 +10,22 @@ struct cmd_results *input_cmd_click_method(int argc, char **argv) {
if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "click_method",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "none") == 0) {
- new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
+ ic->click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE;
} else if (strcasecmp(argv[0], "button_areas") == 0) {
- new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
+ ic->click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS;
} else if (strcasecmp(argv[0], "clickfinger") == 0) {
- new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
+ ic->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "click_method",
"Expected 'click_method <none|button_areas|clickfinger'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
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/input/drag_lock.c b/sway/commands/input/drag_lock.c
index f9ddeef2..db5d5afa 100644
--- a/sway/commands/input/drag_lock.c
+++ b/sway/commands/input/drag_lock.c
@@ -10,21 +10,17 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
if ((error = checkarg(argc, "drag_lock", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE,
"drag_lock", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (parse_boolean(argv[0], true)) {
- new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
+ ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
} else {
- new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
+ ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c
index 15134268..0c3881dd 100644
--- a/sway/commands/input/dwt.c
+++ b/sway/commands/input/dwt.c
@@ -10,20 +10,16 @@ struct cmd_results *input_cmd_dwt(int argc, char **argv) {
if ((error = checkarg(argc, "dwt", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "dwt", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (parse_boolean(argv[0], true)) {
- new_config->dwt = LIBINPUT_CONFIG_DWT_ENABLED;
+ ic->dwt = LIBINPUT_CONFIG_DWT_ENABLED;
} else {
- new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
+ ic->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c
index abfe3b12..e7ed69c6 100644
--- a/sway/commands/input/events.c
+++ b/sway/commands/input/events.c
@@ -10,30 +10,23 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "events",
"No input device defined.");
}
- wlr_log(WLR_DEBUG, "events for device: %s",
- current_input_config->identifier);
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "enabled") == 0) {
- new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
+ ic->send_events = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED;
} else if (strcasecmp(argv[0], "disabled") == 0) {
- new_config->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
+ ic->send_events = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED;
} else if (strcasecmp(argv[0], "disabled_on_external_mouse") == 0) {
- new_config->send_events =
+ ic->send_events =
LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "events",
"Expected 'events <enabled|disabled|disabled_on_external_mouse>'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c
index e770043a..2e0f757b 100644
--- a/sway/commands/input/left_handed.c
+++ b/sway/commands/input/left_handed.c
@@ -10,17 +10,13 @@ struct cmd_results *input_cmd_left_handed(int argc, char **argv) {
if ((error = checkarg(argc, "left_handed", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "left_handed",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->left_handed = parse_boolean(argv[0], true);
+ ic->left_handed = parse_boolean(argv[0], true);
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c
index 40f04214..53608a67 100644
--- a/sway/commands/input/map_from_region.c
+++ b/sway/commands/input/map_from_region.c
@@ -38,50 +38,44 @@ struct cmd_results *input_cmd_map_from_region(int argc, char **argv) {
if ((error = checkarg(argc, "map_from_region", EXPECTED_EQUAL_TO, 2))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "map_from_region",
"No input device defined");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
-
- new_config->mapped_from_region =
+ ic->mapped_from_region =
calloc(1, sizeof(struct input_config_mapped_from_region));
bool mm1, mm2;
- if (!parse_coords(argv[0], &new_config->mapped_from_region->x1,
- &new_config->mapped_from_region->y1, &mm1)) {
- free(new_config->mapped_from_region);
- free_input_config(new_config);
+ if (!parse_coords(argv[0], &ic->mapped_from_region->x1,
+ &ic->mapped_from_region->y1, &mm1)) {
+ free(ic->mapped_from_region);
+ ic->mapped_from_region = NULL;
return cmd_results_new(CMD_FAILURE, "map_from_region",
"Invalid top-left coordinates");
}
- if (!parse_coords(argv[1], &new_config->mapped_from_region->x2,
- &new_config->mapped_from_region->y2, &mm2)) {
- free(new_config->mapped_from_region);
- free_input_config(new_config);
+ if (!parse_coords(argv[1], &ic->mapped_from_region->x2,
+ &ic->mapped_from_region->y2, &mm2)) {
+ free(ic->mapped_from_region);
+ ic->mapped_from_region = NULL;
return cmd_results_new(CMD_FAILURE, "map_from_region",
"Invalid bottom-right coordinates");
}
- if (new_config->mapped_from_region->x1 > new_config->mapped_from_region->x2 ||
- new_config->mapped_from_region->y1 > new_config->mapped_from_region->y2) {
- free(new_config->mapped_from_region);
- free_input_config(new_config);
+ if (ic->mapped_from_region->x1 > ic->mapped_from_region->x2 ||
+ ic->mapped_from_region->y1 > ic->mapped_from_region->y2) {
+ free(ic->mapped_from_region);
+ ic->mapped_from_region = NULL;
return cmd_results_new(CMD_FAILURE, "map_from_region",
"Invalid rectangle");
}
if (mm1 != mm2) {
- free(new_config->mapped_from_region);
- free_input_config(new_config);
+ free(ic->mapped_from_region);
+ ic->mapped_from_region = NULL;
return cmd_results_new(CMD_FAILURE, "map_from_region",
"Both coordinates must be in the same unit");
}
- new_config->mapped_from_region->mm = mm1;
-
- apply_input_config(new_config);
+ ic->mapped_from_region->mm = mm1;
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/map_to_output.c b/sway/commands/input/map_to_output.c
index 68439bec..8b16c557 100644
--- a/sway/commands/input/map_to_output.c
+++ b/sway/commands/input/map_to_output.c
@@ -11,17 +11,13 @@ struct cmd_results *input_cmd_map_to_output(int argc, char **argv) {
if ((error = checkarg(argc, "map_to_output", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "map_to_output",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->mapped_to_output = strdup(argv[0]);
- apply_input_config(new_config);
+ ic->mapped_to_output = strdup(argv[0]);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c
index 414d4d2b..80d26838 100644
--- a/sway/commands/input/middle_emulation.c
+++ b/sway/commands/input/middle_emulation.c
@@ -10,22 +10,17 @@ struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) {
if ((error = checkarg(argc, "middle_emulation", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "middle_emulation",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (parse_boolean(argv[0], true)) {
- new_config->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED;
+ ic->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED;
} else {
- new_config->middle_emulation =
- LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
+ ic->middle_emulation = LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c
index 77c3ff00..e2a93500 100644
--- a/sway/commands/input/natural_scroll.c
+++ b/sway/commands/input/natural_scroll.c
@@ -10,17 +10,13 @@ struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) {
if ((error = checkarg(argc, "natural_scroll", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "natural_scoll",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->natural_scroll = parse_boolean(argv[0], true);
+ ic->natural_scroll = parse_boolean(argv[0], true);
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c
index 8bbd0724..df487b1c 100644
--- a/sway/commands/input/pointer_accel.c
+++ b/sway/commands/input/pointer_accel.c
@@ -9,23 +9,18 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) {
if ((error = checkarg(argc, "pointer_accel", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE,
"pointer_accel", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
float pointer_accel = atof(argv[0]);
if (pointer_accel < -1 || pointer_accel > 1) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "pointer_accel",
"Input out of range [-1, 1]");
}
- new_config->pointer_accel = pointer_accel;
+ ic->pointer_accel = pointer_accel;
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/repeat_delay.c b/sway/commands/input/repeat_delay.c
index c9ddbf0e..d94b3e4d 100644
--- a/sway/commands/input/repeat_delay.c
+++ b/sway/commands/input/repeat_delay.c
@@ -9,23 +9,18 @@ struct cmd_results *input_cmd_repeat_delay(int argc, char **argv) {
if ((error = checkarg(argc, "repeat_delay", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE,
"repeat_delay", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
int repeat_delay = atoi(argv[0]);
if (repeat_delay < 0) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "repeat_delay",
"Repeat delay cannot be negative");
}
- new_config->repeat_delay = repeat_delay;
+ ic->repeat_delay = repeat_delay;
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/repeat_rate.c b/sway/commands/input/repeat_rate.c
index 56878176..ebec4cdb 100644
--- a/sway/commands/input/repeat_rate.c
+++ b/sway/commands/input/repeat_rate.c
@@ -9,23 +9,18 @@ struct cmd_results *input_cmd_repeat_rate(int argc, char **argv) {
if ((error = checkarg(argc, "repeat_rate", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE,
"repeat_rate", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
int repeat_rate = atoi(argv[0]);
if (repeat_rate < 0) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "repeat_rate",
"Repeat rate cannot be negative");
}
- new_config->repeat_rate = repeat_rate;
+ ic->repeat_rate = repeat_rate;
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c
index 350fcca2..1958f23c 100644
--- a/sway/commands/input/scroll_button.c
+++ b/sway/commands/input/scroll_button.c
@@ -10,35 +10,28 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) {
if ((error = checkarg(argc, "scroll_button", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "scroll_button",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
errno = 0;
char *endptr;
int scroll_button = strtol(*argv, &endptr, 10);
if (endptr == *argv && scroll_button == 0) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "scroll_button",
"Scroll button identifier must be an integer.");
}
if (errno == ERANGE) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "scroll_button",
"Scroll button identifier out of range.");
}
if (scroll_button < 0) {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "scroll_button",
"Scroll button identifier cannot be negative.");
}
- new_config->scroll_button = scroll_button;
+ ic->scroll_button = scroll_button;
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c
index 4c6ac6b6..c116b052 100644
--- a/sway/commands/input/scroll_method.c
+++ b/sway/commands/input/scroll_method.c
@@ -9,29 +9,24 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) {
if ((error = checkarg(argc, "scroll_method", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "scroll_method",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "none") == 0) {
- new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
+ ic->scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
} else if (strcasecmp(argv[0], "two_finger") == 0) {
- new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
+ ic->scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
} else if (strcasecmp(argv[0], "edge") == 0) {
- new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
+ ic->scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
} else if (strcasecmp(argv[0], "on_button_down") == 0) {
- new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
+ ic->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "scroll_method",
"Expected 'scroll_method <none|two_finger|edge|on_button_down>'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c
index ac3b8237..c455b696 100644
--- a/sway/commands/input/tap.c
+++ b/sway/commands/input/tap.c
@@ -11,22 +11,16 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) {
if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "tap", "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (parse_boolean(argv[0], true)) {
- new_config->tap = LIBINPUT_CONFIG_TAP_ENABLED;
+ ic->tap = LIBINPUT_CONFIG_TAP_ENABLED;
} else {
- new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED;
+ ic->tap = LIBINPUT_CONFIG_TAP_DISABLED;
}
- wlr_log(WLR_DEBUG, "apply-tap for device: %s",
- current_input_config->identifier);
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/tap_button_map.c b/sway/commands/input/tap_button_map.c
index bdbba472..dff2985b 100644
--- a/sway/commands/input/tap_button_map.c
+++ b/sway/commands/input/tap_button_map.c
@@ -9,25 +9,20 @@ struct cmd_results *input_cmd_tap_button_map(int argc, char **argv) {
if ((error = checkarg(argc, "tap_button_map", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "tap_button_map",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "lrm") == 0) {
- new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
+ ic->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
} else if (strcasecmp(argv[0], "lmr") == 0) {
- new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR;
+ ic->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "tap_button_map",
"Expected 'tap_button_map <lrm|lmr>'");
}
- apply_input_config(new_config);
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 5442c463..669b4ea9 100644
--- a/sway/commands/input/xkb_capslock.c
+++ b/sway/commands/input/xkb_capslock.c
@@ -9,25 +9,20 @@ struct cmd_results *input_cmd_xkb_capslock(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_capslock", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "xkb_capslock",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "enabled") == 0) {
- new_config->xkb_capslock = 1;
+ ic->xkb_capslock = 1;
} else if (strcasecmp(argv[0], "disabled") == 0) {
- new_config->xkb_capslock = 0;
+ ic->xkb_capslock = 0;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "xkb_capslock",
"Expected 'xkb_capslock <enabled|disabled>'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c
index 9fa5a344..5fccd4a3 100644
--- a/sway/commands/input/xkb_layout.c
+++ b/sway/commands/input/xkb_layout.c
@@ -9,18 +9,15 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_layout", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
- return cmd_results_new(CMD_FAILURE, "xkb_layout", "No input device defined.");
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
+ return cmd_results_new(CMD_FAILURE, "xkb_layout",
+ "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->xkb_layout = strdup(argv[0]);
+ ic->xkb_layout = strdup(argv[0]);
- wlr_log(WLR_DEBUG, "apply-xkb_layout for device: %s layout: %s",
- current_input_config->identifier, new_config->xkb_layout);
- apply_input_config(new_config);
+ wlr_log(WLR_DEBUG, "set-xkb_layout for config: %s layout: %s",
+ ic->identifier, ic->xkb_layout);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c
index 0d082625..c4d04638 100644
--- a/sway/commands/input/xkb_model.c
+++ b/sway/commands/input/xkb_model.c
@@ -9,18 +9,15 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_model", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
- return cmd_results_new(CMD_FAILURE, "xkb_model", "No input device defined.");
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
+ return cmd_results_new(CMD_FAILURE, "xkb_model",
+ "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->xkb_model = strdup(argv[0]);
+ ic->xkb_model = strdup(argv[0]);
- wlr_log(WLR_DEBUG, "apply-xkb_model for device: %s model: %s",
- current_input_config->identifier, new_config->xkb_model);
- apply_input_config(new_config);
+ wlr_log(WLR_DEBUG, "set-xkb_model for config: %s model: %s",
+ ic->identifier, ic->xkb_model);
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 39675366..1367da44 100644
--- a/sway/commands/input/xkb_numlock.c
+++ b/sway/commands/input/xkb_numlock.c
@@ -9,25 +9,20 @@ struct cmd_results *input_cmd_xkb_numlock(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_numlock", EXPECTED_AT_LEAST, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
return cmd_results_new(CMD_FAILURE, "xkb_numlock",
"No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
if (strcasecmp(argv[0], "enabled") == 0) {
- new_config->xkb_numlock = 1;
+ ic->xkb_numlock = 1;
} else if (strcasecmp(argv[0], "disabled") == 0) {
- new_config->xkb_numlock = 0;
+ ic->xkb_numlock = 0;
} else {
- free_input_config(new_config);
return cmd_results_new(CMD_INVALID, "xkb_numlock",
"Expected 'xkb_numlock <enabled|disabled>'");
}
- apply_input_config(new_config);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c
index 3059d941..794ab6e9 100644
--- a/sway/commands/input/xkb_options.c
+++ b/sway/commands/input/xkb_options.c
@@ -9,18 +9,15 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_options", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
- return cmd_results_new(CMD_FAILURE, "xkb_options", "No input device defined.");
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
+ return cmd_results_new(CMD_FAILURE, "xkb_options",
+ "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->xkb_options = strdup(argv[0]);
+ ic->xkb_options = strdup(argv[0]);
- wlr_log(WLR_DEBUG, "apply-xkb_options for device: %s options: %s",
- current_input_config->identifier, new_config->xkb_options);
- apply_input_config(new_config);
+ wlr_log(WLR_DEBUG, "set-xkb_options for config: %s options: %s",
+ ic->identifier, ic->xkb_options);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c
index 560f088e..257c3288 100644
--- a/sway/commands/input/xkb_rules.c
+++ b/sway/commands/input/xkb_rules.c
@@ -9,18 +9,15 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_rules", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
- return cmd_results_new(CMD_FAILURE, "xkb_rules", "No input device defined.");
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
+ return cmd_results_new(CMD_FAILURE, "xkb_rules",
+ "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->xkb_rules = strdup(argv[0]);
+ ic->xkb_rules = strdup(argv[0]);
- wlr_log(WLR_DEBUG, "apply-xkb_rules for device: %s rules: %s",
- current_input_config->identifier, new_config->xkb_rules);
- apply_input_config(new_config);
+ wlr_log(WLR_DEBUG, "set-xkb_rules for config: %s rules: %s",
+ ic->identifier, ic->xkb_rules);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c
index 0aa03440..3832dc8e 100644
--- a/sway/commands/input/xkb_variant.c
+++ b/sway/commands/input/xkb_variant.c
@@ -9,18 +9,15 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) {
if ((error = checkarg(argc, "xkb_variant", EXPECTED_EQUAL_TO, 1))) {
return error;
}
- struct input_config *current_input_config =
- config->handler_context.input_config;
- if (!current_input_config) {
- return cmd_results_new(CMD_FAILURE, "xkb_variant", "No input device defined.");
+ struct input_config *ic = config->handler_context.input_config;
+ if (!ic) {
+ return cmd_results_new(CMD_FAILURE, "xkb_variant",
+ "No input device defined.");
}
- struct input_config *new_config =
- new_input_config(current_input_config->identifier);
- new_config->xkb_variant = strdup(argv[0]);
+ ic->xkb_variant = strdup(argv[0]);
- wlr_log(WLR_DEBUG, "apply-xkb_variant for device: %s variant: %s",
- current_input_config->identifier, new_config->xkb_variant);
- apply_input_config(new_config);
+ wlr_log(WLR_DEBUG, "set-xkb_variant for config: %s variant: %s",
+ ic->identifier, ic->xkb_variant);
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/move.c b/sway/commands/move.c
index 849a18ad..fc2f1cc1 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -259,50 +259,24 @@ static void container_move_to_container(struct sway_container *container,
* In other words, rejigger it. */
static void workspace_rejigger(struct sway_workspace *ws,
struct sway_container *child, enum movement_direction move_dir) {
+ if (!child->parent && ws->tiling->length == 1) {
+ ws->layout =
+ move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
+ workspace_update_representation(ws);
+ return;
+ }
container_detach(child);
- workspace_wrap_children(ws);
+ struct sway_container *new_parent = workspace_wrap_children(ws);
int index = move_dir == MOVE_LEFT || move_dir == MOVE_UP ? 0 : 1;
workspace_insert_tiling(ws, child, index);
+ container_flatten(new_parent);
ws->layout =
move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
workspace_update_representation(ws);
child->width = child->height = 0;
}
-static void move_out_of_tabs_stacks(struct sway_container *container,
- struct sway_container *current, enum movement_direction move_dir,
- int offs) {
- enum sway_container_layout layout = move_dir ==
- MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
- list_t *siblings = container_get_siblings(container);
- if (container == current && siblings->length == 1) {
- wlr_log(WLR_DEBUG, "Changing layout of parent");
- if (container->parent) {
- container->parent->layout = layout;
- container_update_representation(container);
- } else {
- container->workspace->layout = layout;
- workspace_update_representation(container->workspace);
- }
- return;
- }
-
- wlr_log(WLR_DEBUG, "Moving out of tab/stack into a split");
- if (current->parent) {
- struct sway_container *new_parent =
- container_split(current->parent, layout);
- container_insert_child(new_parent, container, offs < 0 ? 0 : 1);
- container_reap_empty(new_parent);
- container_flatten(new_parent);
- } else {
- // Changing a workspace
- struct sway_workspace *workspace = container->workspace;
- workspace_split(workspace, layout);
- workspace_insert_tiling(workspace, container, offs < 0 ? 0 : 1);
- }
-}
-
// Returns true if moved
static bool container_move_in_direction(struct sway_container *container,
enum movement_direction move_dir) {
@@ -334,7 +308,6 @@ static bool container_move_in_direction(struct sway_container *container,
int offs = move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1;
while (current) {
- struct sway_container *parent = current->parent;
list_t *siblings = container_get_siblings(current);
enum sway_container_layout layout = container_parent_layout(current);
int index = list_find(siblings, current);
@@ -343,15 +316,8 @@ static bool container_move_in_direction(struct sway_container *container,
if (is_parallel(layout, move_dir)) {
if (desired == -1 || desired == siblings->length) {
if (current->parent == container->parent) {
- if (!(parent && parent->is_fullscreen) &&
- (layout == L_TABBED || layout == L_STACKED)) {
- move_out_of_tabs_stacks(container, current,
- move_dir, offs);
- return true;
- } else {
- current = current->parent;
- continue;
- }
+ current = current->parent;
+ continue;
} else {
// Special case
if (current->parent) {
@@ -369,10 +335,6 @@ static bool container_move_in_direction(struct sway_container *container,
siblings->items[desired], move_dir);
return true;
}
- } else if (!(parent && parent->is_fullscreen) &&
- (layout == L_TABBED || layout == L_STACKED)) {
- move_out_of_tabs_stacks(container, current, move_dir, offs);
- return true;
}
current = current->parent;
@@ -388,10 +350,8 @@ static bool container_move_in_direction(struct sway_container *container,
// Maybe rejigger the workspace
struct sway_workspace *ws = container->workspace;
if (!is_parallel(ws->layout, move_dir)) {
- if (ws->tiling->length >= 2) {
- workspace_rejigger(ws, container, move_dir);
- return true;
- }
+ workspace_rejigger(ws, container, move_dir);
+ return true;
} else if (ws->layout == L_TABBED || ws->layout == L_STACKED) {
workspace_rejigger(ws, container, move_dir);
return true;
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/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);
diff --git a/sway/config.c b/sway/config.c
index 830fb65f..1e08559d 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -95,7 +95,12 @@ void free_config(struct sway_config *config) {
list_free(config->bars);
}
list_free(config->cmd_queue);
- list_free(config->workspace_outputs);
+ if (config->workspace_configs) {
+ for (int i = 0; i < config->workspace_configs->length; i++) {
+ free_workspace_config(config->workspace_configs->items[i]);
+ }
+ list_free(config->workspace_configs);
+ }
if (config->output_configs) {
for (int i = 0; i < config->output_configs->length; i++) {
free_output_config(config->output_configs->items[i]);
@@ -175,7 +180,7 @@ static void config_defaults(struct sway_config *config) {
if (!(config->symbols = create_list())) goto cleanup;
if (!(config->modes = create_list())) goto cleanup;
if (!(config->bars = create_list())) goto cleanup;
- if (!(config->workspace_outputs = create_list())) goto cleanup;
+ if (!(config->workspace_configs = create_list())) goto cleanup;
if (!(config->criteria = create_list())) goto cleanup;
if (!(config->no_focus = create_list())) goto cleanup;
if (!(config->input_configs = create_list())) goto cleanup;
@@ -804,7 +809,7 @@ char *do_var_replacement(char *str) {
// would compare two structs in full, while this method only compares the
// workspace.
int workspace_output_cmp_workspace(const void *a, const void *b) {
- const struct workspace_output *wsa = a, *wsb = b;
+ const struct workspace_config *wsa = a, *wsb = b;
return lenient_strcmp(wsa->workspace, wsb->workspace);
}
diff --git a/sway/config/bar.c b/sway/config/bar.c
index f83b37d1..48a632fb 100644
--- a/sway/config/bar.c
+++ b/sway/config/bar.c
@@ -165,7 +165,7 @@ cleanup:
return NULL;
}
-void invoke_swaybar(struct bar_config *bar) {
+static void invoke_swaybar(struct bar_config *bar) {
// Pipe to communicate errors
int filedes[2];
if (pipe(filedes) == -1) {
@@ -219,27 +219,13 @@ void invoke_swaybar(struct bar_config *bar) {
close(filedes[1]);
}
-void load_swaybars() {
+void load_swaybars(void) {
for (int i = 0; i < config->bars->length; ++i) {
struct bar_config *bar = config->bars->items[i];
- bool apply = false;
- if (bar->outputs) {
- for (int j = 0; j < bar->outputs->length; ++j) {
- char *o = bar->outputs->items[j];
- if (!strcmp(o, "*") || output_by_name(o)) {
- apply = true;
- break;
- }
- }
- } else {
- apply = true;
- }
- if (apply) {
- if (bar->pid != 0) {
- terminate_swaybar(bar->pid);
- }
- wlr_log(WLR_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
- invoke_swaybar(bar);
+ if (bar->pid != 0) {
+ terminate_swaybar(bar->pid);
}
+ wlr_log(WLR_DEBUG, "Invoking swaybar for bar id '%s'", bar->id);
+ invoke_swaybar(bar);
}
}
diff --git a/sway/config/input.c b/sway/config/input.c
index ad5b96c8..794d5194 100644
--- a/sway/config/input.c
+++ b/sway/config/input.c
@@ -20,6 +20,7 @@ struct input_config *new_input_config(const char* identifier) {
input->tap = INT_MIN;
input->tap_button_map = INT_MIN;
+ input->drag = INT_MIN;
input->drag_lock = INT_MIN;
input->dwt = INT_MIN;
input->send_events = INT_MIN;
@@ -40,22 +41,24 @@ struct input_config *new_input_config(const char* identifier) {
}
void merge_input_config(struct input_config *dst, struct input_config *src) {
- if (src->identifier) {
- free(dst->identifier);
- dst->identifier = strdup(src->identifier);
- }
if (src->accel_profile != INT_MIN) {
dst->accel_profile = src->accel_profile;
}
if (src->click_method != INT_MIN) {
dst->click_method = src->click_method;
}
+ if (src->drag != INT_MIN) {
+ dst->drag = src->drag;
+ }
if (src->drag_lock != INT_MIN) {
dst->drag_lock = src->drag_lock;
}
if (src->dwt != INT_MIN) {
dst->dwt = src->dwt;
}
+ if (src->left_handed != INT_MIN) {
+ dst->left_handed = src->left_handed;
+ }
if (src->middle_emulation != INT_MIN) {
dst->middle_emulation = src->middle_emulation;
}
@@ -125,14 +128,51 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
}
}
-struct input_config *copy_input_config(struct input_config *ic) {
- struct input_config *copy = calloc(1, sizeof(struct input_config));
- if (copy == NULL) {
- wlr_log(WLR_ERROR, "could not allocate input config");
- return NULL;
+static void merge_wildcard_on_all(struct input_config *wildcard) {
+ for (int i = 0; i < config->input_configs->length; i++) {
+ struct input_config *ic = config->input_configs->items[i];
+ if (strcmp(wildcard->identifier, ic->identifier) != 0) {
+ wlr_log(WLR_DEBUG, "Merging input * config on %s", ic->identifier);
+ merge_input_config(ic, wildcard);
+ }
}
- merge_input_config(copy, ic);
- return copy;
+}
+
+struct input_config *store_input_config(struct input_config *ic) {
+ bool wildcard = strcmp(ic->identifier, "*") == 0;
+ if (wildcard) {
+ merge_wildcard_on_all(ic);
+ }
+
+ int i = list_seq_find(config->input_configs, input_identifier_cmp,
+ ic->identifier);
+ if (i >= 0) {
+ wlr_log(WLR_DEBUG, "Merging on top of existing input config");
+ struct input_config *current = config->input_configs->items[i];
+ merge_input_config(current, ic);
+ free_input_config(ic);
+ ic = current;
+ } else if (!wildcard) {
+ wlr_log(WLR_DEBUG, "Adding non-wildcard input config");
+ i = list_seq_find(config->input_configs, input_identifier_cmp, "*");
+ if (i >= 0) {
+ wlr_log(WLR_DEBUG, "Merging on top of input * config");
+ struct input_config *current = new_input_config(ic->identifier);
+ merge_input_config(current, config->input_configs->items[i]);
+ merge_input_config(current, ic);
+ free_input_config(ic);
+ ic = current;
+ }
+ list_add(config->input_configs, ic);
+ } else {
+ // New wildcard config. Just add it
+ wlr_log(WLR_DEBUG, "Adding input * config");
+ list_add(config->input_configs, ic);
+ }
+
+ wlr_log(WLR_DEBUG, "Config stored for input %s", ic->identifier);
+
+ return ic;
}
void free_input_config(struct input_config *ic) {
diff --git a/sway/config/output.c b/sway/config/output.c
index 74d79130..6f337b66 100644
--- a/sway/config/output.c
+++ b/sway/config/output.c
@@ -237,7 +237,7 @@ void apply_output_config(struct output_config *oc, struct sway_output *output) {
wlr_log(WLR_DEBUG, "Setting background for output %d to %s",
output_i, oc->background);
- size_t len = snprintf(NULL, 0, "%s %d %s %s %s",
+ size_t len = snprintf(NULL, 0, "%s %d \"%s\" %s %s",
config->swaybg_command ? config->swaybg_command : "swaybg",
output_i, oc->background, oc->background_option,
oc->background_fallback ? oc->background_fallback : "");
@@ -246,7 +246,7 @@ void apply_output_config(struct output_config *oc, struct sway_output *output) {
wlr_log(WLR_DEBUG, "Unable to allocate swaybg command");
return;
}
- snprintf(command, len + 1, "%s %d %s %s %s",
+ snprintf(command, len + 1, "%s %d \"%s\" %s %s",
config->swaybg_command ? config->swaybg_command : "swaybg",
output_i, oc->background, oc->background_option,
oc->background_fallback ? oc->background_fallback : "");
diff --git a/sway/config/seat.c b/sway/config/seat.c
index 83dac4c0..46456caf 100644
--- a/sway/config/seat.c
+++ b/sway/config/seat.c
@@ -30,7 +30,7 @@ struct seat_config *new_seat_config(const char* name) {
return seat;
}
-struct seat_attachment_config *seat_attachment_config_new() {
+struct seat_attachment_config *seat_attachment_config_new(void) {
struct seat_attachment_config *attachment =
calloc(1, sizeof(struct seat_attachment_config));
if (!attachment) {
diff --git a/sway/debug-tree.c b/sway/debug-tree.c
index 9644f4e5..16b479f9 100644
--- a/sway/debug-tree.c
+++ b/sway/debug-tree.c
@@ -120,7 +120,7 @@ static int draw_node(cairo_t *cairo, struct sway_node *node,
return height;
}
-void update_debug_tree() {
+void update_debug_tree(void) {
if (!debug.render_tree) {
return;
}
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index d747e279..34d99d52 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <time.h>
#include <wlr/types/wlr_buffer.h>
+#include "sway/config.h"
#include "sway/debug.h"
#include "sway/desktop.h"
#include "sway/desktop/idle_inhibit_v1.h"
@@ -30,14 +31,14 @@ struct sway_transaction_instruction {
struct sway_transaction *transaction;
struct sway_node *node;
union {
- struct sway_output_state *output_state;
- struct sway_workspace_state *workspace_state;
- struct sway_container_state *container_state;
+ struct sway_output_state output_state;
+ struct sway_workspace_state workspace_state;
+ struct sway_container_state container_state;
};
uint32_t serial;
};
-static struct sway_transaction *transaction_create() {
+static struct sway_transaction *transaction_create(void) {
struct sway_transaction *transaction =
calloc(1, sizeof(struct sway_transaction));
if (!sway_assert(transaction, "Unable to allocate transaction")) {
@@ -85,14 +86,7 @@ static void transaction_destroy(struct sway_transaction *transaction) {
static void copy_output_state(struct sway_output *output,
struct sway_transaction_instruction *instruction) {
- struct sway_output_state *state =
- calloc(1, sizeof(struct sway_output_state));
- if (!state) {
- wlr_log(WLR_ERROR, "Could not allocate output state");
- return;
- }
- instruction->output_state = state;
-
+ struct sway_output_state *state = &instruction->output_state;
state->workspaces = create_list();
list_cat(state->workspaces, output->workspaces);
@@ -101,13 +95,7 @@ static void copy_output_state(struct sway_output *output,
static void copy_workspace_state(struct sway_workspace *ws,
struct sway_transaction_instruction *instruction) {
- struct sway_workspace_state *state =
- calloc(1, sizeof(struct sway_workspace_state));
- if (!state) {
- wlr_log(WLR_ERROR, "Could not allocate workspace state");
- return;
- }
- instruction->workspace_state = state;
+ struct sway_workspace_state *state = &instruction->workspace_state;
state->fullscreen = ws->fullscreen;
state->x = ws->x;
@@ -137,13 +125,7 @@ static void copy_workspace_state(struct sway_workspace *ws,
static void copy_container_state(struct sway_container *container,
struct sway_transaction_instruction *instruction) {
- struct sway_container_state *state =
- calloc(1, sizeof(struct sway_container_state));
- if (!state) {
- wlr_log(WLR_ERROR, "Could not allocate container state");
- return;
- }
- instruction->container_state = state;
+ struct sway_container_state *state = &instruction->container_state;
state->layout = container->layout;
state->con_x = container->x;
@@ -300,15 +282,15 @@ static void transaction_apply(struct sway_transaction *transaction) {
case N_ROOT:
break;
case N_OUTPUT:
- apply_output_state(node->sway_output, instruction->output_state);
+ apply_output_state(node->sway_output, &instruction->output_state);
break;
case N_WORKSPACE:
apply_workspace_state(node->sway_workspace,
- instruction->workspace_state);
+ &instruction->workspace_state);
break;
case N_CONTAINER:
apply_container_state(node->sway_container,
- instruction->container_state);
+ &instruction->container_state);
break;
}
@@ -334,7 +316,7 @@ static bool transaction_same_nodes(struct sway_transaction *a,
return true;
}
-static void transaction_progress_queue() {
+static void transaction_progress_queue(void) {
if (!server.transactions->length) {
return;
}
@@ -389,7 +371,17 @@ static bool should_configure(struct sway_node *node,
return false;
}
struct sway_container_state *cstate = &node->sway_container->current;
- struct sway_container_state *istate = instruction->container_state;
+ struct sway_container_state *istate = &instruction->container_state;
+#ifdef HAVE_XWAYLAND
+ // Xwayland views are position-aware and need to be reconfigured
+ // when their position changes.
+ if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) {
+ if (cstate->view_x != istate->view_x ||
+ cstate->view_y != istate->view_y) {
+ return true;
+ }
+ }
+#endif
if (cstate->view_width == istate->view_width &&
cstate->view_height == istate->view_height) {
return false;
@@ -407,10 +399,10 @@ static void transaction_commit(struct sway_transaction *transaction) {
struct sway_node *node = instruction->node;
if (should_configure(node, instruction)) {
instruction->serial = view_configure(node->sway_container->view,
- instruction->container_state->view_x,
- instruction->container_state->view_y,
- instruction->container_state->view_width,
- instruction->container_state->view_height);
+ instruction->container_state.view_x,
+ instruction->container_state.view_y,
+ instruction->container_state.view_width,
+ instruction->container_state.view_height);
++transaction->num_waiting;
// From here on we are rendering a saved buffer of the view, which
@@ -502,8 +494,8 @@ void transaction_notify_view_ready_by_size(struct sway_view *view,
int width, int height) {
struct sway_transaction_instruction *instruction =
view->container->node.instruction;
- if (instruction->container_state->view_width == width &&
- instruction->container_state->view_height == height) {
+ if (instruction->container_state.view_width == width &&
+ instruction->container_state.view_height == height) {
set_instruction_ready(instruction);
}
}
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 00448be7..6d1ccdd7 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -401,7 +401,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
} else {
if (view->container->parent) {
arrange_container(view->container->parent);
- } else {
+ } else if (view->container->workspace) {
arrange_workspace(view->container->workspace);
}
}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index d2c9a68b..95ca396c 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -398,7 +398,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
} else {
if (view->container->parent) {
arrange_container(view->container->parent);
- } else {
+ } else if (view->container->workspace) {
arrange_workspace(view->container->workspace);
}
}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 3619f202..a12ac854 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -394,7 +394,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
} else {
if (view->container->parent) {
arrange_container(view->container->parent);
- } else {
+ } else if (view->container->workspace) {
arrange_workspace(view->container->workspace);
}
}
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 85951c09..3ddc27a0 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -30,7 +30,7 @@
// when dragging to the edge of a layout container.
#define DROP_LAYOUT_BORDER 30
-static uint32_t get_current_time_msec() {
+static uint32_t get_current_time_msec(void) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_nsec / 1000;
@@ -897,7 +897,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
// Handle moving a tiling container
if (config->tiling_drag && mod_pressed && state == WLR_BUTTON_PRESSED &&
- !is_floating_or_child && !cont->is_fullscreen) {
+ !is_floating_or_child && cont && !cont->is_fullscreen) {
seat_pointer_notify_button(seat, time_msec, button, state);
seat_begin_move_tiling(seat, cont, button);
return;
@@ -911,9 +911,10 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
return;
}
- // Handle clicking a container surface
+ // Handle clicking a container surface or decorations
if (cont) {
- seat_set_focus_container(seat, cont);
+ node = seat_get_focus_inactive(seat, &cont->node);
+ seat_set_focus(seat, node);
seat_pointer_notify_button(seat, time_msec, button, state);
return;
}
@@ -930,12 +931,52 @@ static void handle_cursor_button(struct wl_listener *listener, void *data) {
transaction_commit_dirty();
}
+static void dispatch_cursor_axis(struct sway_cursor *cursor,
+ struct wlr_event_pointer_axis *event) {
+ struct sway_seat *seat = cursor->seat;
+
+ // Determine what's under the cursor
+ struct wlr_surface *surface = NULL;
+ double sx, sy;
+ struct sway_node *node = node_at_coords(seat,
+ cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
+ struct sway_container *cont = node && node->type == N_CONTAINER ?
+ node->sway_container : NULL;
+ enum wlr_edges edge = cont ? find_edge(cont, cursor) : WLR_EDGE_NONE;
+ bool on_border = edge != WLR_EDGE_NONE;
+ bool on_titlebar = cont && !on_border && !surface;
+
+ // Scrolling on a tabbed or stacked title bar
+ if (on_titlebar) {
+ enum sway_container_layout layout = container_parent_layout(cont);
+ if (layout == L_TABBED || layout == L_STACKED) {
+ struct sway_node *active =
+ seat_get_active_tiling_child(seat, node_get_parent(node));
+ list_t *siblings = container_get_siblings(cont);
+ int desired = list_find(siblings, active->sway_container) +
+ event->delta_discrete;
+ if (desired < 0) {
+ desired = 0;
+ } else if (desired >= siblings->length) {
+ desired = siblings->length - 1;
+ }
+ struct sway_container *new_focus = siblings->items[desired];
+ node = seat_get_focus_inactive(seat, &new_focus->node);
+ seat_set_focus(seat, node);
+ return;
+ }
+ }
+
+ wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
+ event->orientation, event->delta, event->delta_discrete, event->source);
+}
+
static void handle_cursor_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
wlr_idle_notify_activity(cursor->seat->input->server->idle, cursor->seat->wlr_seat);
struct wlr_event_pointer_axis *event = data;
- wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
- event->orientation, event->delta, event->delta_discrete, event->source);
+ dispatch_cursor_axis(cursor, event);
+ transaction_commit_dirty();
}
static void handle_touch_down(struct wl_listener *listener, void *data) {
@@ -965,8 +1006,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
if (seat_is_input_allowed(seat, surface)) {
wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
event->touch_id, sx, sy);
- cursor->image_client = NULL;
- wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
+ cursor_set_image(cursor, NULL, NULL);
}
}
@@ -1134,11 +1174,13 @@ static void handle_request_set_cursor(struct wl_listener *listener,
void cursor_set_image(struct sway_cursor *cursor, const char *image,
struct wl_client *client) {
- if (!cursor->image || strcmp(cursor->image, image) != 0) {
+ if (!image) {
+ wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0);
+ } else if (!cursor->image || strcmp(cursor->image, image) != 0) {
wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image,
cursor->cursor);
- cursor->image = image;
}
+ cursor->image = image;
cursor->image_client = client;
}
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index b4352c6a..32f0355e 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -120,6 +120,13 @@ static void input_manager_libinput_config_pointer(
libinput_device_config_click_set_method(libinput_device,
ic->click_method);
}
+ if (ic->drag != INT_MIN) {
+ wlr_log(WLR_DEBUG,
+ "libinput_config_pointer(%s) tap_set_drag_enabled(%d)",
+ ic->identifier, ic->click_method);
+ libinput_device_config_tap_set_drag_enabled(libinput_device,
+ ic->drag);
+ }
if (ic->drag_lock != INT_MIN) {
wlr_log(WLR_DEBUG,
"libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)",
@@ -233,7 +240,8 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
wlr_log(WLR_DEBUG, "adding device: '%s'",
input_device->identifier);
- if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) {
+ if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER ||
+ input_device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) {
input_manager_libinput_config_pointer(input_device);
}
@@ -389,9 +397,12 @@ void input_manager_set_focus(struct sway_input_manager *input,
void input_manager_apply_input_config(struct sway_input_manager *input,
struct input_config *input_config) {
struct sway_input_device *input_device = NULL;
+ bool wildcard = strcmp(input_config->identifier, "*") == 0;
wl_list_for_each(input_device, &input->devices, link) {
- if (strcmp(input_device->identifier, input_config->identifier) == 0) {
- if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER) {
+ if (strcmp(input_device->identifier, input_config->identifier) == 0
+ || wildcard) {
+ if (input_device->wlr_device->type == WLR_INPUT_DEVICE_POINTER ||
+ input_device->wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL) {
input_manager_libinput_config_pointer(input_device);
}
@@ -480,13 +491,16 @@ struct sway_seat *input_manager_get_default_seat(
}
struct input_config *input_device_get_config(struct sway_input_device *device) {
+ struct input_config *wildcard_config = NULL;
struct input_config *input_config = NULL;
for (int i = 0; i < config->input_configs->length; ++i) {
input_config = config->input_configs->items[i];
if (strcmp(input_config->identifier, device->identifier) == 0) {
return input_config;
+ } else if (strcmp(input_config->identifier, "*") == 0) {
+ wildcard_config = input_config;
}
}
- return NULL;
+ return wildcard_config;
}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 49fe46ba..4817eae7 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -348,17 +348,42 @@ struct sway_seat *seat_create(struct sway_input_manager *input,
seat->input = input;
wl_list_init(&seat->devices);
- wlr_seat_set_capabilities(seat->wlr_seat,
- WL_SEAT_CAPABILITY_KEYBOARD |
- WL_SEAT_CAPABILITY_POINTER |
- WL_SEAT_CAPABILITY_TOUCH);
-
-
wl_list_insert(&input->seats, &seat->link);
return seat;
}
+static void seat_update_capabilities(struct sway_seat *seat) {
+ uint32_t caps = 0;
+ struct sway_seat_device *seat_device;
+ wl_list_for_each(seat_device, &seat->devices, link) {
+ switch (seat_device->input_device->wlr_device->type) {
+ case WLR_INPUT_DEVICE_KEYBOARD:
+ caps |= WL_SEAT_CAPABILITY_KEYBOARD;
+ break;
+ case WLR_INPUT_DEVICE_POINTER:
+ caps |= WL_SEAT_CAPABILITY_POINTER;
+ break;
+ case WLR_INPUT_DEVICE_TOUCH:
+ caps |= WL_SEAT_CAPABILITY_TOUCH;
+ break;
+ case WLR_INPUT_DEVICE_TABLET_TOOL:
+ caps |= WL_SEAT_CAPABILITY_POINTER;
+ break;
+ case WLR_INPUT_DEVICE_TABLET_PAD:
+ break;
+ }
+ }
+ wlr_seat_set_capabilities(seat->wlr_seat, caps);
+
+ // Hide cursor if seat doesn't have pointer capability
+ if ((caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
+ cursor_set_image(seat->cursor, NULL, NULL);
+ } else {
+ cursor_set_image(seat->cursor, "left_ptr", NULL);
+ }
+}
+
static void seat_apply_input_config(struct sway_seat *seat,
struct sway_seat_device *sway_device) {
const char *mapped_to_output = NULL;
@@ -489,6 +514,8 @@ void seat_add_device(struct sway_seat *seat,
wl_list_insert(&seat->devices, &seat_device->link);
seat_configure_device(seat, input_device);
+
+ seat_update_capabilities(seat);
}
void seat_remove_device(struct sway_seat *seat,
@@ -503,6 +530,8 @@ void seat_remove_device(struct sway_seat *seat,
input_device->identifier, seat->wlr_seat->name);
seat_device_destroy(seat_device);
+
+ seat_update_capabilities(seat);
}
void seat_configure_xcursor(struct sway_seat *seat) {
@@ -532,8 +561,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
output->name, (double)output->scale);
}
- wlr_xcursor_manager_set_cursor_image(seat->cursor->xcursor_manager,
- "left_ptr", seat->cursor->cursor);
+ cursor_set_image(seat->cursor, "left_ptr", NULL);
wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
seat->cursor->cursor->y);
}
diff --git a/sway/ipc-json.c b/sway/ipc-json.c
index f054ac9f..45915094 100644
--- a/sway/ipc-json.c
+++ b/sway/ipc-json.c
@@ -42,7 +42,7 @@ static const char *ipc_json_orientation_description(enum sway_container_layout l
return "none";
}
-json_object *ipc_json_get_version() {
+json_object *ipc_json_get_version(void) {
int major = 0, minor = 0, patch = 0;
json_object *version = json_object_new_object();
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 8ae265f6..2d915502 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -1,8 +1,5 @@
// See https://i3wm.org/docs/ipc.html for protocol information
-#ifndef __FreeBSD__
-// Any value will hide SOCK_CLOEXEC on FreeBSD (__BSD_VISIBLE=0)
-#define _XOPEN_SOURCE 700
-#endif
+#define _POSIX_C_SOURCE 200112L
#ifdef __linux__
#include <linux/input-event-codes.h>
#elif __FreeBSD__
@@ -89,10 +86,16 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) {
}
void ipc_init(struct sway_server *server) {
- ipc_socket = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+ ipc_socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (ipc_socket == -1) {
sway_abort("Unable to create IPC socket");
}
+ if (fcntl(ipc_socket, F_SETFD, FD_CLOEXEC) == -1) {
+ sway_abort("Unable to set CLOEXEC on IPC socket");
+ }
+ if (fcntl(ipc_socket, F_SETFL, O_NONBLOCK) == -1) {
+ sway_abort("Unable to set NONBLOCK on IPC socket");
+ }
ipc_sockaddr = ipc_user_sockaddr();
@@ -580,7 +583,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
switch (client->current_command) {
case IPC_COMMAND:
{
- struct cmd_results *results = execute_command(buf, NULL);
+ struct cmd_results *results = execute_command(buf, NULL, NULL);
transaction_commit_dirty();
char *json = cmd_results_to_json(results);
int length = strlen(json);
diff --git a/sway/main.c b/sway/main.c
index fb4f0d8c..dea4a31c 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -12,10 +12,6 @@
#include <sys/wait.h>
#include <sys/un.h>
#include <unistd.h>
-#ifdef __linux__
-#include <sys/capability.h>
-#include <sys/prctl.h>
-#endif
#include <wlr/util/log.h>
#include "sway/commands.h"
#include "sway/config.h"
@@ -45,7 +41,7 @@ void sig_handler(int signal) {
sway_terminate(EXIT_SUCCESS);
}
-void detect_raspi() {
+void detect_raspi(void) {
bool raspi = false;
FILE *f = fopen("/sys/firmware/devicetree/base/model", "r");
if (!f) {
@@ -85,7 +81,7 @@ void detect_raspi() {
}
}
-void detect_proprietary() {
+void detect_proprietary(void) {
FILE *f = fopen("/proc/modules", "r");
if (!f) {
return;
@@ -120,7 +116,7 @@ void run_as_ipc_client(char *command, char *socket_path) {
close(socketfd);
}
-static void log_env() {
+static void log_env(void) {
const char *log_vars[] = {
"PATH",
"LD_LIBRARY_PATH",
@@ -135,7 +131,7 @@ static void log_env() {
}
}
-static void log_distro() {
+static void log_distro(void) {
const char *paths[] = {
"/etc/lsb-release",
"/etc/os-release",
@@ -162,7 +158,7 @@ static void log_distro() {
}
}
-static void log_kernel() {
+static void log_kernel(void) {
FILE *f = popen("uname -a", "r");
if (!f) {
wlr_log(WLR_INFO, "Unable to determine kernel version");
@@ -181,28 +177,8 @@ static void log_kernel() {
pclose(f);
}
-static void executable_sanity_check() {
-#ifdef __linux__
- struct stat sb;
- char *exe = realpath("/proc/self/exe", NULL);
- stat(exe, &sb);
- // We assume that cap_get_file returning NULL implies ENODATA
- if (sb.st_mode & (S_ISUID|S_ISGID) && cap_get_file(exe)) {
- wlr_log(WLR_ERROR,
- "sway executable has both the s(g)uid bit AND file caps set.");
- wlr_log(WLR_ERROR,
- "This is strongly discouraged (and completely broken).");
- wlr_log(WLR_ERROR,
- "Please clear one of them (either the suid bit, or the file caps).");
- wlr_log(WLR_ERROR,
- "If unsure, strip the file caps.");
- exit(EXIT_FAILURE);
- }
- free(exe);
-#endif
-}
-static void drop_permissions(bool keep_caps) {
+static void drop_permissions(void) {
if (getuid() != geteuid() || getgid() != getegid()) {
if (setgid(getgid()) != 0) {
wlr_log(WLR_ERROR, "Unable to drop root");
@@ -217,20 +193,6 @@ static void drop_permissions(bool keep_caps) {
wlr_log(WLR_ERROR, "Root privileges can be restored.");
exit(EXIT_FAILURE);
}
-#ifdef __linux__
- if (keep_caps) {
- // Drop every cap except CAP_SYS_PTRACE
- cap_t caps = cap_init();
- cap_value_t keep = CAP_SYS_PTRACE;
- wlr_log(WLR_INFO, "Dropping extra capabilities");
- if (cap_set_flag(caps, CAP_PERMITTED, 1, &keep, CAP_SET) ||
- cap_set_flag(caps, CAP_EFFECTIVE, 1, &keep, CAP_SET) ||
- cap_set_proc(caps)) {
- wlr_log(WLR_ERROR, "Failed to drop extra capabilities");
- exit(EXIT_FAILURE);
- }
- }
-#endif
}
void enable_debug_flag(const char *flag) {
@@ -279,14 +241,6 @@ int main(int argc, char **argv) {
" --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
"\n";
- // Security:
- unsetenv("LD_PRELOAD");
-#ifdef _LD_LIBRARY_PATH
- setenv("LD_LIBRARY_PATH", _LD_LIBRARY_PATH, 1);
-#else
- unsetenv("LD_LIBRARY_PATH");
-#endif
-
int c;
while (1) {
int option_index = 0;
@@ -347,7 +301,7 @@ int main(int argc, char **argv) {
wlr_log(WLR_ERROR, "Don't use options with the IPC client");
exit(EXIT_FAILURE);
}
- drop_permissions(false);
+ drop_permissions();
char *socket_path = getenv("SWAYSOCK");
if (!socket_path) {
wlr_log(WLR_ERROR, "Unable to retrieve socket path");
@@ -358,34 +312,17 @@ int main(int argc, char **argv) {
return 0;
}
- executable_sanity_check();
- bool suid = false;
-
if (!server_privileged_prepare(&server)) {
return 1;
}
-#if defined(__linux__) || defined(__FreeBSD__)
- if (getuid() != geteuid() || getgid() != getegid()) {
-#ifdef __linux__
- // Retain capabilities after setuid()
- if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
- wlr_log(WLR_ERROR, "Cannot keep caps after setuid()");
- exit(EXIT_FAILURE);
- }
-#endif
- suid = true;
- }
-#endif
-
log_kernel();
log_distro();
detect_proprietary();
detect_raspi();
-#if defined(__linux__) || defined(__FreeBSD__)
- drop_permissions(suid);
-#endif
+ drop_permissions();
+
// handle SIGTERM signals
signal(SIGTERM, sig_handler);
@@ -424,11 +361,12 @@ int main(int argc, char **argv) {
}
config->active = true;
+ load_swaybars();
// Execute commands until there are none left
wlr_log(WLR_DEBUG, "Running deferred commands");
while (config->cmd_queue->length) {
char *line = config->cmd_queue->items[0];
- struct cmd_results *res = execute_command(line, NULL);
+ struct cmd_results *res = execute_command(line, NULL, NULL);
if (res->status != CMD_SUCCESS) {
wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
}
diff --git a/sway/meson.build b/sway/meson.build
index d67a4c64..6eb9a9d7 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -119,6 +119,7 @@ sway_sources = files(
'commands/input/accel_profile.c',
'commands/input/click_method.c',
+ 'commands/input/drag.c',
'commands/input/drag_lock.c',
'commands/input/dwt.c',
'commands/input/events.c',
@@ -164,7 +165,6 @@ sway_deps = [
cairo,
gdk_pixbuf,
jsonc,
- libcap,
libinput,
math,
pango,
@@ -187,5 +187,6 @@ executable(
include_directories: [sway_inc],
dependencies: sway_deps,
link_with: [lib_sway_common],
+ install_rpath : rpathdir,
install: true
)
diff --git a/sway/sway-bar.5.scd b/sway/sway-bar.5.scd
index a61e2829..00b9386e 100644
--- a/sway/sway-bar.5.scd
+++ b/sway/sway-bar.5.scd
@@ -6,8 +6,7 @@ sway-bar - bar configuration file and commands
# DESCRIPTION
-Sway allows configuring swaybar in the sway configuration file. Swaybar
-commands must be used inside a _bar { }_ block in the config file.
+Sway allows configuring swaybar in the sway configuration file.
# COMMANDS
diff --git a/sway/sway-input.5.scd b/sway/sway-input.5.scd
index 707c36af..14f2a007 100644
--- a/sway/sway-input.5.scd
+++ b/sway/sway-input.5.scd
@@ -7,7 +7,6 @@ sway-input - input configuration file and commands
# DESCRIPTION
Sway allows for configuration of devices within the sway configuration file.
-sway-input commands must be used inside an _input { }_ block in the config.
To obtain a list of available device identifiers, run *swaymsg -t get\_inputs*.
# INPUT COMMANDS
@@ -68,6 +67,9 @@ The following commands may only be used in the configuration file.
*input* <identifier> click\_method none|button\_areas|clickfinger
Changes the click method for the specified device.
+*input* <identifier> drag enabled|disabled
+ Enables or disables tap-and-drag for specified input device.
+
*input* <identifier> drag\_lock enabled|disabled
Enables or disables drag lock for specified input device.
@@ -116,8 +118,7 @@ The following commands may only be used in the configuration file.
## SEAT CONFIGURATION
-Configure options for multiseat mode. sway-seat commands must be used inside a
-_seat { }_ block in the config.
+Configure options for multiseat mode.
A *seat* is a collection of input devices that act independently of each other.
Seats are identified by name and the default seat is _seat0_ if no seats are
diff --git a/sway/sway.5.scd b/sway/sway.5.scd
index 927bf55c..aa5b38ab 100644
--- a/sway/sway.5.scd
+++ b/sway/sway.5.scd
@@ -19,6 +19,24 @@ bindsym Shift+XF86AudioRaiseVolume exec \\
pactl set-sink-volume @DEFAULT_SINK@ -1%
```
+Commands can also be given as a block in the form *command { <subcommands...>
+}*. Anything before the opening *{* will be prepended to the lines inside the
+block. For example:
+
+```
+output eDP-1 {
+ background ~/wallpaper.png
+ resolution 1920x1080
+}
+```
+
+is identical to
+
+```
+output eDP-1 background ~/wallpaper.png
+output eDP-1 resolution 1920x1080
+```
+
These commands can be executed in your config file, via *swaymsg*(1), or via
the bindsym command.
@@ -37,10 +55,8 @@ which you may only select one. *[...]* is used for optional arguments, and
The following commands may only be used in the configuration file.
-*bar {* <commands...> *}*
- _commands..._ after *{* will be interpreted as bar commands. For
- details, see *sway-bar*(5). A newline is required between *{* and the
- first command, and *}* must be alone on a line.
+*bar* [<bar-id>] <bar-subcommands...>
+ For details on bar subcommands, see *sway-bar*(5).
*default\_orientation* horizontal|vertical|auto
Sets the default container layout for tiled containers.
@@ -51,10 +67,6 @@ The following commands may only be used in the configuration file.
*wordexp*(3) for details). The same include file can only be included once;
subsequent attempts will be ignored.
-*set* $<name> <value>
- Sets variable $_name_ to _value_. You can use the new variable in the
- arguments of future commands.
-
*swaybg\_command* <command>
Executes custom background _command_. Default is _swaybg_. Refer to
*output* below for more information.
@@ -407,37 +419,30 @@ The default colors are:
inner gap is nonzero. When _off_, gaps will only be added between views.
_toggle_ cannot be used in the configuration file.
-*gaps* <amount>
- Sets _amount_ pixels of gap between windows and around each workspace.
-
*gaps* inner|outer <amount>
- Sets default _amount_ pixels of _inner_ or _outer_ gap, where the former
- affects spacing between views and the latter affects the space around each
- workspace.
+ Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
+ affects spacing around each view and outer affects the spacing around each
+ workspace. Outer gaps are in addition to inner gaps.
+
+ This affects new workspaces only, and is used when the workspace doesn't
+ have its own gaps settings (see: workspace <ws> gaps inner|outer <amount>).
-*gaps* inner|outer all|workspace|current set|plus|minus <amount>
- Changes the gaps for the _inner_ or _outer_ gap. _all_ changes the gaps for
- all views or workspace, _workspace_ changes gaps for all views in current
- workspace (or current workspace), and _current_ changes gaps for the current
- view or workspace.
+*gaps* inner|outer all|current set|plus|minus <amount>
+ Changes the _inner_ or _outer_ gaps for either _all_ workspaces or the
+ _current_ workspace.
*hide\_edge\_borders* none|vertical|horizontal|both|smart
Hides window borders adjacent to the screen edges. Default is _none_.
-*input* <input\_device> *{* <commands...> *}*
- _commands..._ after *{* will be interpreted as input commands applying to
- the specified input device. For details, see *sway-input*(5). A newline is
- required between *{* and the first command, and *}* must be alone on a
- line.
+*input* <input\_device> <input-subcommands...>
+ For details on input subcommands, see *sway-input*(5).
\* may be used in lieu of a specific device name to configure all input
devices. A list of input device names may be obtained via *swaymsg -t
get\_inputs*.
-*seat* <seat> *{* <commands...> *}*
- _commands..._ after *{* will be interpreted as seat commands applying to
- the specified seat. For details, see *sway-input*(5). A newline is required
- between *{* and the first command, and *}* must be alone on a line.
+*seat* <seat> <seat-subcommands...>
+ For details on seat subcommands, see *sway-input*(5).
*seat* <seat> cursor move|set <x> <y>
Move specified seat's cursor relative to current position or wrap to
@@ -465,10 +470,8 @@ The default colors are:
*mode* <mode>
Switches to the specified mode. The default mode _default_.
-*mode* [--pango\_markup] <mode> *{* <commands...> *}*
- _commands..._ after *{* will be added to the specified mode. A newline is
- required between *{* and the first command, and *}* must be alone on a
- line. Only *bindsym* and *bindcode* commands are permitted in mode blocks.
+*mode* [--pango\_markup] <mode> <mode-subcommands...>
+ The only two valid _mode-subcommands..._ are *bindsym* and *bindcode*.
If _--pango\_markup_ is given, then _mode_ will be interpreted as pango
markup.
@@ -533,8 +536,15 @@ You may combine output commands into one, like so:
output HDMI-A-1 mode 1920x1080 pos 1920,0 bg ~/wallpaper.png stretch
You can get a list of output names with *swaymsg -t get\_outputs*. You may also
-match any output by using the output name "\*". Be sure to add this output
-config after the others, or it will be matched instead of the others.
+match any output by using the output name "\*".
+
+*set* $<name> <value>
+ Sets variable $_name_ to _value_. You can use the new variable in the
+ arguments of future commands. When the variable is used, it can be escaped
+ with an additional $ (ie $$_name_) to have the replacement happen at run
+ time instead of when reading the config. However, it does not always make
+ sense for the variable to be replaced at run time since some arguments do
+ need to be known at config time.
*show\_marks* yes|no
If *show\_marks* is yes, marks will be displayed in the window borders.
@@ -568,6 +578,10 @@ config after the others, or it will be matched instead of the others.
*workspace* back_and_forth
Switches to the previously focused workspace.
+*workspace* <name> gaps inner|outer <amount>
+ Specifies that workspace _name_ should have the given gaps settings when it
+ is created.
+
*workspace* <name> output <output>
Specifies that workspace _name_ should be shown on the specified _output_.
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index d50be25d..373460a2 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -186,6 +186,7 @@ void arrange_workspace(struct sway_workspace *workspace) {
area->width, area->height, area->x, area->y);
workspace_remove_gaps(workspace);
+ bool first_arrange = workspace->width == 0 && workspace->height == 0;
double prev_x = workspace->x;
double prev_y = workspace->y;
workspace->width = area->width;
@@ -196,7 +197,7 @@ void arrange_workspace(struct sway_workspace *workspace) {
// Adjust any floating containers
double diff_x = workspace->x - prev_x;
double diff_y = workspace->y - prev_y;
- if (diff_x != 0 || diff_y != 0) {
+ if (!first_arrange && (diff_x != 0 || diff_y != 0)) {
for (int i = 0; i < workspace->floating->length; ++i) {
struct sway_container *floater = workspace->floating->items[i];
container_floating_translate(floater, diff_x, diff_y);
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 47687744..788300cc 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -67,12 +67,10 @@ void container_destroy(struct sway_container *con) {
list_free(con->outputs);
if (con->view) {
- struct sway_view *view = con->view;
- view->container = NULL;
- free(view->title_format);
- view->title_format = NULL;
-
- if (view->destroying) {
+ if (con->view->container == con) {
+ con->view->container = NULL;
+ }
+ if (con->view->destroying) {
view_destroy(con->view);
}
}
@@ -215,8 +213,7 @@ static struct sway_container *container_at_tabbed(struct sway_node *parent,
child_index = children->length - 1;
}
struct sway_container *child = children->items[child_index];
- struct sway_node *node = seat_get_focus_inactive(seat, &child->node);
- return node->sway_container;
+ return child;
}
// Surfaces
@@ -243,8 +240,7 @@ static struct sway_container *container_at_stacked(struct sway_node *parent,
int child_index = (ly - box.y) / title_height;
if (child_index < children->length) {
struct sway_container *child = children->items[child_index];
- struct sway_node *node = seat_get_focus_inactive(seat, &child->node);
- return node->sway_container;
+ return child;
}
// Surfaces
@@ -465,11 +461,17 @@ static void update_title_texture(struct sway_container *con,
cairo_surface_t *surface = cairo_image_surface_create(
CAIRO_FORMAT_ARGB32, width, height);
cairo_t *cairo = cairo_create(surface);
+ cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
+ cairo_font_options_t *fo = cairo_font_options_create();
+ cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
+ cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->wlr_output->subpixel));
+ cairo_set_font_options(cairo, fo);
+ cairo_font_options_destroy(fo);
cairo_set_source_rgba(cairo, class->background[0], class->background[1],
class->background[2], class->background[3]);
cairo_paint(cairo);
PangoContext *pango = pango_cairo_create_context(cairo);
- cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
cairo_set_source_rgba(cairo, class->text[0], class->text[1],
class->text[2], class->text[3]);
cairo_move_to(cairo, 0, 0);
@@ -591,7 +593,7 @@ void container_update_representation(struct sway_container *con) {
}
}
-size_t container_titlebar_height() {
+size_t container_titlebar_height(void) {
return config->font_height + TITLEBAR_V_PADDING * 2;
}
@@ -821,9 +823,16 @@ void container_floating_move_to_center(struct sway_container *con) {
return;
}
struct sway_workspace *ws = con->workspace;
+ bool full = con->is_fullscreen;
+ if (full) {
+ container_set_fullscreen(con, false);
+ }
double new_lx = ws->x + (ws->width - con->width) / 2;
double new_ly = ws->y + (ws->height - con->height) / 2;
container_floating_translate(con, new_lx - con->x, new_ly - con->y);
+ if (full) {
+ container_set_fullscreen(con, true);
+ }
}
static bool find_urgent_iterator(struct sway_container *con, void *data) {
@@ -981,7 +990,8 @@ void container_discover_outputs(struct sway_container *con) {
}
}
struct sway_output *new_output = container_get_effective_output(con);
- double old_scale = old_output ? old_output->wlr_output->scale : -1;
+ double old_scale = old_output && old_output->enabled ?
+ old_output->wlr_output->scale : -1;
double new_scale = new_output ? new_output->wlr_output->scale : -1;
if (old_scale != new_scale) {
container_update_title_textures(con);
@@ -1019,7 +1029,7 @@ void container_add_gaps(struct sway_container *c) {
struct sway_workspace *ws = c->workspace;
- c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner;
+ c->current_gaps = ws->gaps_inner;
c->x += c->current_gaps;
c->y += c->current_gaps;
c->width -= 2 * c->current_gaps;
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 1976ad51..c3176325 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -109,12 +109,24 @@ void output_enable(struct sway_output *output, struct output_config *oc) {
wl_signal_emit(&root->events.new_node, &output->node);
- load_swaybars();
-
arrange_layers(output);
arrange_root();
}
+static void evacuate_sticky(struct sway_workspace *old_ws,
+ struct sway_output *new_output) {
+ struct sway_workspace *new_ws = output_get_active_workspace(new_output);
+ while (old_ws->floating->length) {
+ struct sway_container *sticky = old_ws->floating->items[0];
+ container_detach(sticky);
+ workspace_add_floating(new_ws, sticky);
+ container_handle_fullscreen_reparent(sticky);
+ container_floating_move_to_center(sticky);
+ ipc_event_window(sticky, "move");
+ }
+ workspace_detect_urgent(new_ws);
+}
+
static void output_evacuate(struct sway_output *output) {
if (!output->workspaces->length) {
return;
@@ -132,17 +144,21 @@ static void output_evacuate(struct sway_output *output) {
workspace_detach(workspace);
- if (workspace_is_empty(workspace)) {
- workspace_begin_destroy(workspace);
- continue;
- }
-
struct sway_output *new_output =
workspace_output_get_highest_available(workspace, output);
if (!new_output) {
new_output = fallback_output;
}
+ if (workspace_is_empty(workspace)) {
+ // If floating is not empty, there are sticky containers to move
+ if (workspace->floating->length) {
+ evacuate_sticky(workspace, new_output);
+ }
+ workspace_begin_destroy(workspace);
+ continue;
+ }
+
if (new_output) {
workspace_output_add_priority(workspace, new_output);
output_add_workspace(new_output, workspace);
diff --git a/sway/tree/root.c b/sway/tree/root.c
index ecc04ddb..6748e9c9 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -265,14 +265,20 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
// Scratchpad
for (int i = 0; i < root->scratchpad->length; ++i) {
struct sway_container *container = root->scratchpad->items[i];
- // If the container has a parent then it's visible on a workspace
+ // If the container has a workspace then it's visible on a workspace
// and will have been iterated in the previous for loop. So we only
// iterate the hidden scratchpad containers here.
- if (!container->parent) {
+ if (!container->workspace) {
f(container, data);
container_for_each_child(container, f, data);
}
}
+
+ // Saved workspaces
+ for (int i = 0; i < root->saved_workspaces->length; ++i) {
+ struct sway_workspace *ws = root->saved_workspaces->items[i];
+ workspace_for_each_container(ws, f, data);
+ }
}
struct sway_output *root_find_output(
@@ -311,7 +317,7 @@ struct sway_container *root_find_container(
// Scratchpad
for (int i = 0; i < root->scratchpad->length; ++i) {
struct sway_container *container = root->scratchpad->items[i];
- if (!container->parent) {
+ if (!container->workspace) {
if (test(container, data)) {
return container;
}
@@ -320,6 +326,15 @@ struct sway_container *root_find_container(
}
}
}
+
+ // Saved workspaces
+ for (int i = 0; i < root->saved_workspaces->length; ++i) {
+ struct sway_workspace *ws = root->saved_workspaces->items[i];
+ if ((result = workspace_find_container(ws, test, data))) {
+ return result;
+ }
+ }
+
return NULL;
}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 4398f518..a024f325 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view,
}
void view_execute_criteria(struct sway_view *view) {
- struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_node *prior_focus = seat_get_focus(seat);
list_t *criterias = criteria_for_view(view, CT_COMMAND);
for (int i = 0; i < criterias->length; i++) {
struct criteria *criteria = criterias->items[i];
@@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) {
}
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
criteria->raw, view, criteria->cmdlist);
- seat_set_focus_container(seat, view->container);
list_add(view->executed_criteria, criteria);
- struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
- if (res->status != CMD_SUCCESS) {
- wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error);
- }
+ struct cmd_results *res = execute_command(
+ criteria->cmdlist, NULL, view->container);
free_cmd_results(res);
}
list_free(criterias);
- seat_set_focus(seat, prior_focus);
}
static struct sway_workspace *select_workspace(struct sway_view *view) {
@@ -785,14 +779,9 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) {
}
static char *escape_title(char *buffer) {
- int length = escape_markup_text(buffer, NULL, 0);
+ size_t length = escape_markup_text(buffer, NULL);
char *escaped_title = calloc(length + 1, sizeof(char));
- int result = escape_markup_text(buffer, escaped_title, length);
- if (result != length) {
- wlr_log(WLR_ERROR, "Could not escape title: %s", buffer);
- free(escaped_title);
- return buffer;
- }
+ escape_markup_text(buffer, escaped_title);
free(buffer);
return escaped_title;
}
@@ -1000,12 +989,16 @@ bool view_is_visible(struct sway_view *view) {
floater = floater->parent;
}
bool is_sticky = container_is_floating(floater) && floater->is_sticky;
+ if (!is_sticky && !workspace_is_visible(workspace)) {
+ return false;
+ }
// Check view isn't in a tabbed or stacked container on an inactive tab
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *con = view->container;
while (con) {
enum sway_container_layout layout = container_parent_layout(con);
- if (layout == L_TABBED || layout == L_STACKED) {
+ if ((layout == L_TABBED || layout == L_STACKED)
+ && !container_is_floating(con)) {
struct sway_node *parent = con->parent ?
&con->parent->node : &con->workspace->node;
if (seat_get_active_tiling_child(seat, parent) != &con->node) {
@@ -1019,10 +1012,6 @@ bool view_is_visible(struct sway_view *view) {
!container_is_fullscreen_or_child(view->container)) {
return false;
}
- // Check the workspace is visible
- if (!is_sticky) {
- return workspace_is_visible(workspace);
- }
return true;
}
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 18746430..9dd5c815 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -20,17 +20,23 @@
#include "log.h"
#include "util.h"
+struct workspace_config *workspace_find_config(const char *ws_name) {
+ for (int i = 0; i < config->workspace_configs->length; ++i) {
+ struct workspace_config *wsc = config->workspace_configs->items[i];
+ if (strcmp(wsc->workspace, ws_name) == 0) {
+ return wsc;
+ }
+ }
+ return NULL;
+}
+
struct sway_output *workspace_get_initial_output(const char *name) {
- // Search for workspace<->output pair
- for (int i = 0; i < config->workspace_outputs->length; ++i) {
- struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcasecmp(wso->workspace, name) == 0) {
- // Find output to use if it exists
- struct sway_output *output = output_by_name(wso->output);
- if (output) {
- return output;
- }
- break;
+ // Check workspace configs for a workspace<->output pair
+ struct workspace_config *wsc = workspace_find_config(name);
+ if (wsc && wsc->output) {
+ struct sway_output *output = output_by_name(wsc->output);
+ if (output) {
+ return output;
}
}
// Otherwise put it on the focused output
@@ -54,10 +60,6 @@ struct sway_workspace *workspace_create(struct sway_output *output,
return NULL;
}
node_init(&ws->node, N_WORKSPACE, ws);
- ws->x = output->lx;
- ws->y = output->ly;
- ws->width = output->width;
- ws->height = output->height;
ws->name = name ? strdup(name) : NULL;
ws->prev_split_layout = L_NONE;
ws->layout = output_get_default_layout(output);
@@ -66,6 +68,20 @@ struct sway_workspace *workspace_create(struct sway_output *output,
ws->output_priority = create_list();
workspace_output_add_priority(ws, output);
+ ws->gaps_outer = config->gaps_outer;
+ ws->gaps_inner = config->gaps_inner;
+ if (name) {
+ struct workspace_config *wsc = workspace_find_config(name);
+ if (wsc) {
+ if (wsc->gaps_outer != -1) {
+ ws->gaps_outer = wsc->gaps_outer;
+ }
+ if (wsc->gaps_inner != -1) {
+ ws->gaps_inner = wsc->gaps_inner;
+ }
+ }
+ }
+
output_add_workspace(output, ws);
output_sort_workspaces(output);
@@ -125,17 +141,8 @@ void next_name_map(struct sway_container *ws, void *data) {
static bool workspace_valid_on_output(const char *output_name,
const char *ws_name) {
- int i;
- for (i = 0; i < config->workspace_outputs->length; ++i) {
- struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcasecmp(wso->workspace, ws_name) == 0) {
- if (strcasecmp(wso->output, output_name) != 0) {
- return false;
- }
- }
- }
-
- return true;
+ struct workspace_config *wsc = workspace_find_config(ws_name);
+ return !wsc || !wsc->output || strcmp(wsc->output, output_name) == 0;
}
static void workspace_name_from_binding(const struct sway_binding * binding,
@@ -235,13 +242,13 @@ char *workspace_next_name(const char *output_name) {
workspace_name_from_binding(mode->keycode_bindings->items[i],
output_name, &order, &target);
}
- for (int i = 0; i < config->workspace_outputs->length; ++i) {
+ for (int i = 0; i < config->workspace_configs->length; ++i) {
// Unlike with bindings, this does not guarantee order
- const struct workspace_output *wso = config->workspace_outputs->items[i];
- if (strcmp(wso->output, output_name) == 0
- && workspace_by_name(wso->workspace) == NULL) {
+ const struct workspace_config *wsc = config->workspace_configs->items[i];
+ if (wsc->output && strcmp(wsc->output, output_name) == 0
+ && workspace_by_name(wsc->workspace) == NULL) {
free(target);
- target = strdup(wso->workspace);
+ target = strdup(wsc->workspace);
break;
}
}
@@ -389,13 +396,11 @@ bool workspace_switch(struct sway_workspace *workspace,
struct sway_output *next_output = workspace->output;
struct sway_workspace *next_output_prev_ws =
output_get_active_workspace(next_output);
- bool has_sticky = false;
if (workspace != next_output_prev_ws) {
for (int i = 0; i < next_output_prev_ws->floating->length; ++i) {
struct sway_container *floater =
next_output_prev_ws->floating->items[i];
if (floater->is_sticky) {
- has_sticky = true;
container_detach(floater);
workspace_add_floating(workspace, floater);
if (&floater->node == focus) {
@@ -414,14 +419,6 @@ bool workspace_switch(struct sway_workspace *workspace,
if (next == NULL) {
next = &workspace->node;
}
- if (has_sticky) {
- // If there's a sticky container, we might be setting focus to the same
- // container that's already focused, so seat_set_focus is effectively a
- // no op. We therefore need to send the IPC event and clean up the old
- // workspace here.
- ipc_event_workspace(active_ws, workspace, "focus");
- workspace_consider_destroy(active_ws);
- }
seat_set_focus(seat, next);
arrange_workspace(workspace);
cursor_send_pointer_motion(seat->cursor, 0, true);
@@ -649,13 +646,13 @@ void workspace_add_gaps(struct sway_workspace *ws) {
return;
}
- ws->current_gaps = ws->has_gaps ? ws->gaps_outer : config->gaps_outer;
+ ws->current_gaps = ws->gaps_outer;
if (ws->layout == L_TABBED || ws->layout == L_STACKED) {
// We have to add inner gaps for this, because children of tabbed and
// stacked containers don't apply their own gaps - they assume the
// tabbed/stacked container is using gaps.
- ws->current_gaps += ws->has_gaps ? ws->gaps_inner : config->gaps_inner;
+ ws->current_gaps += ws->gaps_inner;
}
ws->x += ws->current_gaps;