aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands')
-rw-r--r--sway/commands/assign.c3
-rw-r--r--sway/commands/bar.c5
-rw-r--r--sway/commands/bar/bind.c2
-rw-r--r--sway/commands/bar/font.c1
-rw-r--r--sway/commands/bar/hidden_state.c1
-rw-r--r--sway/commands/bar/icon_theme.c1
-rw-r--r--sway/commands/bar/id.c1
-rw-r--r--sway/commands/bar/mode.c1
-rw-r--r--sway/commands/bar/output.c1
-rw-r--r--sway/commands/bar/position.c1
-rw-r--r--sway/commands/bar/separator_symbol.c1
-rw-r--r--sway/commands/bar/tray_bind.c2
-rw-r--r--sway/commands/bar/tray_output.c1
-rw-r--r--sway/commands/bind.c15
-rw-r--r--sway/commands/client.c12
-rw-r--r--sway/commands/exec_always.c28
-rw-r--r--sway/commands/floating_minmax_size.c6
-rw-r--r--sway/commands/font.c28
-rw-r--r--sway/commands/for_window.c2
-rw-r--r--sway/commands/gesture.c165
-rw-r--r--sway/commands/hide_edge_borders.c4
-rw-r--r--sway/commands/inhibit_idle.c2
-rw-r--r--sway/commands/input.c3
-rw-r--r--sway/commands/input/calibration_matrix.c1
-rw-r--r--sway/commands/input/dwtp.c25
-rw-r--r--sway/commands/input/events.c11
-rw-r--r--sway/commands/input/map_from_region.c19
-rw-r--r--sway/commands/input/map_to_output.c1
-rw-r--r--sway/commands/input/map_to_region.c3
-rw-r--r--sway/commands/input/rotation_angle.c29
-rw-r--r--sway/commands/input/scroll_button.c2
-rw-r--r--sway/commands/input/scroll_button_lock.c26
-rw-r--r--sway/commands/input/xkb_file.c1
-rw-r--r--sway/commands/input/xkb_layout.c1
-rw-r--r--sway/commands/input/xkb_model.c1
-rw-r--r--sway/commands/input/xkb_numlock.c1
-rw-r--r--sway/commands/input/xkb_options.c1
-rw-r--r--sway/commands/input/xkb_rules.c1
-rw-r--r--sway/commands/input/xkb_switch_layout.c7
-rw-r--r--sway/commands/input/xkb_variant.c1
-rw-r--r--sway/commands/layout.c2
-rw-r--r--sway/commands/mark.c3
-rw-r--r--sway/commands/mode.c4
-rw-r--r--sway/commands/move.c50
-rw-r--r--sway/commands/no_focus.c2
-rw-r--r--sway/commands/opacity.c3
-rw-r--r--sway/commands/output.c11
-rw-r--r--sway/commands/output/background.c4
-rw-r--r--sway/commands/output/dpms.c45
-rw-r--r--sway/commands/output/power.c43
-rw-r--r--sway/commands/output/toggle.c2
-rw-r--r--sway/commands/output/transform.c1
-rw-r--r--sway/commands/output/unplug.c54
-rw-r--r--sway/commands/primary_selection.c25
-rw-r--r--sway/commands/reload.c8
-rw-r--r--sway/commands/rename.c7
-rw-r--r--sway/commands/resize.c50
-rw-r--r--sway/commands/seat/attach.c1
-rw-r--r--sway/commands/seat/cursor.c26
-rw-r--r--sway/commands/seat/hide_cursor.c1
-rw-r--r--sway/commands/seat/idle.c7
-rw-r--r--sway/commands/seat/pointer_constraint.c1
-rw-r--r--sway/commands/seat/shortcuts_inhibitor.c1
-rw-r--r--sway/commands/seat/xcursor_theme.c1
-rw-r--r--sway/commands/set.c1
-rw-r--r--sway/commands/shortcuts_inhibitor.c1
-rw-r--r--sway/commands/show_marks.c12
-rw-r--r--sway/commands/split.c2
-rw-r--r--sway/commands/swap.c184
-rw-r--r--sway/commands/title_align.c9
-rw-r--r--sway/commands/title_format.c1
-rw-r--r--sway/commands/titlebar_border_thickness.c1
-rw-r--r--sway/commands/titlebar_padding.c1
-rw-r--r--sway/commands/unmark.c12
-rw-r--r--sway/commands/workspace.c13
-rw-r--r--sway/commands/xwayland.c4
76 files changed, 621 insertions, 389 deletions
diff --git a/sway/commands/assign.c b/sway/commands/assign.c
index 976bc3cc..bf95cf00 100644
--- a/sway/commands/assign.c
+++ b/sway/commands/assign.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
@@ -17,7 +16,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
17 char *err_str = NULL; 16 char *err_str = NULL;
18 struct criteria *criteria = criteria_parse(argv[0], &err_str); 17 struct criteria *criteria = criteria_parse(argv[0], &err_str);
19 if (!criteria) { 18 if (!criteria) {
20 error = cmd_results_new(CMD_INVALID, err_str); 19 error = cmd_results_new(CMD_INVALID, "%s", err_str);
21 free(err_str); 20 free(err_str);
22 return error; 21 return error;
23 } 22 }
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index 8571d282..635e895b 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
@@ -73,12 +72,10 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
73 } 72 }
74 ++argv; --argc; 73 ++argv; --argc;
75 } else if (config->reading && !config->current_bar) { 74 } else if (config->reading && !config->current_bar) {
76 int len = snprintf(NULL, 0, "bar-%d", config->bars->length) + 1; 75 id = format_str("bar-%d", config->bars->length);
77 id = malloc(len * sizeof(char));
78 if (!id) { 76 if (!id) {
79 return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id"); 77 return cmd_results_new(CMD_FAILURE, "Unable to allocate bar id");
80 } 78 }
81 snprintf(id, len, "bar-%d", config->bars->length);
82 } else if (!config->reading && strcmp(argv[0], "mode") != 0 && 79 } else if (!config->reading && strcmp(argv[0], "mode") != 0 &&
83 strcmp(argv[0], "hidden_state") != 0) { 80 strcmp(argv[0], "hidden_state") != 0) {
84 if (is_subcommand(argv[0])) { 81 if (is_subcommand(argv[0])) {
diff --git a/sway/commands/bar/bind.c b/sway/commands/bar/bind.c
index b4b5bc45..8a837e3f 100644
--- a/sway/commands/bar/bind.c
+++ b/sway/commands/bar/bind.c
@@ -96,7 +96,7 @@ static struct cmd_results *bar_cmd_bind(int argc, char **argv, bool code,
96 } 96 }
97 if (message) { 97 if (message) {
98 free_bar_binding(binding); 98 free_bar_binding(binding);
99 error = cmd_results_new(CMD_INVALID, message); 99 error = cmd_results_new(CMD_INVALID, "%s", message);
100 free(message); 100 free(message);
101 return error; 101 return error;
102 } else if (!binding->button) { 102 } else if (!binding->button) {
diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c
index 891c87af..0c074679 100644
--- a/sway/commands/bar/font.c
+++ b/sway/commands/bar/font.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c
index 8b661e3a..7b38831e 100644
--- a/sway/commands/bar/hidden_state.c
+++ b/sway/commands/bar/hidden_state.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/icon_theme.c b/sway/commands/bar/icon_theme.c
index 6ac07843..fee21709 100644
--- a/sway/commands/bar/icon_theme.c
+++ b/sway/commands/bar/icon_theme.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "config.h" 2#include "config.h"
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c
index a9a61743..46cf4ca9 100644
--- a/sway/commands/bar/id.c
+++ b/sway/commands/bar/id.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c
index 7c2f423b..d69e910b 100644
--- a/sway/commands/bar/mode.c
+++ b/sway/commands/bar/mode.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c
index cac1d056..51730176 100644
--- a/sway/commands/bar/output.c
+++ b/sway/commands/bar/output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c
index b207de0b..94f530ec 100644
--- a/sway/commands/bar/position.c
+++ b/sway/commands/bar/position.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c
index 6737d4d2..50e9a873 100644
--- a/sway/commands/bar/separator_symbol.c
+++ b/sway/commands/bar/separator_symbol.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/bar/tray_bind.c b/sway/commands/bar/tray_bind.c
index 243834ba..3dc9bc4c 100644
--- a/sway/commands/bar/tray_bind.c
+++ b/sway/commands/bar/tray_bind.c
@@ -26,7 +26,7 @@ static struct cmd_results *tray_bind(int argc, char **argv, bool code) {
26 } 26 }
27 if (message) { 27 if (message) {
28 free(binding); 28 free(binding);
29 error = cmd_results_new(CMD_INVALID, message); 29 error = cmd_results_new(CMD_INVALID, "%s", message);
30 free(message); 30 free(message);
31 return error; 31 return error;
32 } else if (!binding->button) { 32 } else if (!binding->button) {
diff --git a/sway/commands/bar/tray_output.c b/sway/commands/bar/tray_output.c
index eb3b486e..679facf7 100644
--- a/sway/commands/bar/tray_output.c
+++ b/sway/commands/bar/tray_output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "config.h" 2#include "config.h"
4#include "sway/commands.h" 3#include "sway/commands.h"
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 26c99e63..268f2855 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <libevdev/libevdev.h> 1#include <libevdev/libevdev.h>
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#include <string.h> 3#include <string.h>
@@ -127,7 +126,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
127 if (!button) { 126 if (!button) {
128 if (message) { 127 if (message) {
129 struct cmd_results *error = 128 struct cmd_results *error =
130 cmd_results_new(CMD_INVALID, message); 129 cmd_results_new(CMD_INVALID, "%s", message);
131 free(message); 130 free(message);
132 return error; 131 return error;
133 } else { 132 } else {
@@ -143,7 +142,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
143 if (!button) { 142 if (!button) {
144 if (message) { 143 if (message) {
145 struct cmd_results *error = 144 struct cmd_results *error =
146 cmd_results_new(CMD_INVALID, message); 145 cmd_results_new(CMD_INVALID, "%s", message);
147 free(message); 146 free(message);
148 return error; 147 return error;
149 } else { 148 } else {
@@ -182,7 +181,7 @@ static struct cmd_results *identify_key(const char* name, bool first_key,
182 uint32_t button = get_mouse_bindsym(name, &message); 181 uint32_t button = get_mouse_bindsym(name, &message);
183 if (message) { 182 if (message) {
184 struct cmd_results *error = 183 struct cmd_results *error =
185 cmd_results_new(CMD_INVALID, message); 184 cmd_results_new(CMD_INVALID, "%s", message);
186 free(message); 185 free(message);
187 return error; 186 return error;
188 } else if (button) { 187 } else if (button) {
@@ -372,6 +371,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
372 strlen("--input-device=")) == 0) { 371 strlen("--input-device=")) == 0) {
373 free(binding->input); 372 free(binding->input);
374 binding->input = strdup(argv[0] + strlen("--input-device=")); 373 binding->input = strdup(argv[0] + strlen("--input-device="));
374 strip_quotes(binding->input);
375 } else if (strcmp("--no-warn", argv[0]) == 0) { 375 } else if (strcmp("--no-warn", argv[0]) == 0) {
376 warn = false; 376 warn = false;
377 } else if (strcmp("--no-repeat", argv[0]) == 0) { 377 } else if (strcmp("--no-repeat", argv[0]) == 0) {
@@ -538,7 +538,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
538 free_switch_binding(binding); 538 free_switch_binding(binding);
539 return cmd_results_new(CMD_FAILURE, 539 return cmd_results_new(CMD_FAILURE,
540 "Invalid %s command (expected binding with the form " 540 "Invalid %s command (expected binding with the form "
541 "<switch>:<state>)", bindtype, argc); 541 "<switch>:<state>)", bindtype);
542 } 542 }
543 if (strcmp(split->items[0], "tablet") == 0) { 543 if (strcmp(split->items[0], "tablet") == 0) {
544 binding->type = WLR_SWITCH_TYPE_TABLET_MODE; 544 binding->type = WLR_SWITCH_TYPE_TABLET_MODE;
@@ -548,7 +548,8 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
548 free_switch_binding(binding); 548 free_switch_binding(binding);
549 return cmd_results_new(CMD_FAILURE, 549 return cmd_results_new(CMD_FAILURE,
550 "Invalid %s command (expected switch binding: " 550 "Invalid %s command (expected switch binding: "
551 "unknown switch %s)", bindtype, split->items[0]); 551 "unknown switch %s)", bindtype,
552 (const char *)split->items[0]);
552 } 553 }
553 if (strcmp(split->items[1], "on") == 0) { 554 if (strcmp(split->items[1], "on") == 0) {
554 binding->trigger = SWAY_SWITCH_TRIGGER_ON; 555 binding->trigger = SWAY_SWITCH_TRIGGER_ON;
@@ -561,7 +562,7 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
561 return cmd_results_new(CMD_FAILURE, 562 return cmd_results_new(CMD_FAILURE,
562 "Invalid %s command " 563 "Invalid %s command "
563 "(expected switch state: unknown state %s)", 564 "(expected switch state: unknown state %s)",
564 bindtype, split->items[1]); 565 bindtype, (const char *)split->items[1]);
565 } 566 }
566 list_free_items_and_destroy(split); 567 list_free_items_and_destroy(split);
567 568
diff --git a/sway/commands/client.c b/sway/commands/client.c
index 77263145..fd2ac7a8 100644
--- a/sway/commands/client.c
+++ b/sway/commands/client.c
@@ -5,9 +5,8 @@
5#include "sway/tree/container.h" 5#include "sway/tree/container.h"
6#include "util.h" 6#include "util.h"
7 7
8static void rebuild_textures_iterator(struct sway_container *con, void *data) { 8static void container_update_iterator(struct sway_container *con, void *data) {
9 container_update_marks_textures(con); 9 container_update(con);
10 container_update_title_textures(con);
11} 10}
12 11
13static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name, 12static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
@@ -51,12 +50,7 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
51 memcpy(class, &colors, sizeof(struct border_colors)); 50 memcpy(class, &colors, sizeof(struct border_colors));
52 51
53 if (config->active) { 52 if (config->active) {
54 root_for_each_container(rebuild_textures_iterator, NULL); 53 root_for_each_container(container_update_iterator, NULL);
55
56 for (int i = 0; i < root->outputs->length; ++i) {
57 struct sway_output *output = root->outputs->items[i];
58 output_damage_whole(output);
59 }
60 } 54 }
61 55
62 return cmd_results_new(CMD_SUCCESS, NULL); 56 return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c
index b35065c1..8bc1048c 100644
--- a/sway/commands/exec_always.c
+++ b/sway/commands/exec_always.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <stdint.h> 2#include <stdint.h>
4#include <string.h> 3#include <string.h>
@@ -8,6 +7,7 @@
8#include "sway/commands.h" 7#include "sway/commands.h"
9#include "sway/config.h" 8#include "sway/config.h"
10#include "sway/server.h" 9#include "sway/server.h"
10#include "sway/desktop/launcher.h"
11#include "sway/tree/container.h" 11#include "sway/tree/container.h"
12#include "sway/tree/root.h" 12#include "sway/tree/root.h"
13#include "sway/tree/workspace.h" 13#include "sway/tree/workspace.h"
@@ -25,11 +25,22 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
25 return error; 25 return error;
26} 26}
27 27
28static void export_xdga_token(struct launcher_ctx *ctx) {
29 const char *token = launcher_ctx_get_token_name(ctx);
30 setenv("XDG_ACTIVATION_TOKEN", token, 1);
31}
32
33static void export_startup_id(struct launcher_ctx *ctx) {
34 const char *token = launcher_ctx_get_token_name(ctx);
35 setenv("DESKTOP_STARTUP_ID", token, 1);
36}
37
28struct cmd_results *cmd_exec_process(int argc, char **argv) { 38struct cmd_results *cmd_exec_process(int argc, char **argv) {
29 struct cmd_results *error = NULL; 39 struct cmd_results *error = NULL;
30 char *cmd = NULL; 40 char *cmd = NULL;
41 bool no_startup_id = false;
31 if (strcmp(argv[0], "--no-startup-id") == 0) { 42 if (strcmp(argv[0], "--no-startup-id") == 0) {
32 sway_log(SWAY_INFO, "exec switch '--no-startup-id' not supported, ignored."); 43 no_startup_id = true;
33 --argc; ++argv; 44 --argc; ++argv;
34 if ((error = checkarg(argc, argv[-1], EXPECTED_AT_LEAST, 1))) { 45 if ((error = checkarg(argc, argv[-1], EXPECTED_AT_LEAST, 1))) {
35 return error; 46 return error;
@@ -51,6 +62,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
51 } 62 }
52 63
53 pid_t pid, child; 64 pid_t pid, child;
65 struct launcher_ctx *ctx = launcher_ctx_create_internal();
54 // Fork process 66 // Fork process
55 if ((pid = fork()) == 0) { 67 if ((pid = fork()) == 0) {
56 // Fork child process again 68 // Fork child process again
@@ -63,6 +75,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
63 close(fd[0]); 75 close(fd[0]);
64 if ((child = fork()) == 0) { 76 if ((child = fork()) == 0) {
65 close(fd[1]); 77 close(fd[1]);
78 if (ctx) {
79 export_xdga_token(ctx);
80 }
81 if (ctx && !no_startup_id) {
82 export_startup_id(ctx);
83 }
66 execlp("sh", "sh", "-c", cmd, (void *)NULL); 84 execlp("sh", "sh", "-c", cmd, (void *)NULL);
67 sway_log_errno(SWAY_ERROR, "execlp failed"); 85 sway_log_errno(SWAY_ERROR, "execlp failed");
68 _exit(1); 86 _exit(1);
@@ -90,8 +108,12 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
90 waitpid(pid, NULL, 0); 108 waitpid(pid, NULL, 0);
91 if (child > 0) { 109 if (child > 0) {
92 sway_log(SWAY_DEBUG, "Child process created with pid %d", child); 110 sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
93 root_record_workspace_pid(child); 111 if (ctx != NULL) {
112 sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
113 ctx->pid = child;
114 }
94 } else { 115 } else {
116 launcher_ctx_destroy(ctx);
95 return cmd_results_new(CMD_FAILURE, "Second fork() failed"); 117 return cmd_results_new(CMD_FAILURE, "Second fork() failed");
96 } 118 }
97 119
diff --git a/sway/commands/floating_minmax_size.c b/sway/commands/floating_minmax_size.c
index 3a1d606a..e8c24ace 100644
--- a/sway/commands/floating_minmax_size.c
+++ b/sway/commands/floating_minmax_size.c
@@ -23,16 +23,16 @@ static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
23 char *err; 23 char *err;
24 int width = (int)strtol(argv[0], &err, 10); 24 int width = (int)strtol(argv[0], &err, 10);
25 if (*err) { 25 if (*err) {
26 return cmd_results_new(CMD_INVALID, cmd_name, usage); 26 return cmd_results_new(CMD_INVALID, "%s", usage);
27 } 27 }
28 28
29 if (strcmp(argv[1], "x") != 0) { 29 if (strcmp(argv[1], "x") != 0) {
30 return cmd_results_new(CMD_INVALID, cmd_name, usage); 30 return cmd_results_new(CMD_INVALID, "%s", usage);
31 } 31 }
32 32
33 int height = (int)strtol(argv[2], &err, 10); 33 int height = (int)strtol(argv[2], &err, 10);
34 if (*err) { 34 if (*err) {
35 return cmd_results_new(CMD_INVALID, cmd_name, usage); 35 return cmd_results_new(CMD_INVALID, "%s", usage);
36 } 36 }
37 37
38 *config_width = width; 38 *config_width = width;
diff --git a/sway/commands/font.c b/sway/commands/font.c
index cea720f5..9920d03e 100644
--- a/sway/commands/font.c
+++ b/sway/commands/font.c
@@ -1,9 +1,9 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
5#include "log.h" 4#include "log.h"
6#include "stringop.h" 5#include "stringop.h"
6#include <pango/pangocairo.h>
7 7
8struct cmd_results *cmd_font(int argc, char **argv) { 8struct cmd_results *cmd_font(int argc, char **argv) {
9 struct cmd_results *error = NULL; 9 struct cmd_results *error = NULL;
@@ -16,12 +16,34 @@ struct cmd_results *cmd_font(int argc, char **argv) {
16 if (strncmp(font, "pango:", 6) == 0) { 16 if (strncmp(font, "pango:", 6) == 0) {
17 config->pango_markup = true; 17 config->pango_markup = true;
18 config->font = strdup(font + 6); 18 config->font = strdup(font + 6);
19 free(font);
19 } else { 20 } else {
20 config->pango_markup = false; 21 config->pango_markup = false;
21 config->font = strdup(font); 22 config->font = font;
22 } 23 }
23 24
24 free(font); 25 // Parse the font early so we can reject it if it's not valid for pango.
26 // Also avoids re-parsing each time we render text.
27 PangoFontDescription *font_description = pango_font_description_from_string(config->font);
28
29 const char *family = pango_font_description_get_family(font_description);
30 if (family == NULL) {
31 pango_font_description_free(font_description);
32 return cmd_results_new(CMD_FAILURE, "Invalid font family.");
33 }
34
35 const gint size = pango_font_description_get_size(font_description);
36 if (size == 0) {
37 pango_font_description_free(font_description);
38 return cmd_results_new(CMD_FAILURE, "Invalid font size.");
39 }
40
41 if (config->font_description != NULL) {
42 pango_font_description_free(config->font_description);
43 }
44
45 config->font_description = font_description;
25 config_update_font_height(); 46 config_update_font_height();
47
26 return cmd_results_new(CMD_SUCCESS, NULL); 48 return cmd_results_new(CMD_SUCCESS, NULL);
27} 49}
diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c
index ee9f4647..905e6776 100644
--- a/sway/commands/for_window.c
+++ b/sway/commands/for_window.c
@@ -14,7 +14,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) {
14 char *err_str = NULL; 14 char *err_str = NULL;
15 struct criteria *criteria = criteria_parse(argv[0], &err_str); 15 struct criteria *criteria = criteria_parse(argv[0], &err_str);
16 if (!criteria) { 16 if (!criteria) {
17 error = cmd_results_new(CMD_INVALID, err_str); 17 error = cmd_results_new(CMD_INVALID, "%s", err_str);
18 free(err_str); 18 free(err_str);
19 return error; 19 return error;
20 } 20 }
diff --git a/sway/commands/gesture.c b/sway/commands/gesture.c
new file mode 100644
index 00000000..90a20716
--- /dev/null
+++ b/sway/commands/gesture.c
@@ -0,0 +1,165 @@
1#include "sway/config.h"
2
3#include "gesture.h"
4#include "log.h"
5#include "stringop.h"
6#include "sway/commands.h"
7
8void free_gesture_binding(struct sway_gesture_binding *binding) {
9 if (!binding) {
10 return;
11 }
12 free(binding->input);
13 free(binding->command);
14 free(binding);
15}
16
17/**
18 * Returns true if the bindings have the same gesture type, direction, etc
19 */
20static bool binding_gesture_equal(struct sway_gesture_binding *binding_a,
21 struct sway_gesture_binding *binding_b) {
22 if (strcmp(binding_a->input, binding_b->input) != 0) {
23 return false;
24 }
25
26 if (!gesture_equal(&binding_a->gesture, &binding_b->gesture)) {
27 return false;
28 }
29
30 if ((binding_a->flags & BINDING_EXACT) !=
31 (binding_b->flags & BINDING_EXACT)) {
32 return false;
33 }
34 return true;
35}
36
37/**
38 * Add gesture binding to config
39 */
40static struct cmd_results *gesture_binding_add(
41 struct sway_gesture_binding *binding,
42 const char *gesturecombo, bool warn) {
43 list_t *mode_bindings = config->current_mode->gesture_bindings;
44 // overwrite the binding if it already exists
45 bool overwritten = false;
46 for (int i = 0; i < mode_bindings->length; ++i) {
47 struct sway_gesture_binding *config_binding = mode_bindings->items[i];
48 if (binding_gesture_equal(binding, config_binding)) {
49 sway_log(SWAY_INFO, "Overwriting binding '%s' to `%s` from `%s`",
50 gesturecombo, binding->command, config_binding->command);
51 if (warn) {
52 config_add_swaynag_warning("Overwriting binding"
53 "'%s' to `%s` from `%s`",
54 gesturecombo, binding->command,
55 config_binding->command);
56 }
57 free_gesture_binding(config_binding);
58 mode_bindings->items[i] = binding;
59 overwritten = true;
60 }
61 }
62
63 if (!overwritten) {
64 list_add(mode_bindings, binding);
65 sway_log(SWAY_DEBUG, "bindgesture - Bound %s to command `%s`",
66 gesturecombo, binding->command);
67 }
68
69 return cmd_results_new(CMD_SUCCESS, NULL);
70}
71
72/**
73 * Remove gesture binding from config
74 */
75static struct cmd_results *gesture_binding_remove(
76 struct sway_gesture_binding *binding, const char *gesturecombo) {
77 list_t *mode_bindings = config->current_mode->gesture_bindings;
78 for (int i = 0; i < mode_bindings->length; ++i) {
79 struct sway_gesture_binding *config_binding = mode_bindings->items[i];
80 if (binding_gesture_equal(binding, config_binding)) {
81 free_gesture_binding(config_binding);
82 free_gesture_binding(binding);
83 list_del(mode_bindings, i);
84 sway_log(SWAY_DEBUG, "unbindgesture - Unbound %s gesture",
85 gesturecombo);
86 return cmd_results_new(CMD_SUCCESS, NULL);
87 }
88 }
89
90 free_gesture_binding(binding);
91 return cmd_results_new(CMD_FAILURE, "Could not find gesture binding `%s`",
92 gesturecombo);
93}
94
95/**
96 * Parse and execute bindgesture or unbindgesture command.
97 */
98static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, bool unbind) {
99 int minargs = 2;
100 char *bindtype = "bindgesture";
101 if (unbind) {
102 minargs--;
103 bindtype = "unbindgesture";
104 }
105
106 struct cmd_results *error = NULL;
107 if ((error = checkarg(argc, bindtype, EXPECTED_AT_LEAST, minargs))) {
108 return error;
109 }
110 struct sway_gesture_binding *binding = calloc(1, sizeof(struct sway_gesture_binding));
111 if (!binding) {
112 return cmd_results_new(CMD_FAILURE, "Unable to allocate binding");
113 }
114 binding->input = strdup("*");
115
116 bool warn = true;
117
118 // Handle flags
119 while (argc > 0) {
120 if (strcmp("--exact", argv[0]) == 0) {
121 binding->flags |= BINDING_EXACT;
122 } else if (strcmp("--no-warn", argv[0]) == 0) {
123 warn = false;
124 } else if (strncmp("--input-device=", argv[0],
125 strlen("--input-device=")) == 0) {
126 free(binding->input);
127 binding->input = strdup(argv[0] + strlen("--input-device="));
128 } else {
129 break;
130 }
131 argv++;
132 argc--;
133 }
134
135 if (argc < minargs) {
136 free(binding);
137 return cmd_results_new(CMD_FAILURE,
138 "Invalid %s command (expected at least %d "
139 "non-option arguments, got %d)", bindtype, minargs, argc);
140 }
141
142 char* errmsg = NULL;
143 if ((errmsg = gesture_parse(argv[0], &binding->gesture))) {
144 free(binding);
145 struct cmd_results *final = cmd_results_new(CMD_FAILURE,
146 "Invalid %s command (%s)",
147 bindtype, errmsg);
148 free(errmsg);
149 return final;
150 }
151
152 if (unbind) {
153 return gesture_binding_remove(binding, argv[0]);
154 }
155 binding->command = join_args(argv + 1, argc - 1);
156 return gesture_binding_add(binding, argv[0], warn);
157}
158
159struct cmd_results *cmd_bindgesture(int argc, char **argv) {
160 return cmd_bind_or_unbind_gesture(argc, argv, false);
161}
162
163struct cmd_results *cmd_unbindgesture(int argc, char **argv) {
164 return cmd_bind_or_unbind_gesture(argc, argv, true);
165}
diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c
index 9a1d8445..43bd6dc8 100644
--- a/sway/commands/hide_edge_borders.c
+++ b/sway/commands/hide_edge_borders.c
@@ -20,7 +20,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
20 } 20 }
21 21
22 if (!argc) { 22 if (!argc) {
23 return cmd_results_new(CMD_INVALID, expected_syntax); 23 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
24 } 24 }
25 25
26 if (strcmp(argv[0], "none") == 0) { 26 if (strcmp(argv[0], "none") == 0) {
@@ -38,7 +38,7 @@ struct cmd_results *cmd_hide_edge_borders(int argc, char **argv) {
38 config->hide_edge_borders = E_NONE; 38 config->hide_edge_borders = E_NONE;
39 config->hide_edge_borders_smart = ESMART_NO_GAPS; 39 config->hide_edge_borders_smart = ESMART_NO_GAPS;
40 } else { 40 } else {
41 return cmd_results_new(CMD_INVALID, expected_syntax); 41 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
42 } 42 }
43 config->hide_lone_tab = hide_lone_tab; 43 config->hide_lone_tab = hide_lone_tab;
44 44
diff --git a/sway/commands/inhibit_idle.c b/sway/commands/inhibit_idle.c
index aebc2bf9..6125736a 100644
--- a/sway/commands/inhibit_idle.c
+++ b/sway/commands/inhibit_idle.c
@@ -41,7 +41,7 @@ struct cmd_results *cmd_inhibit_idle(int argc, char **argv) {
41 sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor); 41 sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor);
42 } else { 42 } else {
43 inhibitor->mode = mode; 43 inhibitor->mode = mode;
44 sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); 44 sway_idle_inhibit_v1_check_active();
45 } 45 }
46 } else if (!clear) { 46 } else if (!clear) {
47 sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode); 47 sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode);
diff --git a/sway/commands/input.c b/sway/commands/input.c
index 77acb671..306c40f7 100644
--- a/sway/commands/input.c
+++ b/sway/commands/input.c
@@ -14,6 +14,7 @@ static const struct cmd_handler input_handlers[] = {
14 { "drag", input_cmd_drag }, 14 { "drag", input_cmd_drag },
15 { "drag_lock", input_cmd_drag_lock }, 15 { "drag_lock", input_cmd_drag_lock },
16 { "dwt", input_cmd_dwt }, 16 { "dwt", input_cmd_dwt },
17 { "dwtp", input_cmd_dwtp },
17 { "events", input_cmd_events }, 18 { "events", input_cmd_events },
18 { "left_handed", input_cmd_left_handed }, 19 { "left_handed", input_cmd_left_handed },
19 { "map_from_region", input_cmd_map_from_region }, 20 { "map_from_region", input_cmd_map_from_region },
@@ -24,7 +25,9 @@ static const struct cmd_handler input_handlers[] = {
24 { "pointer_accel", input_cmd_pointer_accel }, 25 { "pointer_accel", input_cmd_pointer_accel },
25 { "repeat_delay", input_cmd_repeat_delay }, 26 { "repeat_delay", input_cmd_repeat_delay },
26 { "repeat_rate", input_cmd_repeat_rate }, 27 { "repeat_rate", input_cmd_repeat_rate },
28 { "rotation_angle", input_cmd_rotation_angle },
27 { "scroll_button", input_cmd_scroll_button }, 29 { "scroll_button", input_cmd_scroll_button },
30 { "scroll_button_lock", input_cmd_scroll_button_lock },
28 { "scroll_factor", input_cmd_scroll_factor }, 31 { "scroll_factor", input_cmd_scroll_factor },
29 { "scroll_method", input_cmd_scroll_method }, 32 { "scroll_method", input_cmd_scroll_method },
30 { "tap", input_cmd_tap }, 33 { "tap", input_cmd_tap },
diff --git a/sway/commands/input/calibration_matrix.c b/sway/commands/input/calibration_matrix.c
index 38749fbb..53fe2c35 100644
--- a/sway/commands/input/calibration_matrix.c
+++ b/sway/commands/input/calibration_matrix.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/dwtp.c b/sway/commands/input/dwtp.c
new file mode 100644
index 00000000..232e2b26
--- /dev/null
+++ b/sway/commands/input/dwtp.c
@@ -0,0 +1,25 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/config.h"
4#include "sway/commands.h"
5#include "sway/input/input-manager.h"
6#include "util.h"
7
8struct cmd_results *input_cmd_dwtp(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "dwtp", EXPECTED_AT_LEAST, 1))) {
11 return error;
12 }
13 struct input_config *ic = config->handler_context.input_config;
14 if (!ic) {
15 return cmd_results_new(CMD_FAILURE, "No input device defined.");
16 }
17
18 if (parse_boolean(argv[0], true)) {
19 ic->dwtp = LIBINPUT_CONFIG_DWTP_ENABLED;
20 } else {
21 ic->dwtp = LIBINPUT_CONFIG_DWTP_DISABLED;
22 }
23
24 return cmd_results_new(CMD_SUCCESS, NULL);
25}
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c
index 9405181a..3cea026e 100644
--- a/sway/commands/input/events.c
+++ b/sway/commands/input/events.c
@@ -1,14 +1,20 @@
1#include <limits.h> 1#include <limits.h>
2#include <string.h> 2#include <string.h>
3#include <strings.h> 3#include <strings.h>
4#include <wlr/backend/libinput.h> 4#include <wlr/config.h>
5#include "sway/config.h" 5#include "sway/config.h"
6#include "sway/commands.h" 6#include "sway/commands.h"
7#include "sway/input/input-manager.h" 7#include "sway/input/input-manager.h"
8#include "sway/server.h"
8#include "log.h" 9#include "log.h"
9 10
11#if WLR_HAS_LIBINPUT_BACKEND
12#include <wlr/backend/libinput.h>
13#endif
14
10static void toggle_supported_send_events_for_device(struct input_config *ic, 15static void toggle_supported_send_events_for_device(struct input_config *ic,
11 struct sway_input_device *input_device) { 16 struct sway_input_device *input_device) {
17#if WLR_HAS_LIBINPUT_BACKEND
12 struct wlr_input_device *wlr_device = input_device->wlr_device; 18 struct wlr_input_device *wlr_device = input_device->wlr_device;
13 if (!wlr_input_device_is_libinput(wlr_device)) { 19 if (!wlr_input_device_is_libinput(wlr_device)) {
14 return; 20 return;
@@ -41,6 +47,7 @@ static void toggle_supported_send_events_for_device(struct input_config *ic,
41 } 47 }
42 48
43 ic->send_events = mode; 49 ic->send_events = mode;
50#endif
44} 51}
45 52
46static int mode_for_name(const char *name) { 53static int mode_for_name(const char *name) {
@@ -56,6 +63,7 @@ static int mode_for_name(const char *name) {
56 63
57static void toggle_select_send_events_for_device(struct input_config *ic, 64static void toggle_select_send_events_for_device(struct input_config *ic,
58 struct sway_input_device *input_device, int argc, char **argv) { 65 struct sway_input_device *input_device, int argc, char **argv) {
66#if WLR_HAS_LIBINPUT_BACKEND
59 if (!wlr_input_device_is_libinput(input_device->wlr_device)) { 67 if (!wlr_input_device_is_libinput(input_device->wlr_device)) {
60 return; 68 return;
61 } 69 }
@@ -72,6 +80,7 @@ static void toggle_select_send_events_for_device(struct input_config *ic,
72 } 80 }
73 } 81 }
74 ic->send_events = mode_for_name(argv[index % argc]); 82 ic->send_events = mode_for_name(argv[index % argc]);
83#endif
75} 84}
76 85
77static void toggle_send_events(int argc, char **argv) { 86static void toggle_send_events(int argc, char **argv) {
diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c
index de00b714..2f8f753d 100644
--- a/sway/commands/input/map_from_region.c
+++ b/sway/commands/input/map_from_region.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
@@ -11,11 +10,21 @@ static bool parse_coords(const char *str, double *x, double *y, bool *mm) {
11 *mm = false; 10 *mm = false;
12 11
13 char *end; 12 char *end;
14 *x = strtod(str, &end); 13
15 if (end[0] != 'x') { 14 // Check for "0x" prefix to avoid strtod treating the string as hex
16 return false; 15 if (str[0] == '0' && str[1] == 'x') {
16 if (strlen(str) < 3) {
17 return false;
18 }
19 *x = 0;
20 end = (char *)str + 2;
21 } else {
22 *x = strtod(str, &end);
23 if (end[0] != 'x') {
24 return false;
25 }
26 ++end;
17 } 27 }
18 ++end;
19 28
20 *y = strtod(end, &end); 29 *y = strtod(end, &end);
21 if (end[0] == 'm') { 30 if (end[0] == 'm') {
diff --git a/sway/commands/input/map_to_output.c b/sway/commands/input/map_to_output.c
index f60fb7d5..a7266baa 100644
--- a/sway/commands/input/map_to_output.c
+++ b/sway/commands/input/map_to_output.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include <strings.h> 2#include <strings.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/map_to_region.c b/sway/commands/input/map_to_region.c
index 284b57d0..9087c589 100644
--- a/sway/commands/input/map_to_region.c
+++ b/sway/commands/input/map_to_region.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
@@ -49,5 +48,5 @@ struct cmd_results *input_cmd_map_to_region(int argc, char **argv) {
49error: 48error:
50 free(ic->mapped_to_region); 49 free(ic->mapped_to_region);
51 ic->mapped_to_region = NULL; 50 ic->mapped_to_region = NULL;
52 return cmd_results_new(CMD_FAILURE, errstr); 51 return cmd_results_new(CMD_FAILURE, "%s", errstr);
53} 52}
diff --git a/sway/commands/input/rotation_angle.c b/sway/commands/input/rotation_angle.c
new file mode 100644
index 00000000..5e278fff
--- /dev/null
+++ b/sway/commands/input/rotation_angle.c
@@ -0,0 +1,29 @@
1#include <math.h>
2#include <stdlib.h>
3#include <string.h>
4#include "sway/config.h"
5#include "sway/commands.h"
6#include "sway/input/input-manager.h"
7#include "util.h"
8
9struct cmd_results *input_cmd_rotation_angle(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "rotation_angle", EXPECTED_AT_LEAST, 1))) {
12 return error;
13 }
14 struct input_config *ic = config->handler_context.input_config;
15 if (!ic) {
16 return cmd_results_new(CMD_FAILURE, "No input device defined.");
17 }
18
19 float rotation_angle = parse_float(argv[0]);
20 if (isnan(rotation_angle)) {
21 return cmd_results_new(CMD_INVALID,
22 "Invalid rotation_angle; expected float.");
23 } if (rotation_angle < 0 || rotation_angle > 360) {
24 return cmd_results_new(CMD_INVALID, "Input out of range [0, 360)");
25 }
26 ic->rotation_angle = rotation_angle;
27
28 return cmd_results_new(CMD_SUCCESS, NULL);
29}
diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c
index 6b331419..81f69a6d 100644
--- a/sway/commands/input/scroll_button.c
+++ b/sway/commands/input/scroll_button.c
@@ -21,7 +21,7 @@ struct cmd_results *input_cmd_scroll_button(int argc, char **argv) {
21 char *message = NULL; 21 char *message = NULL;
22 uint32_t button = get_mouse_button(*argv, &message); 22 uint32_t button = get_mouse_button(*argv, &message);
23 if (message) { 23 if (message) {
24 error = cmd_results_new(CMD_INVALID, message); 24 error = cmd_results_new(CMD_INVALID, "%s", message);
25 free(message); 25 free(message);
26 return error; 26 return error;
27 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN 27 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN
diff --git a/sway/commands/input/scroll_button_lock.c b/sway/commands/input/scroll_button_lock.c
new file mode 100644
index 00000000..f96b6514
--- /dev/null
+++ b/sway/commands/input/scroll_button_lock.c
@@ -0,0 +1,26 @@
1#include <libinput.h>
2#include <string.h>
3#include <strings.h>
4#include "sway/config.h"
5#include "sway/commands.h"
6#include "sway/input/input-manager.h"
7#include "util.h"
8
9struct cmd_results *input_cmd_scroll_button_lock(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "scroll_button_lock", EXPECTED_AT_LEAST, 1))) {
12 return error;
13 }
14 struct input_config *ic = config->handler_context.input_config;
15 if (!ic) {
16 return cmd_results_new(CMD_FAILURE, "No input device defined.");
17 }
18
19 if (parse_boolean(argv[0], true)) {
20 ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED;
21 } else {
22 ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
23 }
24
25 return cmd_results_new(CMD_SUCCESS, NULL);
26}
diff --git a/sway/commands/input/xkb_file.c b/sway/commands/input/xkb_file.c
index 493f94fb..056f00e5 100644
--- a/sway/commands/input/xkb_file.c
+++ b/sway/commands/input/xkb_file.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <unistd.h> 1#include <unistd.h>
3#include <errno.h> 2#include <errno.h>
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c
index 22626517..1d01886c 100644
--- a/sway/commands/input/xkb_layout.c
+++ b/sway/commands/input/xkb_layout.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c
index f4a33de3..a9144a8a 100644
--- a/sway/commands/input/xkb_model.c
+++ b/sway/commands/input/xkb_model.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_numlock.c b/sway/commands/input/xkb_numlock.c
index 87d3e60c..bbe848fe 100644
--- a/sway/commands/input/xkb_numlock.c
+++ b/sway/commands/input/xkb_numlock.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "util.h" 3#include "util.h"
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c
index d609293f..7ca20777 100644
--- a/sway/commands/input/xkb_options.c
+++ b/sway/commands/input/xkb_options.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c
index 3b59622c..8fbd26fb 100644
--- a/sway/commands/input/xkb_rules.c
+++ b/sway/commands/input/xkb_rules.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/input/xkb_switch_layout.c b/sway/commands/input/xkb_switch_layout.c
index dabc6697..8d600fca 100644
--- a/sway/commands/input/xkb_switch_layout.c
+++ b/sway/commands/input/xkb_switch_layout.c
@@ -1,9 +1,9 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <wlr/interfaces/wlr_keyboard.h> 2#include <wlr/interfaces/wlr_keyboard.h>
4#include "sway/config.h" 3#include "sway/config.h"
5#include "sway/commands.h" 4#include "sway/commands.h"
6#include "sway/input/input-manager.h" 5#include "sway/input/input-manager.h"
6#include "sway/server.h"
7#include "log.h" 7#include "log.h"
8 8
9struct xkb_switch_layout_action { 9struct xkb_switch_layout_action {
@@ -98,10 +98,9 @@ struct cmd_results *input_cmd_xkb_switch_layout(int argc, char **argv) {
98 struct xkb_switch_layout_action *action = 98 struct xkb_switch_layout_action *action =
99 &actions[actions_len++]; 99 &actions[actions_len++];
100 100
101 action->keyboard = dev->wlr_device->keyboard; 101 action->keyboard = wlr_keyboard_from_input_device(dev->wlr_device);
102 if (relative) { 102 if (relative) {
103 action->layout = get_layout_relative( 103 action->layout = get_layout_relative(action->keyboard, relative);
104 dev->wlr_device->keyboard, relative);
105 } else { 104 } else {
106 action->layout = layout; 105 action->layout = layout;
107 } 106 }
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c
index d0e21d77..2d14ea9c 100644
--- a/sway/commands/input/xkb_variant.c
+++ b/sway/commands/input/xkb_variant.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include "sway/config.h" 1#include "sway/config.h"
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "log.h" 3#include "log.h"
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 2ba61b38..12ce4839 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -153,7 +153,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
153 workspace->output); 153 workspace->output);
154 } 154 }
155 if (new_layout == L_NONE) { 155 if (new_layout == L_NONE) {
156 return cmd_results_new(CMD_INVALID, expected_syntax); 156 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
157 } 157 }
158 if (new_layout != old_layout) { 158 if (new_layout != old_layout) {
159 if (container) { 159 if (container) {
diff --git a/sway/commands/mark.c b/sway/commands/mark.c
index aa5f185c..2bfc86b3 100644
--- a/sway/commands/mark.c
+++ b/sway/commands/mark.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
@@ -59,7 +58,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
59 } 58 }
60 59
61 free(mark); 60 free(mark);
62 container_update_marks_textures(container); 61 container_update_marks(container);
63 if (container->view) { 62 if (container->view) {
64 view_execute_criteria(container->view); 63 view_execute_criteria(container->view);
65 } 64 }
diff --git a/sway/commands/mode.c b/sway/commands/mode.c
index e23e4ee4..b3216967 100644
--- a/sway/commands/mode.c
+++ b/sway/commands/mode.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdbool.h> 1#include <stdbool.h>
3#include <string.h> 2#include <string.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
@@ -11,10 +10,12 @@
11// Must be in order for the bsearch 10// Must be in order for the bsearch
12static const struct cmd_handler mode_handlers[] = { 11static const struct cmd_handler mode_handlers[] = {
13 { "bindcode", cmd_bindcode }, 12 { "bindcode", cmd_bindcode },
13 { "bindgesture", cmd_bindgesture },
14 { "bindswitch", cmd_bindswitch }, 14 { "bindswitch", cmd_bindswitch },
15 { "bindsym", cmd_bindsym }, 15 { "bindsym", cmd_bindsym },
16 { "set", cmd_set }, 16 { "set", cmd_set },
17 { "unbindcode", cmd_unbindcode }, 17 { "unbindcode", cmd_unbindcode },
18 { "unbindgesture", cmd_unbindgesture },
18 { "unbindswitch", cmd_unbindswitch }, 19 { "unbindswitch", cmd_unbindswitch },
19 { "unbindsym", cmd_unbindsym }, 20 { "unbindsym", cmd_unbindsym },
20}; 21};
@@ -59,6 +60,7 @@ struct cmd_results *cmd_mode(int argc, char **argv) {
59 mode->keycode_bindings = create_list(); 60 mode->keycode_bindings = create_list();
60 mode->mouse_bindings = create_list(); 61 mode->mouse_bindings = create_list();
61 mode->switch_bindings = create_list(); 62 mode->switch_bindings = create_list();
63 mode->gesture_bindings = create_list();
62 mode->pango = pango; 64 mode->pango = pango;
63 list_add(config->modes, mode); 65 list_add(config->modes, mode);
64 } 66 }
diff --git a/sway/commands/move.c b/sway/commands/move.c
index 0d0d9727..ff656cfb 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <math.h> 2#include <math.h>
4#include <stdbool.h> 3#include <stdbool.h>
@@ -12,6 +11,7 @@
12#include "sway/input/seat.h" 11#include "sway/input/seat.h"
13#include "sway/ipc-server.h" 12#include "sway/ipc-server.h"
14#include "sway/output.h" 13#include "sway/output.h"
14#include "sway/server.h"
15#include "sway/tree/arrange.h" 15#include "sway/tree/arrange.h"
16#include "sway/tree/container.h" 16#include "sway/tree/container.h"
17#include "sway/tree/root.h" 17#include "sway/tree/root.h"
@@ -206,9 +206,17 @@ static void container_move_to_workspace(struct sway_container *container,
206 container_detach(container); 206 container_detach(container);
207 workspace_add_floating(workspace, container); 207 workspace_add_floating(workspace, container);
208 container_handle_fullscreen_reparent(container); 208 container_handle_fullscreen_reparent(container);
209 // If changing output, center it within the workspace 209 // If changing output, adjust the coordinates of the window.
210 if (old_output != workspace->output && !container->pending.fullscreen_mode) { 210 if (old_output != workspace->output && !container->pending.fullscreen_mode) {
211 container_floating_move_to_center(container); 211 struct wlr_box workspace_box, old_workspace_box;
212 workspace_get_box(workspace, &workspace_box);
213 workspace_get_box(old_workspace, &old_workspace_box);
214 floating_fix_coordinates(container, &old_workspace_box, &workspace_box);
215 if (container->scratchpad && workspace->output) {
216 struct wlr_box output_box;
217 output_get_box(workspace->output, &output_box);
218 container->transform = workspace_box;
219 }
212 } 220 }
213 } else { 221 } else {
214 container_detach(container); 222 container_detach(container);
@@ -462,7 +470,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
462 if (strcasecmp(argv[1], "number") == 0) { 470 if (strcasecmp(argv[1], "number") == 0) {
463 // move [window|container] [to] "workspace number x" 471 // move [window|container] [to] "workspace number x"
464 if (argc < 3) { 472 if (argc < 3) {
465 return cmd_results_new(CMD_INVALID, expected_syntax); 473 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
466 } 474 }
467 if (!isdigit(argv[2][0])) { 475 if (!isdigit(argv[2][0])) {
468 return cmd_results_new(CMD_INVALID, 476 return cmd_results_new(CMD_INVALID,
@@ -522,7 +530,7 @@ static struct cmd_results *cmd_move_container(bool no_auto_back_and_forth,
522 } 530 }
523 destination = &dest_con->node; 531 destination = &dest_con->node;
524 } else { 532 } else {
525 return cmd_results_new(CMD_INVALID, expected_syntax); 533 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
526 } 534 }
527 535
528 if (destination->type == N_CONTAINER && 536 if (destination->type == N_CONTAINER &&
@@ -686,6 +694,9 @@ static struct cmd_results *cmd_move_workspace(int argc, char **argv) {
686 arrange_output(old_output); 694 arrange_output(old_output);
687 arrange_output(new_output); 695 arrange_output(new_output);
688 696
697 struct sway_seat *seat = config->handler_context.seat;
698 seat_consider_warp_to_focus(seat);
699
689 return cmd_results_new(CMD_SUCCESS, NULL); 700 return cmd_results_new(CMD_SUCCESS, NULL);
690} 701}
691 702
@@ -759,15 +770,6 @@ static struct cmd_results *cmd_move_in_direction(
759 ipc_event_window(container, "move"); 770 ipc_event_window(container, "move");
760 } 771 }
761 772
762 // Hack to re-focus container
763 seat_set_raw_focus(config->handler_context.seat, &new_ws->node);
764 seat_set_focus_container(config->handler_context.seat, container);
765
766 if (old_ws != new_ws) {
767 ipc_event_workspace(old_ws, new_ws, "focus");
768 workspace_detect_urgent(old_ws);
769 workspace_detect_urgent(new_ws);
770 }
771 container_end_mouse_operation(container); 773 container_end_mouse_operation(container);
772 774
773 return cmd_results_new(CMD_SUCCESS, NULL); 775 return cmd_results_new(CMD_SUCCESS, NULL);
@@ -818,7 +820,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
818 } 820 }
819 821
820 if (!argc) { 822 if (!argc) {
821 return cmd_results_new(CMD_INVALID, expected_position_syntax); 823 return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
822 } 824 }
823 825
824 bool absolute = false; 826 bool absolute = false;
@@ -828,19 +830,19 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
828 ++argv; 830 ++argv;
829 } 831 }
830 if (!argc) { 832 if (!argc) {
831 return cmd_results_new(CMD_INVALID, expected_position_syntax); 833 return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
832 } 834 }
833 if (strcmp(argv[0], "position") == 0) { 835 if (strcmp(argv[0], "position") == 0) {
834 --argc; 836 --argc;
835 ++argv; 837 ++argv;
836 } 838 }
837 if (!argc) { 839 if (!argc) {
838 return cmd_results_new(CMD_INVALID, expected_position_syntax); 840 return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
839 } 841 }
840 if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 || 842 if (strcmp(argv[0], "cursor") == 0 || strcmp(argv[0], "mouse") == 0 ||
841 strcmp(argv[0], "pointer") == 0) { 843 strcmp(argv[0], "pointer") == 0) {
842 if (absolute) { 844 if (absolute) {
843 return cmd_results_new(CMD_INVALID, expected_position_syntax); 845 return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
844 } 846 }
845 return cmd_move_to_position_pointer(container); 847 return cmd_move_to_position_pointer(container);
846 } else if (strcmp(argv[0], "center") == 0) { 848 } else if (strcmp(argv[0], "center") == 0) {
@@ -862,7 +864,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
862 } 864 }
863 865
864 if (argc < 2) { 866 if (argc < 2) {
865 return cmd_results_new(CMD_FAILURE, expected_position_syntax); 867 return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
866 } 868 }
867 869
868 struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; 870 struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
@@ -875,7 +877,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
875 } 877 }
876 878
877 if (argc < 1) { 879 if (argc < 1) {
878 return cmd_results_new(CMD_FAILURE, expected_position_syntax); 880 return cmd_results_new(CMD_FAILURE, "%s", expected_position_syntax);
879 } 881 }
880 882
881 struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID }; 883 struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
@@ -884,7 +886,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
884 argc -= num_consumed_args; 886 argc -= num_consumed_args;
885 argv += num_consumed_args; 887 argv += num_consumed_args;
886 if (argc > 0) { 888 if (argc > 0) {
887 return cmd_results_new(CMD_INVALID, expected_position_syntax); 889 return cmd_results_new(CMD_INVALID, "%s", expected_position_syntax);
888 } 890 }
889 if (ly.unit == MOVEMENT_UNIT_INVALID) { 891 if (ly.unit == MOVEMENT_UNIT_INVALID) {
890 return cmd_results_new(CMD_INVALID, "Invalid y position specified"); 892 return cmd_results_new(CMD_INVALID, "Invalid y position specified");
@@ -1030,13 +1032,13 @@ struct cmd_results *cmd_move(int argc, char **argv) {
1030 } 1032 }
1031 1033
1032 if (!argc) { 1034 if (!argc) {
1033 return cmd_results_new(CMD_INVALID, expected_full_syntax); 1035 return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
1034 } 1036 }
1035 1037
1036 // Only `move [window|container] [to] workspace` supports 1038 // Only `move [window|container] [to] workspace` supports
1037 // `--no-auto-back-and-forth` so treat others as invalid syntax 1039 // `--no-auto-back-and-forth` so treat others as invalid syntax
1038 if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) { 1040 if (no_auto_back_and_forth && strcasecmp(argv[0], "workspace") != 0) {
1039 return cmd_results_new(CMD_INVALID, expected_full_syntax); 1041 return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
1040 } 1042 }
1041 1043
1042 if (strcasecmp(argv[0], "workspace") == 0 || 1044 if (strcasecmp(argv[0], "workspace") == 0 ||
@@ -1050,5 +1052,5 @@ struct cmd_results *cmd_move(int argc, char **argv) {
1050 strcasecmp(argv[1], "position") == 0)) { 1052 strcasecmp(argv[1], "position") == 0)) {
1051 return cmd_move_to_position(argc, argv); 1053 return cmd_move_to_position(argc, argv);
1052 } 1054 }
1053 return cmd_results_new(CMD_INVALID, expected_full_syntax); 1055 return cmd_results_new(CMD_INVALID, "%s", expected_full_syntax);
1054} 1056}
diff --git a/sway/commands/no_focus.c b/sway/commands/no_focus.c
index 2001e04f..ccfdec82 100644
--- a/sway/commands/no_focus.c
+++ b/sway/commands/no_focus.c
@@ -13,7 +13,7 @@ struct cmd_results *cmd_no_focus(int argc, char **argv) {
13 char *err_str = NULL; 13 char *err_str = NULL;
14 struct criteria *criteria = criteria_parse(argv[0], &err_str); 14 struct criteria *criteria = criteria_parse(argv[0], &err_str);
15 if (!criteria) { 15 if (!criteria) {
16 error = cmd_results_new(CMD_INVALID, err_str); 16 error = cmd_results_new(CMD_INVALID, "%s", err_str);
17 free(err_str); 17 free(err_str);
18 return error; 18 return error;
19 } 19 }
diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c
index 96e6228e..610cecc6 100644
--- a/sway/commands/opacity.c
+++ b/sway/commands/opacity.c
@@ -37,6 +37,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
37 } 37 }
38 38
39 con->alpha = val; 39 con->alpha = val;
40 container_damage_whole(con); 40 container_update(con);
41
41 return cmd_results_new(CMD_SUCCESS, NULL); 42 return cmd_results_new(CMD_SUCCESS, NULL);
42} 43}
diff --git a/sway/commands/output.c b/sway/commands/output.c
index 125df5a7..5e5d31b3 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -18,6 +18,7 @@ static const struct cmd_handler output_handlers[] = {
18 { "modeline", output_cmd_modeline }, 18 { "modeline", output_cmd_modeline },
19 { "pos", output_cmd_position }, 19 { "pos", output_cmd_position },
20 { "position", output_cmd_position }, 20 { "position", output_cmd_position },
21 { "power", output_cmd_power },
21 { "render_bit_depth", output_cmd_render_bit_depth }, 22 { "render_bit_depth", output_cmd_render_bit_depth },
22 { "res", output_cmd_mode }, 23 { "res", output_cmd_mode },
23 { "resolution", output_cmd_mode }, 24 { "resolution", output_cmd_mode },
@@ -26,6 +27,7 @@ static const struct cmd_handler output_handlers[] = {
26 { "subpixel", output_cmd_subpixel }, 27 { "subpixel", output_cmd_subpixel },
27 { "toggle", output_cmd_toggle }, 28 { "toggle", output_cmd_toggle },
28 { "transform", output_cmd_transform }, 29 { "transform", output_cmd_transform },
30 { "unplug", output_cmd_unplug },
29}; 31};
30 32
31struct cmd_results *cmd_output(int argc, char **argv) { 33struct cmd_results *cmd_output(int argc, char **argv) {
@@ -101,15 +103,18 @@ struct cmd_results *cmd_output(int argc, char **argv) {
101 103
102 bool background = output->background; 104 bool background = output->background;
103 105
104 output = store_output_config(output); 106 store_output_config(output);
105 107
106 // If reloading, the output configs will be applied after reading the 108 // If reloading, the output configs will be applied after reading the
107 // entire config and before the deferred commands so that an auto generated 109 // entire config and before the deferred commands so that an auto generated
108 // workspace name is not given to re-enabled outputs. 110 // workspace name is not given to re-enabled outputs.
109 if (!config->reloading && !config->validating) { 111 if (!config->reloading && !config->validating) {
110 apply_output_config_to_outputs(output); 112 apply_all_output_configs();
111 if (background) { 113 if (background) {
112 spawn_swaybg(); 114 if (!spawn_swaybg()) {
115 return cmd_results_new(CMD_FAILURE,
116 "Failed to apply background configuration");
117 }
113 } 118 }
114 } 119 }
115 120
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c
index 67f212ff..55bd7671 100644
--- a/sway/commands/output/background.c
+++ b/sway/commands/output/background.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <libgen.h> 1#include <libgen.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <string.h> 3#include <string.h>
@@ -123,7 +122,10 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
123 src); 122 src);
124 config_add_swaynag_warning("Unable to access background file '%s'", 123 config_add_swaynag_warning("Unable to access background file '%s'",
125 src); 124 src);
125 struct cmd_results *result = cmd_results_new(CMD_FAILURE,
126 "unable to access background file '%s'", src);
126 free(src); 127 free(src);
128 return result;
127 } else { 129 } else {
128 output->background = src; 130 output->background = src;
129 output->background_option = strdup(mode); 131 output->background_option = strdup(mode);
diff --git a/sway/commands/output/dpms.c b/sway/commands/output/dpms.c
index 638c0ade..c7adbd58 100644
--- a/sway/commands/output/dpms.c
+++ b/sway/commands/output/dpms.c
@@ -1,45 +1,8 @@
1#include "log.h"
1#include "sway/commands.h" 2#include "sway/commands.h"
2#include "sway/config.h"
3#include "sway/output.h"
4#include "util.h"
5#include <strings.h>
6 3
7struct cmd_results *output_cmd_dpms(int argc, char **argv) { 4struct cmd_results *output_cmd_dpms(int argc, char **argv) {
8 if (!config->handler_context.output_config) { 5 sway_log(SWAY_INFO, "The \"output dpms\" command is deprecated, "
9 return cmd_results_new(CMD_FAILURE, "Missing output config"); 6 "use \"output power\" instead");
10 } 7 return output_cmd_power(argc, argv);
11 if (!argc) {
12 return cmd_results_new(CMD_INVALID, "Missing dpms argument.");
13 }
14
15 enum config_dpms current_dpms = DPMS_ON;
16
17 if (strcasecmp(argv[0], "toggle") == 0) {
18
19 const char *oc_name = config->handler_context.output_config->name;
20 if (strcmp(oc_name, "*") == 0) {
21 return cmd_results_new(CMD_INVALID,
22 "Cannot apply toggle to all outputs.");
23 }
24
25 struct sway_output *sway_output = all_output_by_name_or_id(oc_name);
26 if (!sway_output || !sway_output->wlr_output) {
27 return cmd_results_new(CMD_FAILURE,
28 "Cannot apply toggle to unknown output %s", oc_name);
29 }
30
31 if (sway_output->enabled && !sway_output->wlr_output->enabled) {
32 current_dpms = DPMS_OFF;
33 }
34 }
35
36 if (parse_boolean(argv[0], current_dpms == DPMS_ON)) {
37 config->handler_context.output_config->dpms_state = DPMS_ON;
38 } else {
39 config->handler_context.output_config->dpms_state = DPMS_OFF;
40 }
41
42 config->handler_context.leftovers.argc = argc - 1;
43 config->handler_context.leftovers.argv = argv + 1;
44 return NULL;
45} 8}
diff --git a/sway/commands/output/power.c b/sway/commands/output/power.c
new file mode 100644
index 00000000..e6ae2852
--- /dev/null
+++ b/sway/commands/output/power.c
@@ -0,0 +1,43 @@
1#include <strings.h>
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/output.h"
5#include "util.h"
6
7struct cmd_results *output_cmd_power(int argc, char **argv) {
8 if (!config->handler_context.output_config) {
9 return cmd_results_new(CMD_FAILURE, "Missing output config");
10 }
11 if (argc == 0) {
12 return cmd_results_new(CMD_INVALID, "Missing power argument");
13 }
14
15 bool current = true;
16 if (strcasecmp(argv[0], "toggle") == 0) {
17 const char *oc_name = config->handler_context.output_config->name;
18 if (strcmp(oc_name, "*") == 0) {
19 return cmd_results_new(CMD_INVALID,
20 "Cannot apply toggle to all outputs");
21 }
22
23 struct sway_output *sway_output = all_output_by_name_or_id(oc_name);
24 if (!sway_output || !sway_output->wlr_output) {
25 return cmd_results_new(CMD_FAILURE,
26 "Cannot apply toggle to unknown output %s", oc_name);
27 }
28
29 if (sway_output->enabled && !sway_output->wlr_output->enabled) {
30 current = false;
31 }
32 }
33
34 if (parse_boolean(argv[0], current)) {
35 config->handler_context.output_config->power = 1;
36 } else {
37 config->handler_context.output_config->power = 0;
38 }
39
40 config->handler_context.leftovers.argc = argc - 1;
41 config->handler_context.leftovers.argv = argv + 1;
42 return NULL;
43}
diff --git a/sway/commands/output/toggle.c b/sway/commands/output/toggle.c
index 6342d526..c6b72845 100644
--- a/sway/commands/output/toggle.c
+++ b/sway/commands/output/toggle.c
@@ -29,7 +29,7 @@ struct cmd_results *output_cmd_toggle(int argc, char **argv) {
29 config->handler_context.output_config->enabled = 1; 29 config->handler_context.output_config->enabled = 1;
30 } 30 }
31 31
32 free(oc); 32 free_output_config(oc);
33 config->handler_context.leftovers.argc = argc; 33 config->handler_context.leftovers.argc = argc;
34 config->handler_context.leftovers.argv = argv; 34 config->handler_context.leftovers.argv = argv;
35 return NULL; 35 return NULL;
diff --git a/sway/commands/output/transform.c b/sway/commands/output/transform.c
index f4fcc8c9..8db71bb3 100644
--- a/sway/commands/output/transform.c
+++ b/sway/commands/output/transform.c
@@ -1,4 +1,5 @@
1#include <string.h> 1#include <string.h>
2#include <wlr/util/transform.h>
2#include "sway/commands.h" 3#include "sway/commands.h"
3#include "sway/config.h" 4#include "sway/config.h"
4#include "log.h" 5#include "log.h"
diff --git a/sway/commands/output/unplug.c b/sway/commands/output/unplug.c
new file mode 100644
index 00000000..dfef626f
--- /dev/null
+++ b/sway/commands/output/unplug.c
@@ -0,0 +1,54 @@
1#include <strings.h>
2#include <wlr/config.h>
3#include <wlr/backend/headless.h>
4#include <wlr/backend/wayland.h>
5#if WLR_HAS_X11_BACKEND
6#include <wlr/backend/x11.h>
7#endif
8#include "sway/commands.h"
9#include "sway/config.h"
10#include "sway/output.h"
11
12static bool is_backend_allowed(struct wlr_backend *backend) {
13 if (wlr_backend_is_headless(backend)) {
14 return true;
15 }
16 if (wlr_backend_is_wl(backend)) {
17 return true;
18 }
19#if WLR_HAS_X11_BACKEND
20 if (wlr_backend_is_x11(backend)) {
21 return true;
22 }
23#endif
24 return false;
25}
26
27/**
28 * This command is intended for developer use only.
29 */
30struct cmd_results *output_cmd_unplug(int argc, char **argv) {
31 if (!config->handler_context.output_config) {
32 return cmd_results_new(CMD_FAILURE, "Missing output config");
33 }
34
35 const char *oc_name = config->handler_context.output_config->name;
36 if (strcmp(oc_name, "*") == 0) {
37 return cmd_results_new(CMD_INVALID, "Won't unplug all outputs");
38 }
39
40 struct sway_output *sway_output = all_output_by_name_or_id(oc_name);
41 if (!sway_output) {
42 return cmd_results_new(CMD_INVALID,
43 "Cannot unplug unknown output %s", oc_name);
44 }
45
46 if (!is_backend_allowed(sway_output->wlr_output->backend)) {
47 return cmd_results_new(CMD_INVALID,
48 "Can only unplug outputs with headless, wayland or x11 backend");
49 }
50
51 wlr_output_destroy(sway_output->wlr_output);
52
53 return cmd_results_new(CMD_SUCCESS, NULL);
54}
diff --git a/sway/commands/primary_selection.c b/sway/commands/primary_selection.c
new file mode 100644
index 00000000..9e2689c2
--- /dev/null
+++ b/sway/commands/primary_selection.c
@@ -0,0 +1,25 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/config.h"
4#include "sway/commands.h"
5#include "util.h"
6
7struct cmd_results *cmd_primary_selection(int argc, char **argv) {
8 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "primary_selection", EXPECTED_EQUAL_TO, 1))) {
10 return error;
11 }
12
13 bool primary_selection = parse_boolean(argv[0], true);
14
15 // config->primary_selection is reset to the previous value on reload in
16 // load_main_config()
17 if (config->reloading && config->primary_selection != primary_selection) {
18 return cmd_results_new(CMD_FAILURE,
19 "primary_selection can only be enabled/disabled at launch");
20 }
21
22 config->primary_selection = primary_selection;
23
24 return cmd_results_new(CMD_SUCCESS, NULL);
25}
diff --git a/sway/commands/reload.c b/sway/commands/reload.c
index 76f14bba..6c0aac26 100644
--- a/sway/commands/reload.c
+++ b/sway/commands/reload.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
@@ -9,9 +8,8 @@
9#include "list.h" 8#include "list.h"
10#include "log.h" 9#include "log.h"
11 10
12static void rebuild_textures_iterator(struct sway_container *con, void *data) { 11static void title_bar_update_iterator(struct sway_container *con, void *data) {
13 container_update_marks_textures(con); 12 container_update_title_bar(con);
14 container_update_title_textures(con);
15} 13}
16 14
17static void do_reload(void *data) { 15static void do_reload(void *data) {
@@ -48,7 +46,7 @@ static void do_reload(void *data) {
48 } 46 }
49 list_free_items_and_destroy(bar_ids); 47 list_free_items_and_destroy(bar_ids);
50 48
51 root_for_each_container(rebuild_textures_iterator, NULL); 49 root_for_each_container(title_bar_update_iterator, NULL);
52 50
53 arrange_root(); 51 arrange_root();
54} 52}
diff --git a/sway/commands/rename.c b/sway/commands/rename.c
index 3b855fdf..0d36cc21 100644
--- a/sway/commands/rename.c
+++ b/sway/commands/rename.c
@@ -7,6 +7,7 @@
7#include "sway/config.h" 7#include "sway/config.h"
8#include "sway/ipc-server.h" 8#include "sway/ipc-server.h"
9#include "sway/output.h" 9#include "sway/output.h"
10#include "sway/desktop/launcher.h"
10#include "sway/tree/container.h" 11#include "sway/tree/container.h"
11#include "sway/tree/workspace.h" 12#include "sway/tree/workspace.h"
12#include "sway/tree/root.h" 13#include "sway/tree/root.h"
@@ -25,7 +26,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
25 "Can't run this command while there's no outputs connected."); 26 "Can't run this command while there's no outputs connected.");
26 } 27 }
27 if (strcasecmp(argv[0], "workspace") != 0) { 28 if (strcasecmp(argv[0], "workspace") != 0) {
28 return cmd_results_new(CMD_INVALID, expected_syntax); 29 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
29 } 30 }
30 31
31 int argn = 1; 32 int argn = 1;
@@ -64,7 +65,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
64 ++argn; // move past "to" 65 ++argn; // move past "to"
65 66
66 if (argn >= argc) { 67 if (argn >= argc) {
67 return cmd_results_new(CMD_INVALID, expected_syntax); 68 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
68 } 69 }
69 70
70 char *new_name = join_args(argv + argn, argc - argn); 71 char *new_name = join_args(argv + argn, argc - argn);
@@ -91,8 +92,6 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
91 92
92 sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); 93 sway_log(SWAY_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name);
93 94
94 root_rename_pid_workspaces(workspace->name, new_name);
95
96 free(workspace->name); 95 free(workspace->name);
97 workspace->name = new_name; 96 workspace->name = new_name;
98 97
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 425069de..32b746ea 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -75,6 +75,10 @@ void container_resize_tiled(struct sway_container *con,
75 return; 75 return;
76 } 76 }
77 77
78 if (container_is_scratchpad_hidden_or_child(con)) {
79 return;
80 }
81
78 // For HORIZONTAL or VERTICAL, we are growing in two directions so select 82 // For HORIZONTAL or VERTICAL, we are growing in two directions so select
79 // both adjacent siblings. For RIGHT or DOWN, just select the next sibling. 83 // both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
80 // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to 84 // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
@@ -249,16 +253,35 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
249 struct movement_amount *amount) { 253 struct movement_amount *amount) {
250 struct sway_container *current = config->handler_context.container; 254 struct sway_container *current = config->handler_context.container;
251 255
256 if (container_is_scratchpad_hidden_or_child(current)) {
257 return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container");
258 }
259
252 if (amount->unit == MOVEMENT_UNIT_DEFAULT) { 260 if (amount->unit == MOVEMENT_UNIT_DEFAULT) {
253 amount->unit = MOVEMENT_UNIT_PPT; 261 amount->unit = MOVEMENT_UNIT_PPT;
254 } 262 }
255 if (amount->unit == MOVEMENT_UNIT_PPT) { 263 if (amount->unit == MOVEMENT_UNIT_PPT) {
264 struct sway_container *parent = current->pending.parent;
256 float pct = amount->amount / 100.0f; 265 float pct = amount->amount / 100.0f;
257 266
258 if (is_horizontal(axis)) { 267 if (is_horizontal(axis)) {
259 amount->amount = (float)current->pending.width * pct; 268 while (parent && parent->pending.layout != L_HORIZ) {
269 parent = parent->pending.parent;
270 }
271 if (parent) {
272 amount->amount = (float)parent->pending.width * pct;
273 } else {
274 amount->amount = (float)current->pending.workspace->width * pct;
275 }
260 } else { 276 } else {
261 amount->amount = (float)current->pending.height * pct; 277 while (parent && parent->pending.layout != L_VERT) {
278 parent = parent->pending.parent;
279 }
280 if (parent) {
281 amount->amount = (float)parent->pending.height * pct;
282 } else {
283 amount->amount = (float)current->pending.workspace->height * pct;
284 }
262 } 285 }
263 } 286 }
264 287
@@ -277,6 +300,11 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
277 */ 300 */
278static struct cmd_results *resize_set_tiled(struct sway_container *con, 301static struct cmd_results *resize_set_tiled(struct sway_container *con,
279 struct movement_amount *width, struct movement_amount *height) { 302 struct movement_amount *width, struct movement_amount *height) {
303
304 if (container_is_scratchpad_hidden_or_child(con)) {
305 return cmd_results_new(CMD_FAILURE, "Cannot resize a hidden scratchpad container");
306 }
307
280 if (width->amount) { 308 if (width->amount) {
281 if (width->unit == MOVEMENT_UNIT_PPT || 309 if (width->unit == MOVEMENT_UNIT_PPT ||
282 width->unit == MOVEMENT_UNIT_DEFAULT) { 310 width->unit == MOVEMENT_UNIT_DEFAULT) {
@@ -415,7 +443,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
415 argc -= num_consumed_args; 443 argc -= num_consumed_args;
416 argv += num_consumed_args; 444 argv += num_consumed_args;
417 if (width.unit == MOVEMENT_UNIT_INVALID) { 445 if (width.unit == MOVEMENT_UNIT_INVALID) {
418 return cmd_results_new(CMD_INVALID, usage); 446 return cmd_results_new(CMD_INVALID, "%s", usage);
419 } 447 }
420 } 448 }
421 449
@@ -427,10 +455,10 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
427 } 455 }
428 int num_consumed_args = parse_movement_amount(argc, argv, &height); 456 int num_consumed_args = parse_movement_amount(argc, argv, &height);
429 if (argc > num_consumed_args) { 457 if (argc > num_consumed_args) {
430 return cmd_results_new(CMD_INVALID, usage); 458 return cmd_results_new(CMD_INVALID, "%s", usage);
431 } 459 }
432 if (width.unit == MOVEMENT_UNIT_INVALID) { 460 if (width.unit == MOVEMENT_UNIT_INVALID) {
433 return cmd_results_new(CMD_INVALID, usage); 461 return cmd_results_new(CMD_INVALID, "%s", usage);
434 } 462 }
435 } 463 }
436 464
@@ -462,7 +490,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
462 "[<amount> px|ppt [or <amount> px|ppt]]'"; 490 "[<amount> px|ppt [or <amount> px|ppt]]'";
463 uint32_t axis = parse_resize_axis(*argv); 491 uint32_t axis = parse_resize_axis(*argv);
464 if (axis == WLR_EDGE_NONE) { 492 if (axis == WLR_EDGE_NONE) {
465 return cmd_results_new(CMD_INVALID, usage); 493 return cmd_results_new(CMD_INVALID, "%s", usage);
466 } 494 }
467 --argc; ++argv; 495 --argc; ++argv;
468 496
@@ -473,7 +501,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
473 argc -= num_consumed_args; 501 argc -= num_consumed_args;
474 argv += num_consumed_args; 502 argv += num_consumed_args;
475 if (first_amount.unit == MOVEMENT_UNIT_INVALID) { 503 if (first_amount.unit == MOVEMENT_UNIT_INVALID) {
476 return cmd_results_new(CMD_INVALID, usage); 504 return cmd_results_new(CMD_INVALID, "%s", usage);
477 } 505 }
478 } else { 506 } else {
479 first_amount.amount = 10; 507 first_amount.amount = 10;
@@ -483,7 +511,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
483 // "or" 511 // "or"
484 if (argc) { 512 if (argc) {
485 if (strcmp(*argv, "or") != 0) { 513 if (strcmp(*argv, "or") != 0) {
486 return cmd_results_new(CMD_INVALID, usage); 514 return cmd_results_new(CMD_INVALID, "%s", usage);
487 } 515 }
488 --argc; ++argv; 516 --argc; ++argv;
489 } 517 }
@@ -493,10 +521,10 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
493 if (argc) { 521 if (argc) {
494 int num_consumed_args = parse_movement_amount(argc, argv, &second_amount); 522 int num_consumed_args = parse_movement_amount(argc, argv, &second_amount);
495 if (argc > num_consumed_args) { 523 if (argc > num_consumed_args) {
496 return cmd_results_new(CMD_INVALID, usage); 524 return cmd_results_new(CMD_INVALID, "%s", usage);
497 } 525 }
498 if (second_amount.unit == MOVEMENT_UNIT_INVALID) { 526 if (second_amount.unit == MOVEMENT_UNIT_INVALID) {
499 return cmd_results_new(CMD_INVALID, usage); 527 return cmd_results_new(CMD_INVALID, "%s", usage);
500 } 528 }
501 } else { 529 } else {
502 second_amount.amount = 0; 530 second_amount.amount = 0;
@@ -566,5 +594,5 @@ struct cmd_results *cmd_resize(int argc, char **argv) {
566 const char usage[] = "Expected 'resize <shrink|grow> " 594 const char usage[] = "Expected 'resize <shrink|grow> "
567 "<width|height|up|down|left|right> [<amount>] [px|ppt]'"; 595 "<width|height|up|down|left|right> [<amount>] [px|ppt]'";
568 596
569 return cmd_results_new(CMD_INVALID, usage); 597 return cmd_results_new(CMD_INVALID, "%s", usage);
570} 598}
diff --git a/sway/commands/seat/attach.c b/sway/commands/seat/attach.c
index 00bfdab6..47d18546 100644
--- a/sway/commands/seat/attach.c
+++ b/sway/commands/seat/attach.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c
index 504a9f5e..434e6bbb 100644
--- a/sway/commands/seat/cursor.c
+++ b/sway/commands/seat/cursor.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <linux/input-event-codes.h> 1#include <linux/input-event-codes.h>
3 2
4#include <strings.h> 3#include <strings.h>
@@ -6,6 +5,7 @@
6#include <wlr/types/wlr_pointer.h> 5#include <wlr/types/wlr_pointer.h>
7#include "sway/commands.h" 6#include "sway/commands.h"
8#include "sway/input/cursor.h" 7#include "sway/input/cursor.h"
8#include "sway/server.h"
9 9
10static struct cmd_results *press_or_release(struct sway_cursor *cursor, 10static struct cmd_results *press_or_release(struct sway_cursor *cursor,
11 char *action, char *button_str); 11 char *action, char *button_str);
@@ -18,7 +18,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
18 int argc, char **argv) { 18 int argc, char **argv) {
19 if (strcasecmp(argv[0], "move") == 0) { 19 if (strcasecmp(argv[0], "move") == 0) {
20 if (argc < 3) { 20 if (argc < 3) {
21 return cmd_results_new(CMD_INVALID, expected_syntax); 21 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
22 } 22 }
23 int delta_x = strtol(argv[1], NULL, 10); 23 int delta_x = strtol(argv[1], NULL, 10);
24 int delta_y = strtol(argv[2], NULL, 10); 24 int delta_y = strtol(argv[2], NULL, 10);
@@ -27,7 +27,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
27 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 27 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
28 } else if (strcasecmp(argv[0], "set") == 0) { 28 } else if (strcasecmp(argv[0], "set") == 0) {
29 if (argc < 3) { 29 if (argc < 3) {
30 return cmd_results_new(CMD_INVALID, expected_syntax); 30 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
31 } 31 }
32 // map absolute coords (0..1,0..1) to root container coords 32 // map absolute coords (0..1,0..1) to root container coords
33 float x = strtof(argv[1], NULL) / root->width; 33 float x = strtof(argv[1], NULL) / root->width;
@@ -37,7 +37,7 @@ static struct cmd_results *handle_command(struct sway_cursor *cursor,
37 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 37 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
38 } else { 38 } else {
39 if (argc < 2) { 39 if (argc < 2) {
40 return cmd_results_new(CMD_INVALID, expected_syntax); 40 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
41 } 41 }
42 struct cmd_results *error = NULL; 42 struct cmd_results *error = NULL;
43 if ((error = press_or_release(cursor, argv[0], argv[1]))) { 43 if ((error = press_or_release(cursor, argv[0], argv[1]))) {
@@ -85,36 +85,36 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
85 85
86static struct cmd_results *press_or_release(struct sway_cursor *cursor, 86static struct cmd_results *press_or_release(struct sway_cursor *cursor,
87 char *action, char *button_str) { 87 char *action, char *button_str) {
88 enum wlr_button_state state; 88 enum wl_pointer_button_state state;
89 uint32_t button; 89 uint32_t button;
90 if (strcasecmp(action, "press") == 0) { 90 if (strcasecmp(action, "press") == 0) {
91 state = WLR_BUTTON_PRESSED; 91 state = WL_POINTER_BUTTON_STATE_PRESSED;
92 } else if (strcasecmp(action, "release") == 0) { 92 } else if (strcasecmp(action, "release") == 0) {
93 state = WLR_BUTTON_RELEASED; 93 state = WL_POINTER_BUTTON_STATE_RELEASED;
94 } else { 94 } else {
95 return cmd_results_new(CMD_INVALID, expected_syntax); 95 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
96 } 96 }
97 97
98 char *message = NULL; 98 char *message = NULL;
99 button = get_mouse_button(button_str, &message); 99 button = get_mouse_button(button_str, &message);
100 if (message) { 100 if (message) {
101 struct cmd_results *error = 101 struct cmd_results *error =
102 cmd_results_new(CMD_INVALID, message); 102 cmd_results_new(CMD_INVALID, "%s", message);
103 free(message); 103 free(message);
104 return error; 104 return error;
105 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN 105 } else if (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN
106 || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) { 106 || button == SWAY_SCROLL_LEFT || button == SWAY_SCROLL_RIGHT) {
107 // Dispatch axis event 107 // Dispatch axis event
108 enum wlr_axis_orientation orientation = 108 enum wl_pointer_axis orientation =
109 (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN) 109 (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_DOWN)
110 ? WLR_AXIS_ORIENTATION_VERTICAL 110 ? WL_POINTER_AXIS_VERTICAL_SCROLL
111 : WLR_AXIS_ORIENTATION_HORIZONTAL; 111 : WL_POINTER_AXIS_HORIZONTAL_SCROLL;
112 double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT) 112 double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT)
113 ? -1 : 1; 113 ? -1 : 1;
114 struct wlr_pointer_axis_event event = { 114 struct wlr_pointer_axis_event event = {
115 .pointer = NULL, 115 .pointer = NULL,
116 .time_msec = 0, 116 .time_msec = 0,
117 .source = WLR_AXIS_SOURCE_WHEEL, 117 .source = WL_POINTER_AXIS_SOURCE_WHEEL,
118 .orientation = orientation, 118 .orientation = orientation,
119 .delta = delta * 15, 119 .delta = delta * 15,
120 .delta_discrete = delta 120 .delta_discrete = delta
diff --git a/sway/commands/seat/hide_cursor.c b/sway/commands/seat/hide_cursor.c
index e09b82d9..f5177a47 100644
--- a/sway/commands/seat/hide_cursor.c
+++ b/sway/commands/seat/hide_cursor.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/seat/idle.c b/sway/commands/seat/idle.c
index 82428f2c..2974453e 100644
--- a/sway/commands/seat/idle.c
+++ b/sway/commands/seat/idle.c
@@ -1,8 +1,8 @@
1#define _POSIX_C_SOURCE 200809L
2#include <limits.h> 1#include <limits.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
5#include <stdint.h> 4#include <stdint.h>
5#include "log.h"
6#include "sway/commands.h" 6#include "sway/commands.h"
7#include "sway/config.h" 7#include "sway/config.h"
8#include "sway/input/seat.h" 8#include "sway/input/seat.h"
@@ -69,5 +69,10 @@ struct cmd_results *seat_cmd_idle_wake(int argc, char **argv) {
69 return cmd_results_new(CMD_FAILURE, "Invalid idle source"); 69 return cmd_results_new(CMD_FAILURE, "Invalid idle source");
70 } 70 }
71 config->handler_context.seat_config->idle_wake_sources = sources; 71 config->handler_context.seat_config->idle_wake_sources = sources;
72 sway_log(SWAY_INFO, "Warning: seat idle_wake is deprecated");
73 if (config->reading) {
74 config_add_swaynag_warning("seat idle_wake is deprecated. "
75 "Only seat idle_inhibit is supported.");
76 }
72 return cmd_results_new(CMD_SUCCESS, NULL); 77 return cmd_results_new(CMD_SUCCESS, NULL);
73} 78}
diff --git a/sway/commands/seat/pointer_constraint.c b/sway/commands/seat/pointer_constraint.c
index 3890ebde..38f85bcd 100644
--- a/sway/commands/seat/pointer_constraint.c
+++ b/sway/commands/seat/pointer_constraint.c
@@ -4,6 +4,7 @@
4#include "sway/config.h" 4#include "sway/config.h"
5#include "sway/input/cursor.h" 5#include "sway/input/cursor.h"
6#include "sway/input/seat.h" 6#include "sway/input/seat.h"
7#include "sway/server.h"
7 8
8enum operation { 9enum operation {
9 OP_ENABLE, 10 OP_ENABLE,
diff --git a/sway/commands/seat/shortcuts_inhibitor.c b/sway/commands/seat/shortcuts_inhibitor.c
index 7c7f99cf..df68618d 100644
--- a/sway/commands/seat/shortcuts_inhibitor.c
+++ b/sway/commands/seat/shortcuts_inhibitor.c
@@ -2,6 +2,7 @@
2#include "sway/commands.h" 2#include "sway/commands.h"
3#include "sway/input/seat.h" 3#include "sway/input/seat.h"
4#include "sway/input/input-manager.h" 4#include "sway/input/input-manager.h"
5#include "sway/server.h"
5#include "util.h" 6#include "util.h"
6 7
7static struct cmd_results *handle_action(struct seat_config *sc, 8static struct cmd_results *handle_action(struct seat_config *sc,
diff --git a/sway/commands/seat/xcursor_theme.c b/sway/commands/seat/xcursor_theme.c
index 202f35b9..61322a57 100644
--- a/sway/commands/seat/xcursor_theme.c
+++ b/sway/commands/seat/xcursor_theme.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/set.c b/sway/commands/set.c
index c539e9fc..ba384c7c 100644
--- a/sway/commands/set.c
+++ b/sway/commands/set.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdio.h> 1#include <stdio.h>
3#include <string.h> 2#include <string.h>
4#include <strings.h> 3#include <strings.h>
diff --git a/sway/commands/shortcuts_inhibitor.c b/sway/commands/shortcuts_inhibitor.c
index ffa1a5c9..2dfd1b9f 100644
--- a/sway/commands/shortcuts_inhibitor.c
+++ b/sway/commands/shortcuts_inhibitor.c
@@ -3,6 +3,7 @@
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/config.h" 4#include "sway/config.h"
5#include "sway/input/seat.h" 5#include "sway/input/seat.h"
6#include "sway/server.h"
6#include "sway/tree/container.h" 7#include "sway/tree/container.h"
7#include "sway/tree/view.h" 8#include "sway/tree/view.h"
8 9
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c
index 0d373b80..60cef9fa 100644
--- a/sway/commands/show_marks.c
+++ b/sway/commands/show_marks.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
@@ -10,8 +9,8 @@
10#include "stringop.h" 9#include "stringop.h"
11#include "util.h" 10#include "util.h"
12 11
13static void rebuild_marks_iterator(struct sway_container *con, void *data) { 12static void title_bar_update_iterator(struct sway_container *con, void *data) {
14 container_update_marks_textures(con); 13 container_update_marks(con);
15} 14}
16 15
17struct cmd_results *cmd_show_marks(int argc, char **argv) { 16struct cmd_results *cmd_show_marks(int argc, char **argv) {
@@ -23,12 +22,7 @@ struct cmd_results *cmd_show_marks(int argc, char **argv) {
23 config->show_marks = parse_boolean(argv[0], config->show_marks); 22 config->show_marks = parse_boolean(argv[0], config->show_marks);
24 23
25 if (config->show_marks) { 24 if (config->show_marks) {
26 root_for_each_container(rebuild_marks_iterator, NULL); 25 root_for_each_container(title_bar_update_iterator, NULL);
27 }
28
29 for (int i = 0; i < root->outputs->length; ++i) {
30 struct sway_output *output = root->outputs->items[i];
31 output_damage_whole(output);
32 } 26 }
33 27
34 return cmd_results_new(CMD_SUCCESS, NULL); 28 return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/split.c b/sway/commands/split.c
index c8a2cfc1..500a497d 100644
--- a/sway/commands/split.c
+++ b/sway/commands/split.c
@@ -32,7 +32,7 @@ static struct cmd_results *do_split(int layout) {
32 return cmd_results_new(CMD_SUCCESS, NULL); 32 return cmd_results_new(CMD_SUCCESS, NULL);
33} 33}
34 34
35static struct cmd_results *do_unsplit() { 35static struct cmd_results *do_unsplit(void) {
36 struct sway_container *con = config->handler_context.container; 36 struct sway_container *con = config->handler_context.container;
37 struct sway_workspace *ws = config->handler_context.workspace; 37 struct sway_workspace *ws = config->handler_context.workspace;
38 38
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index 9355944d..c0b0d0b9 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -1,10 +1,10 @@
1#define _POSIX_C_SOURCE 200809L
2#include <strings.h> 1#include <strings.h>
3#include "config.h" 2#include "config.h"
4#include "log.h" 3#include "log.h"
5#include "sway/commands.h" 4#include "sway/commands.h"
6#include "sway/output.h" 5#include "sway/output.h"
7#include "sway/tree/arrange.h" 6#include "sway/tree/arrange.h"
7#include "sway/tree/container.h"
8#include "sway/tree/root.h" 8#include "sway/tree/root.h"
9#include "sway/tree/view.h" 9#include "sway/tree/view.h"
10#include "sway/tree/workspace.h" 10#include "sway/tree/workspace.h"
@@ -13,186 +13,12 @@
13static const char expected_syntax[] = 13static const char expected_syntax[] =
14 "Expected 'swap container with id|con_id|mark <arg>'"; 14 "Expected 'swap container with id|con_id|mark <arg>'";
15 15
16static void swap_places(struct sway_container *con1,
17 struct sway_container *con2) {
18 struct sway_container *temp = malloc(sizeof(struct sway_container));
19 temp->pending.x = con1->pending.x;
20 temp->pending.y = con1->pending.y;
21 temp->pending.width = con1->pending.width;
22 temp->pending.height = con1->pending.height;
23 temp->width_fraction = con1->width_fraction;
24 temp->height_fraction = con1->height_fraction;
25 temp->pending.parent = con1->pending.parent;
26 temp->pending.workspace = con1->pending.workspace;
27 bool temp_floating = container_is_floating(con1);
28
29 con1->pending.x = con2->pending.x;
30 con1->pending.y = con2->pending.y;
31 con1->pending.width = con2->pending.width;
32 con1->pending.height = con2->pending.height;
33 con1->width_fraction = con2->width_fraction;
34 con1->height_fraction = con2->height_fraction;
35
36 con2->pending.x = temp->pending.x;
37 con2->pending.y = temp->pending.y;
38 con2->pending.width = temp->pending.width;
39 con2->pending.height = temp->pending.height;
40 con2->width_fraction = temp->width_fraction;
41 con2->height_fraction = temp->height_fraction;
42
43 int temp_index = container_sibling_index(con1);
44 if (con2->pending.parent) {
45 container_insert_child(con2->pending.parent, con1,
46 container_sibling_index(con2));
47 } else if (container_is_floating(con2)) {
48 workspace_add_floating(con2->pending.workspace, con1);
49 } else {
50 workspace_insert_tiling(con2->pending.workspace, con1,
51 container_sibling_index(con2));
52 }
53 if (temp->pending.parent) {
54 container_insert_child(temp->pending.parent, con2, temp_index);
55 } else if (temp_floating) {
56 workspace_add_floating(temp->pending.workspace, con2);
57 } else {
58 workspace_insert_tiling(temp->pending.workspace, con2, temp_index);
59 }
60
61 free(temp);
62}
63
64static void swap_focus(struct sway_container *con1,
65 struct sway_container *con2, struct sway_seat *seat,
66 struct sway_container *focus) {
67 if (focus == con1 || focus == con2) {
68 struct sway_workspace *ws1 = con1->pending.workspace;
69 struct sway_workspace *ws2 = con2->pending.workspace;
70 enum sway_container_layout layout1 = container_parent_layout(con1);
71 enum sway_container_layout layout2 = container_parent_layout(con2);
72 if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) {
73 if (workspace_is_visible(ws2)) {
74 seat_set_focus(seat, &con2->node);
75 }
76 seat_set_focus_container(seat, ws1 != ws2 ? con2 : con1);
77 } else if (focus == con2 && (layout1 == L_TABBED
78 || layout1 == L_STACKED)) {
79 if (workspace_is_visible(ws1)) {
80 seat_set_focus(seat, &con1->node);
81 }
82 seat_set_focus_container(seat, ws1 != ws2 ? con1 : con2);
83 } else if (ws1 != ws2) {
84 seat_set_focus_container(seat, focus == con1 ? con2 : con1);
85 } else {
86 seat_set_focus_container(seat, focus);
87 }
88 } else {
89 seat_set_focus_container(seat, focus);
90 }
91
92 if (root->fullscreen_global) {
93 seat_set_focus(seat,
94 seat_get_focus_inactive(seat, &root->fullscreen_global->node));
95 }
96}
97
98void container_swap(struct sway_container *con1, struct sway_container *con2) {
99 if (!sway_assert(con1 && con2, "Cannot swap with nothing")) {
100 return;
101 }
102 if (!sway_assert(!container_has_ancestor(con1, con2)
103 && !container_has_ancestor(con2, con1),
104 "Cannot swap ancestor and descendant")) {
105 return;
106 }
107
108 sway_log(SWAY_DEBUG, "Swapping containers %zu and %zu",
109 con1->node.id, con2->node.id);
110
111 bool scratch1 = con1->scratchpad;
112 bool hidden1 = container_is_scratchpad_hidden(con1);
113 bool scratch2 = con2->scratchpad;
114 bool hidden2 = container_is_scratchpad_hidden(con2);
115 if (scratch1) {
116 if (hidden1) {
117 root_scratchpad_show(con1);
118 }
119 root_scratchpad_remove_container(con1);
120 }
121 if (scratch2) {
122 if (hidden2) {
123 root_scratchpad_show(con2);
124 }
125 root_scratchpad_remove_container(con2);
126 }
127
128 enum sway_fullscreen_mode fs1 = con1->pending.fullscreen_mode;
129 if (fs1) {
130 container_fullscreen_disable(con1);
131 }
132 enum sway_fullscreen_mode fs2 = con2->pending.fullscreen_mode;
133 if (fs2) {
134 container_fullscreen_disable(con2);
135 }
136
137 struct sway_seat *seat = config->handler_context.seat;
138 struct sway_container *focus = seat_get_focused_container(seat);
139 struct sway_workspace *vis1 =
140 output_get_active_workspace(con1->pending.workspace->output);
141 struct sway_workspace *vis2 =
142 output_get_active_workspace(con2->pending.workspace->output);
143 if (!sway_assert(vis1 && vis2, "con1 or con2 are on an output without a"
144 "workspace. This should not happen")) {
145 return;
146 }
147
148 char *stored_prev_name = NULL;
149 if (seat->prev_workspace_name) {
150 stored_prev_name = strdup(seat->prev_workspace_name);
151 }
152
153 swap_places(con1, con2);
154
155 if (!workspace_is_visible(vis1)) {
156 seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node));
157 }
158 if (!workspace_is_visible(vis2)) {
159 seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node));
160 }
161
162 swap_focus(con1, con2, seat, focus);
163
164 if (stored_prev_name) {
165 free(seat->prev_workspace_name);
166 seat->prev_workspace_name = stored_prev_name;
167 }
168
169 if (scratch1) {
170 root_scratchpad_add_container(con2, NULL);
171 if (!hidden1) {
172 root_scratchpad_show(con2);
173 }
174 }
175 if (scratch2) {
176 root_scratchpad_add_container(con1, NULL);
177 if (!hidden2) {
178 root_scratchpad_show(con1);
179 }
180 }
181
182 if (fs1) {
183 container_set_fullscreen(con2, fs1);
184 }
185 if (fs2) {
186 container_set_fullscreen(con1, fs2);
187 }
188}
189
190static bool test_con_id(struct sway_container *container, void *data) { 16static bool test_con_id(struct sway_container *container, void *data) {
191 size_t *con_id = data; 17 size_t *con_id = data;
192 return container->node.id == *con_id; 18 return container->node.id == *con_id;
193} 19}
194 20
195#if HAVE_XWAYLAND 21#if WLR_HAS_XWAYLAND
196static bool test_id(struct sway_container *container, void *data) { 22static bool test_id(struct sway_container *container, void *data) {
197 xcb_window_t *wid = data; 23 xcb_window_t *wid = data;
198 return (container->view && container->view->type == SWAY_VIEW_XWAYLAND 24 return (container->view && container->view->type == SWAY_VIEW_XWAYLAND
@@ -219,7 +45,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
219 } 45 }
220 46
221 if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) { 47 if (strcasecmp(argv[0], "container") || strcasecmp(argv[1], "with")) {
222 return cmd_results_new(CMD_INVALID, expected_syntax); 48 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
223 } 49 }
224 50
225 struct sway_container *current = config->handler_context.container; 51 struct sway_container *current = config->handler_context.container;
@@ -227,7 +53,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
227 53
228 char *value = join_args(argv + 3, argc - 3); 54 char *value = join_args(argv + 3, argc - 3);
229 if (strcasecmp(argv[2], "id") == 0) { 55 if (strcasecmp(argv[2], "id") == 0) {
230#if HAVE_XWAYLAND 56#if WLR_HAS_XWAYLAND
231 xcb_window_t id = strtol(value, NULL, 0); 57 xcb_window_t id = strtol(value, NULL, 0);
232 other = root_find_container(test_id, &id); 58 other = root_find_container(test_id, &id);
233#endif 59#endif
@@ -238,7 +64,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
238 other = root_find_container(test_mark, value); 64 other = root_find_container(test_mark, value);
239 } else { 65 } else {
240 free(value); 66 free(value);
241 return cmd_results_new(CMD_INVALID, expected_syntax); 67 return cmd_results_new(CMD_INVALID, "%s", expected_syntax);
242 } 68 }
243 69
244 if (!other) { 70 if (!other) {
diff --git a/sway/commands/title_align.c b/sway/commands/title_align.c
index c30355de..be298a29 100644
--- a/sway/commands/title_align.c
+++ b/sway/commands/title_align.c
@@ -4,6 +4,10 @@
4#include "sway/tree/container.h" 4#include "sway/tree/container.h"
5#include "sway/tree/root.h" 5#include "sway/tree/root.h"
6 6
7static void arrange_title_bar_iterator(struct sway_container *con, void *data) {
8 container_arrange_title_bar(con);
9}
10
7struct cmd_results *cmd_title_align(int argc, char **argv) { 11struct cmd_results *cmd_title_align(int argc, char **argv) {
8 struct cmd_results *error = NULL; 12 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) { 13 if ((error = checkarg(argc, "title_align", EXPECTED_AT_LEAST, 1))) {
@@ -21,10 +25,7 @@ struct cmd_results *cmd_title_align(int argc, char **argv) {
21 "Expected 'title_align left|center|right'"); 25 "Expected 'title_align left|center|right'");
22 } 26 }
23 27
24 for (int i = 0; i < root->outputs->length; ++i) { 28 root_for_each_container(arrange_title_bar_iterator, NULL);
25 struct sway_output *output = root->outputs->items[i];
26 output_damage_whole(output);
27 }
28 29
29 return cmd_results_new(CMD_SUCCESS, NULL); 30 return cmd_results_new(CMD_SUCCESS, NULL);
30} 31}
diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c
index a2446b7e..0b2ea265 100644
--- a/sway/commands/title_format.c
+++ b/sway/commands/title_format.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
diff --git a/sway/commands/titlebar_border_thickness.c b/sway/commands/titlebar_border_thickness.c
index 7c27c163..fa3db3c5 100644
--- a/sway/commands/titlebar_border_thickness.c
+++ b/sway/commands/titlebar_border_thickness.c
@@ -27,7 +27,6 @@ struct cmd_results *cmd_titlebar_border_thickness(int argc, char **argv) {
27 "Expected output to have a workspace"); 27 "Expected output to have a workspace");
28 } 28 }
29 arrange_workspace(ws); 29 arrange_workspace(ws);
30 output_damage_whole(output);
31 } 30 }
32 31
33 return cmd_results_new(CMD_SUCCESS, NULL); 32 return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/titlebar_padding.c b/sway/commands/titlebar_padding.c
index 29ce59ff..6999f7a2 100644
--- a/sway/commands/titlebar_padding.c
+++ b/sway/commands/titlebar_padding.c
@@ -33,7 +33,6 @@ struct cmd_results *cmd_titlebar_padding(int argc, char **argv) {
33 for (int i = 0; i < root->outputs->length; ++i) { 33 for (int i = 0; i < root->outputs->length; ++i) {
34 struct sway_output *output = root->outputs->items[i]; 34 struct sway_output *output = root->outputs->items[i];
35 arrange_workspace(output_get_active_workspace(output)); 35 arrange_workspace(output_get_active_workspace(output));
36 output_damage_whole(output);
37 } 36 }
38 37
39 return cmd_results_new(CMD_SUCCESS, NULL); 38 return cmd_results_new(CMD_SUCCESS, NULL);
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c
index 19274dfb..4aba5bae 100644
--- a/sway/commands/unmark.c
+++ b/sway/commands/unmark.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <string.h> 1#include <string.h>
3#include "sway/commands.h" 2#include "sway/commands.h"
4#include "sway/config.h" 3#include "sway/config.h"
@@ -8,9 +7,13 @@
8#include "log.h" 7#include "log.h"
9#include "stringop.h" 8#include "stringop.h"
10 9
11static void remove_all_marks_iterator(struct sway_container *con, void *data) { 10static void remove_mark(struct sway_container *con) {
12 container_clear_marks(con); 11 container_clear_marks(con);
13 container_update_marks_textures(con); 12 container_update_marks(con);
13}
14
15static void remove_all_marks_iterator(struct sway_container *con, void *data) {
16 remove_mark(con);
14} 17}
15 18
16// unmark Remove all marks from all views 19// unmark Remove all marks from all views
@@ -38,8 +41,7 @@ struct cmd_results *cmd_unmark(int argc, char **argv) {
38 } 41 }
39 } else if (con && !mark) { 42 } else if (con && !mark) {
40 // Clear all marks from the given container 43 // Clear all marks from the given container
41 container_clear_marks(con); 44 remove_mark(con);
42 container_update_marks_textures(con);
43 } else if (!con && mark) { 45 } else if (!con && mark) {
44 // Remove mark from whichever container has it 46 // Remove mark from whichever container has it
45 container_find_and_unmark(mark); 47 container_find_and_unmark(mark);
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index a6a0beda..37a201b4 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <limits.h> 2#include <limits.h>
4#include <string.h> 3#include <string.h>
@@ -61,7 +60,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
61 const char expected[] = "Expected 'workspace <name> gaps " 60 const char expected[] = "Expected 'workspace <name> gaps "
62 "inner|outer|horizontal|vertical|top|right|bottom|left <px>'"; 61 "inner|outer|horizontal|vertical|top|right|bottom|left <px>'";
63 if (gaps_location == 0) { 62 if (gaps_location == 0) {
64 return cmd_results_new(CMD_INVALID, expected); 63 return cmd_results_new(CMD_INVALID, "%s", expected);
65 } 64 }
66 struct cmd_results *error = NULL; 65 struct cmd_results *error = NULL;
67 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO, 66 if ((error = checkarg(argc, "workspace", EXPECTED_EQUAL_TO,
@@ -79,7 +78,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
79 char *end; 78 char *end;
80 int amount = strtol(argv[gaps_location + 2], &end, 10); 79 int amount = strtol(argv[gaps_location + 2], &end, 10);
81 if (strlen(end)) { 80 if (strlen(end)) {
82 return cmd_results_new(CMD_FAILURE, expected); 81 return cmd_results_new(CMD_FAILURE, "%s", expected);
83 } 82 }
84 83
85 bool valid = false; 84 bool valid = false;
@@ -110,7 +109,7 @@ static struct cmd_results *cmd_workspace_gaps(int argc, char **argv,
110 } 109 }
111 } 110 }
112 if (!valid) { 111 if (!valid) {
113 return cmd_results_new(CMD_INVALID, expected); 112 return cmd_results_new(CMD_INVALID, "%s", expected);
114 } 113 }
115 114
116 // Prevent invalid gaps configurations. 115 // Prevent invalid gaps configurations.
@@ -158,6 +157,10 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
158 return cmd_results_new(CMD_FAILURE, 157 return cmd_results_new(CMD_FAILURE,
159 "Unable to allocate workspace output"); 158 "Unable to allocate workspace output");
160 } 159 }
160 if (output_location + 1 < argc) {
161 list_free_items_and_destroy(wsc->outputs);
162 wsc->outputs = create_list();
163 }
161 for (int i = output_location + 1; i < argc; ++i) { 164 for (int i = output_location + 1; i < argc; ++i) {
162 list_add(wsc->outputs, strdup(argv[i])); 165 list_add(wsc->outputs, strdup(argv[i]));
163 } 166 }
@@ -174,7 +177,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
174 } 177 }
175 178
176 if (root->fullscreen_global) { 179 if (root->fullscreen_global) {
177 return cmd_results_new(CMD_FAILURE, "workspace", 180 return cmd_results_new(CMD_FAILURE,
178 "Can't switch workspaces while fullscreen global"); 181 "Can't switch workspaces while fullscreen global");
179 } 182 }
180 183
diff --git a/sway/commands/xwayland.c b/sway/commands/xwayland.c
index 6ca26923..c0b175fc 100644
--- a/sway/commands/xwayland.c
+++ b/sway/commands/xwayland.c
@@ -10,7 +10,7 @@ struct cmd_results *cmd_xwayland(int argc, char **argv) {
10 return error; 10 return error;
11 } 11 }
12 12
13#ifdef HAVE_XWAYLAND 13#ifdef WLR_HAS_XWAYLAND
14 enum xwayland_mode xwayland; 14 enum xwayland_mode xwayland;
15 if (strcmp(argv[0], "force") == 0) { 15 if (strcmp(argv[0], "force") == 0) {
16 xwayland = XWAYLAND_MODE_IMMEDIATE; 16 xwayland = XWAYLAND_MODE_IMMEDIATE;
@@ -20,6 +20,8 @@ struct cmd_results *cmd_xwayland(int argc, char **argv) {
20 xwayland = XWAYLAND_MODE_DISABLED; 20 xwayland = XWAYLAND_MODE_DISABLED;
21 } 21 }
22 22
23 // config->xwayland is reset to the previous value on reload in
24 // load_main_config()
23 if (config->reloading && config->xwayland != xwayland) { 25 if (config->reloading && config->xwayland != xwayland) {
24 return cmd_results_new(CMD_FAILURE, 26 return cmd_results_new(CMD_FAILURE,
25 "xwayland can only be enabled/disabled at launch"); 27 "xwayland can only be enabled/disabled at launch");