aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-07-23 20:27:56 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-07-23 20:31:11 -0400
commitf4b882475eee7a81c206c7825616cc4656b2f60b (patch)
tree38e6ebf81b235424f105dcbcbb194e5e9eac70c0 /sway/commands
parentImplement pid->workspace tracking (diff)
parentMerge pull request #2342 from RyanDwyer/update-cursor (diff)
downloadsway-f4b882475eee7a81c206c7825616cc4656b2f60b.tar.gz
sway-f4b882475eee7a81c206c7825616cc4656b2f60b.tar.zst
sway-f4b882475eee7a81c206c7825616cc4656b2f60b.zip
Merge branch 'master' into pid-workspaces
Diffstat (limited to 'sway/commands')
-rw-r--r--sway/commands/assign.c3
-rw-r--r--sway/commands/bar.c6
-rw-r--r--sway/commands/bar/binding_mode_indicator.c4
-rw-r--r--sway/commands/bar/font.c4
-rw-r--r--sway/commands/bar/height.c2
-rw-r--r--sway/commands/bar/hidden_state.c2
-rw-r--r--sway/commands/bar/id.c2
-rw-r--r--sway/commands/bar/mode.c2
-rw-r--r--sway/commands/bar/modifier.c7
-rw-r--r--sway/commands/bar/output.c2
-rw-r--r--sway/commands/bar/pango_markup.c4
-rw-r--r--sway/commands/bar/position.c3
-rw-r--r--sway/commands/bar/separator_symbol.c2
-rw-r--r--sway/commands/bar/status_command.c2
-rw-r--r--sway/commands/bar/strip_workspace_numbers.c4
-rw-r--r--sway/commands/bar/swaybar_command.c2
-rw-r--r--sway/commands/bar/workspace_buttons.c4
-rw-r--r--sway/commands/bar/wrap_scroll.c4
-rw-r--r--sway/commands/bind.c4
-rw-r--r--sway/commands/border.c2
-rw-r--r--sway/commands/default_floating_border.c29
-rw-r--r--sway/commands/exec.c2
-rw-r--r--sway/commands/exec_always.c35
-rw-r--r--sway/commands/floating.c2
-rw-r--r--sway/commands/floating_minmax_size.c53
-rw-r--r--sway/commands/floating_modifier.c20
-rw-r--r--sway/commands/focus.c71
-rw-r--r--sway/commands/for_window.c2
-rw-r--r--sway/commands/force_display_urgency_hint.c23
-rw-r--r--sway/commands/fullscreen.c2
-rw-r--r--sway/commands/gaps.c8
-rw-r--r--sway/commands/input.c4
-rw-r--r--sway/commands/input/accel_profile.c1
-rw-r--r--sway/commands/input/click_method.c1
-rw-r--r--sway/commands/input/drag_lock.c1
-rw-r--r--sway/commands/input/dwt.c1
-rw-r--r--sway/commands/input/events.c3
-rw-r--r--sway/commands/input/left_handed.c1
-rw-r--r--sway/commands/input/map_from_region.c8
-rw-r--r--sway/commands/input/middle_emulation.c1
-rw-r--r--sway/commands/input/natural_scroll.c1
-rw-r--r--sway/commands/input/pointer_accel.c1
-rw-r--r--sway/commands/input/repeat_delay.c1
-rw-r--r--sway/commands/input/repeat_rate.c1
-rw-r--r--sway/commands/input/scroll_button.c44
-rw-r--r--sway/commands/input/scroll_method.c1
-rw-r--r--sway/commands/input/tap.c3
-rw-r--r--sway/commands/input/tap_button_map.c33
-rw-r--r--sway/commands/input/xkb_layout.c2
-rw-r--r--sway/commands/input/xkb_model.c2
-rw-r--r--sway/commands/input/xkb_options.c2
-rw-r--r--sway/commands/input/xkb_rules.c2
-rw-r--r--sway/commands/input/xkb_variant.c2
-rw-r--r--sway/commands/layout.c2
-rw-r--r--sway/commands/mode.c19
-rw-r--r--sway/commands/move.c166
-rw-r--r--sway/commands/no_focus.c26
-rw-r--r--sway/commands/output.c54
-rw-r--r--sway/commands/output/background.c11
-rw-r--r--sway/commands/output/mode.c2
-rw-r--r--sway/commands/output/position.c2
-rw-r--r--sway/commands/reload.c4
-rw-r--r--sway/commands/rename.c2
-rw-r--r--sway/commands/resize.c410
-rw-r--r--sway/commands/scratchpad.c36
-rw-r--r--sway/commands/set.c2
-rw-r--r--sway/commands/smart_gaps.c2
-rw-r--r--sway/commands/split.c2
-rw-r--r--sway/commands/swap.c9
-rw-r--r--sway/commands/swaybg_command.c2
-rw-r--r--sway/commands/urgent.c36
-rw-r--r--sway/commands/workspace.c2
72 files changed, 982 insertions, 235 deletions
diff --git a/sway/commands/assign.c b/sway/commands/assign.c
index 9d15e166..0bc0929a 100644
--- a/sway/commands/assign.c
+++ b/sway/commands/assign.c
@@ -27,6 +27,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
27 27
28 if (strncmp(*argv, "→", strlen("→")) == 0) { 28 if (strncmp(*argv, "→", strlen("→")) == 0) {
29 if (argc < 3) { 29 if (argc < 3) {
30 free(criteria);
30 return cmd_results_new(CMD_INVALID, "assign", "Missing workspace"); 31 return cmd_results_new(CMD_INVALID, "assign", "Missing workspace");
31 } 32 }
32 ++argv; 33 ++argv;
@@ -44,7 +45,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
44 criteria->target = join_args(argv, target_len); 45 criteria->target = join_args(argv, target_len);
45 46
46 list_add(config->criteria, criteria); 47 list_add(config->criteria, criteria);
47 wlr_log(L_DEBUG, "assign: '%s' -> '%s' added", criteria->raw, 48 wlr_log(WLR_DEBUG, "assign: '%s' -> '%s' added", criteria->raw,
48 criteria->target); 49 criteria->target);
49 50
50 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 51 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/bar.c b/sway/commands/bar.c
index d84ce808..f6a70c17 100644
--- a/sway/commands/bar.c
+++ b/sway/commands/bar.c
@@ -63,13 +63,13 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
63 for (int i = 0; i < config->bars->length; ++i) { 63 for (int i = 0; i < config->bars->length; ++i) {
64 struct bar_config *item = config->bars->items[i]; 64 struct bar_config *item = config->bars->items[i];
65 if (strcmp(item->id, argv[0]) == 0) { 65 if (strcmp(item->id, argv[0]) == 0) {
66 wlr_log(L_DEBUG, "Selecting bar: %s", argv[0]); 66 wlr_log(WLR_DEBUG, "Selecting bar: %s", argv[0]);
67 bar = item; 67 bar = item;
68 break; 68 break;
69 } 69 }
70 } 70 }
71 if (!bar) { 71 if (!bar) {
72 wlr_log(L_DEBUG, "Creating bar: %s", argv[0]); 72 wlr_log(WLR_DEBUG, "Creating bar: %s", argv[0]);
73 bar = default_bar_config(); 73 bar = default_bar_config();
74 if (!bar) { 74 if (!bar) {
75 return cmd_results_new(CMD_FAILURE, "bar", 75 return cmd_results_new(CMD_FAILURE, "bar",
@@ -108,7 +108,7 @@ struct cmd_results *cmd_bar(int argc, char **argv) {
108 108
109 // Set current bar 109 // Set current bar
110 config->current_bar = bar; 110 config->current_bar = bar;
111 wlr_log(L_DEBUG, "Creating bar %s", bar->id); 111 wlr_log(WLR_DEBUG, "Creating bar %s", bar->id);
112 } 112 }
113 113
114 return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers)); 114 return config_subcommand(argv, argc, bar_handlers, sizeof(bar_handlers));
diff --git a/sway/commands/bar/binding_mode_indicator.c b/sway/commands/bar/binding_mode_indicator.c
index 3ba5f33f..0c48bee9 100644
--- a/sway/commands/bar/binding_mode_indicator.c
+++ b/sway/commands/bar/binding_mode_indicator.c
@@ -15,11 +15,11 @@ struct cmd_results *bar_cmd_binding_mode_indicator(int argc, char **argv) {
15 } 15 }
16 if (strcasecmp("yes", argv[0]) == 0) { 16 if (strcasecmp("yes", argv[0]) == 0) {
17 config->current_bar->binding_mode_indicator = true; 17 config->current_bar->binding_mode_indicator = true;
18 wlr_log(L_DEBUG, "Enabling binding mode indicator on bar: %s", 18 wlr_log(WLR_DEBUG, "Enabling binding mode indicator on bar: %s",
19 config->current_bar->id); 19 config->current_bar->id);
20 } else if (strcasecmp("no", argv[0]) == 0) { 20 } else if (strcasecmp("no", argv[0]) == 0) {
21 config->current_bar->binding_mode_indicator = false; 21 config->current_bar->binding_mode_indicator = false;
22 wlr_log(L_DEBUG, "Disabling binding mode indicator on bar: %s", 22 wlr_log(WLR_DEBUG, "Disabling binding mode indicator on bar: %s",
23 config->current_bar->id); 23 config->current_bar->id);
24 } 24 }
25 return cmd_results_new(CMD_INVALID, "binding_mode_indicator", 25 return cmd_results_new(CMD_INVALID, "binding_mode_indicator",
diff --git a/sway/commands/bar/font.c b/sway/commands/bar/font.c
index 80b7a593..2aa4e895 100644
--- a/sway/commands/bar/font.c
+++ b/sway/commands/bar/font.c
@@ -14,8 +14,8 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) {
14 } 14 }
15 char *font = join_args(argv, argc); 15 char *font = join_args(argv, argc);
16 free(config->current_bar->font); 16 free(config->current_bar->font);
17 config->current_bar->font = strdup(font); 17 config->current_bar->font = font;
18 wlr_log(L_DEBUG, "Settings font '%s' for bar: %s", 18 wlr_log(WLR_DEBUG, "Settings font '%s' for bar: %s",
19 config->current_bar->font, config->current_bar->id); 19 config->current_bar->font, config->current_bar->id);
20 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 20 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
21} 21}
diff --git a/sway/commands/bar/height.c b/sway/commands/bar/height.c
index 3160caed..18258526 100644
--- a/sway/commands/bar/height.c
+++ b/sway/commands/bar/height.c
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_height(int argc, char **argv) {
14 "Invalid height value: %s", argv[0]); 14 "Invalid height value: %s", argv[0]);
15 } 15 }
16 config->current_bar->height = height; 16 config->current_bar->height = height;
17 wlr_log(L_DEBUG, "Setting bar height to %d on bar: %s", 17 wlr_log(WLR_DEBUG, "Setting bar height to %d on bar: %s",
18 height, config->current_bar->id); 18 height, config->current_bar->id);
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
20} 20}
diff --git a/sway/commands/bar/hidden_state.c b/sway/commands/bar/hidden_state.c
index 6641f184..502ce2c4 100644
--- a/sway/commands/bar/hidden_state.c
+++ b/sway/commands/bar/hidden_state.c
@@ -27,7 +27,7 @@ static struct cmd_results *bar_set_hidden_state(struct bar_config *bar,
27 if (!config->reading) { 27 if (!config->reading) {
28 ipc_event_barconfig_update(bar); 28 ipc_event_barconfig_update(bar);
29 } 29 }
30 wlr_log(L_DEBUG, "Setting hidden_state: '%s' for bar: %s", 30 wlr_log(WLR_DEBUG, "Setting hidden_state: '%s' for bar: %s",
31 bar->hidden_state, bar->id); 31 bar->hidden_state, bar->id);
32 } 32 }
33 // free old mode 33 // free old mode
diff --git a/sway/commands/bar/id.c b/sway/commands/bar/id.c
index 6ce86fef..65fa69fd 100644
--- a/sway/commands/bar/id.c
+++ b/sway/commands/bar/id.c
@@ -24,7 +24,7 @@ struct cmd_results *bar_cmd_id(int argc, char **argv) {
24 } 24 }
25 } 25 }
26 26
27 wlr_log(L_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name); 27 wlr_log(WLR_DEBUG, "Renaming bar: '%s' to '%s'", oldname, name);
28 28
29 // free old bar id 29 // free old bar id
30 free(config->current_bar->id); 30 free(config->current_bar->id);
diff --git a/sway/commands/bar/mode.c b/sway/commands/bar/mode.c
index 34bb0a4f..28e2d77b 100644
--- a/sway/commands/bar/mode.c
+++ b/sway/commands/bar/mode.c
@@ -28,7 +28,7 @@ static struct cmd_results *bar_set_mode(struct bar_config *bar, const char *mode
28 if (!config->reading) { 28 if (!config->reading) {
29 ipc_event_barconfig_update(bar); 29 ipc_event_barconfig_update(bar);
30 } 30 }
31 wlr_log(L_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id); 31 wlr_log(WLR_DEBUG, "Setting mode: '%s' for bar: %s", bar->mode, bar->id);
32 } 32 }
33 33
34 // free old mode 34 // free old mode
diff --git a/sway/commands/bar/modifier.c b/sway/commands/bar/modifier.c
index 7ba4b125..09025fff 100644
--- a/sway/commands/bar/modifier.c
+++ b/sway/commands/bar/modifier.c
@@ -22,14 +22,15 @@ struct cmd_results *bar_cmd_modifier(int argc, char **argv) {
22 mod |= tmp_mod; 22 mod |= tmp_mod;
23 continue; 23 continue;
24 } else { 24 } else {
25 error = cmd_results_new(CMD_INVALID, "modifier",
26 "Unknown modifier '%s'", split->items[i]);
25 free_flat_list(split); 27 free_flat_list(split);
26 return cmd_results_new(CMD_INVALID, "modifier", 28 return error;
27 "Unknown modifier '%s'", split->items[i]);
28 } 29 }
29 } 30 }
30 free_flat_list(split); 31 free_flat_list(split);
31 config->current_bar->modifier = mod; 32 config->current_bar->modifier = mod;
32 wlr_log(L_DEBUG, 33 wlr_log(WLR_DEBUG,
33 "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]); 34 "Show/Hide the bar when pressing '%s' in hide mode.", argv[0]);
34 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 35 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
35} 36}
diff --git a/sway/commands/bar/output.c b/sway/commands/bar/output.c
index f7ca0aa4..72754e05 100644
--- a/sway/commands/bar/output.c
+++ b/sway/commands/bar/output.c
@@ -42,7 +42,7 @@ struct cmd_results *bar_cmd_output(int argc, char **argv) {
42 42
43 if (add_output) { 43 if (add_output) {
44 list_add(outputs, strdup(output)); 44 list_add(outputs, strdup(output));
45 wlr_log(L_DEBUG, "Adding bar: '%s' to output '%s'", 45 wlr_log(WLR_DEBUG, "Adding bar: '%s' to output '%s'",
46 config->current_bar->id, output); 46 config->current_bar->id, output);
47 } 47 }
48 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 48 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/bar/pango_markup.c b/sway/commands/bar/pango_markup.c
index 480af724..857571fb 100644
--- a/sway/commands/bar/pango_markup.c
+++ b/sway/commands/bar/pango_markup.c
@@ -13,11 +13,11 @@ struct cmd_results *bar_cmd_pango_markup(int argc, char **argv) {
13 } 13 }
14 if (strcasecmp("enabled", argv[0]) == 0) { 14 if (strcasecmp("enabled", argv[0]) == 0) {
15 config->current_bar->pango_markup = true; 15 config->current_bar->pango_markup = true;
16 wlr_log(L_DEBUG, "Enabling pango markup for bar: %s", 16 wlr_log(WLR_DEBUG, "Enabling pango markup for bar: %s",
17 config->current_bar->id); 17 config->current_bar->id);
18 } else if (strcasecmp("disabled", argv[0]) == 0) { 18 } else if (strcasecmp("disabled", argv[0]) == 0) {
19 config->current_bar->pango_markup = false; 19 config->current_bar->pango_markup = false;
20 wlr_log(L_DEBUG, "Disabling pango markup for bar: %s", 20 wlr_log(WLR_DEBUG, "Disabling pango markup for bar: %s",
21 config->current_bar->id); 21 config->current_bar->id);
22 } else { 22 } else {
23 error = cmd_results_new(CMD_INVALID, "pango_markup", 23 error = cmd_results_new(CMD_INVALID, "pango_markup",
diff --git a/sway/commands/bar/position.c b/sway/commands/bar/position.c
index 9c580483..44bb4ae3 100644
--- a/sway/commands/bar/position.c
+++ b/sway/commands/bar/position.c
@@ -15,8 +15,9 @@ struct cmd_results *bar_cmd_position(int argc, char **argv) {
15 char *valid[] = { "top", "bottom", "left", "right" }; 15 char *valid[] = { "top", "bottom", "left", "right" };
16 for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) { 16 for (size_t i = 0; i < sizeof(valid) / sizeof(valid[0]); ++i) {
17 if (strcasecmp(valid[i], argv[0]) == 0) { 17 if (strcasecmp(valid[i], argv[0]) == 0) {
18 wlr_log(L_DEBUG, "Setting bar position '%s' for bar: %s", 18 wlr_log(WLR_DEBUG, "Setting bar position '%s' for bar: %s",
19 argv[0], config->current_bar->id); 19 argv[0], config->current_bar->id);
20 free(config->current_bar->position);
20 config->current_bar->position = strdup(argv[0]); 21 config->current_bar->position = strdup(argv[0]);
21 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 22 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
22 } 23 }
diff --git a/sway/commands/bar/separator_symbol.c b/sway/commands/bar/separator_symbol.c
index 1e08df6d..392ab730 100644
--- a/sway/commands/bar/separator_symbol.c
+++ b/sway/commands/bar/separator_symbol.c
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_separator_symbol(int argc, char **argv) {
14 } 14 }
15 free(config->current_bar->separator_symbol); 15 free(config->current_bar->separator_symbol);
16 config->current_bar->separator_symbol = strdup(argv[0]); 16 config->current_bar->separator_symbol = strdup(argv[0]);
17 wlr_log(L_DEBUG, "Settings separator_symbol '%s' for bar: %s", 17 wlr_log(WLR_DEBUG, "Settings separator_symbol '%s' for bar: %s",
18 config->current_bar->separator_symbol, config->current_bar->id); 18 config->current_bar->separator_symbol, config->current_bar->id);
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
20} 20}
diff --git a/sway/commands/bar/status_command.c b/sway/commands/bar/status_command.c
index 5e199cde..6f6f81a3 100644
--- a/sway/commands/bar/status_command.c
+++ b/sway/commands/bar/status_command.c
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_status_command(int argc, char **argv) {
14 } 14 }
15 free(config->current_bar->status_command); 15 free(config->current_bar->status_command);
16 config->current_bar->status_command = join_args(argv, argc); 16 config->current_bar->status_command = join_args(argv, argc);
17 wlr_log(L_DEBUG, "Feeding bar with status command: %s", 17 wlr_log(WLR_DEBUG, "Feeding bar with status command: %s",
18 config->current_bar->status_command); 18 config->current_bar->status_command);
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
20} 20}
diff --git a/sway/commands/bar/strip_workspace_numbers.c b/sway/commands/bar/strip_workspace_numbers.c
index 4f24a356..4e47d047 100644
--- a/sway/commands/bar/strip_workspace_numbers.c
+++ b/sway/commands/bar/strip_workspace_numbers.c
@@ -15,11 +15,11 @@ struct cmd_results *bar_cmd_strip_workspace_numbers(int argc, char **argv) {
15 } 15 }
16 if (strcasecmp("yes", argv[0]) == 0) { 16 if (strcasecmp("yes", argv[0]) == 0) {
17 config->current_bar->strip_workspace_numbers = true; 17 config->current_bar->strip_workspace_numbers = true;
18 wlr_log(L_DEBUG, "Stripping workspace numbers on bar: %s", 18 wlr_log(WLR_DEBUG, "Stripping workspace numbers on bar: %s",
19 config->current_bar->id); 19 config->current_bar->id);
20 } else if (strcasecmp("no", argv[0]) == 0) { 20 } else if (strcasecmp("no", argv[0]) == 0) {
21 config->current_bar->strip_workspace_numbers = false; 21 config->current_bar->strip_workspace_numbers = false;
22 wlr_log(L_DEBUG, "Enabling workspace numbers on bar: %s", 22 wlr_log(WLR_DEBUG, "Enabling workspace numbers on bar: %s",
23 config->current_bar->id); 23 config->current_bar->id);
24 } else { 24 } else {
25 return cmd_results_new(CMD_INVALID, 25 return cmd_results_new(CMD_INVALID,
diff --git a/sway/commands/bar/swaybar_command.c b/sway/commands/bar/swaybar_command.c
index 520cdd11..04e78e77 100644
--- a/sway/commands/bar/swaybar_command.c
+++ b/sway/commands/bar/swaybar_command.c
@@ -14,7 +14,7 @@ struct cmd_results *bar_cmd_swaybar_command(int argc, char **argv) {
14 } 14 }
15 free(config->current_bar->swaybar_command); 15 free(config->current_bar->swaybar_command);
16 config->current_bar->swaybar_command = join_args(argv, argc); 16 config->current_bar->swaybar_command = join_args(argv, argc);
17 wlr_log(L_DEBUG, "Using custom swaybar command: %s", 17 wlr_log(WLR_DEBUG, "Using custom swaybar command: %s",
18 config->current_bar->swaybar_command); 18 config->current_bar->swaybar_command);
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
20} 20}
diff --git a/sway/commands/bar/workspace_buttons.c b/sway/commands/bar/workspace_buttons.c
index 6edc3a0d..a4079b2a 100644
--- a/sway/commands/bar/workspace_buttons.c
+++ b/sway/commands/bar/workspace_buttons.c
@@ -14,11 +14,11 @@ struct cmd_results *bar_cmd_workspace_buttons(int argc, char **argv) {
14 } 14 }
15 if (strcasecmp("yes", argv[0]) == 0) { 15 if (strcasecmp("yes", argv[0]) == 0) {
16 config->current_bar->workspace_buttons = true; 16 config->current_bar->workspace_buttons = true;
17 wlr_log(L_DEBUG, "Enabling workspace buttons on bar: %s", 17 wlr_log(WLR_DEBUG, "Enabling workspace buttons on bar: %s",
18 config->current_bar->id); 18 config->current_bar->id);
19 } else if (strcasecmp("no", argv[0]) == 0) { 19 } else if (strcasecmp("no", argv[0]) == 0) {
20 config->current_bar->workspace_buttons = false; 20 config->current_bar->workspace_buttons = false;
21 wlr_log(L_DEBUG, "Disabling workspace buttons on bar: %s", 21 wlr_log(WLR_DEBUG, "Disabling workspace buttons on bar: %s",
22 config->current_bar->id); 22 config->current_bar->id);
23 } else { 23 } else {
24 return cmd_results_new(CMD_INVALID, "workspace_buttons", 24 return cmd_results_new(CMD_INVALID, "workspace_buttons",
diff --git a/sway/commands/bar/wrap_scroll.c b/sway/commands/bar/wrap_scroll.c
index 7386f82c..701de00a 100644
--- a/sway/commands/bar/wrap_scroll.c
+++ b/sway/commands/bar/wrap_scroll.c
@@ -13,11 +13,11 @@ struct cmd_results *bar_cmd_wrap_scroll(int argc, char **argv) {
13 } 13 }
14 if (strcasecmp("yes", argv[0]) == 0) { 14 if (strcasecmp("yes", argv[0]) == 0) {
15 config->current_bar->wrap_scroll = true; 15 config->current_bar->wrap_scroll = true;
16 wlr_log(L_DEBUG, "Enabling wrap scroll on bar: %s", 16 wlr_log(WLR_DEBUG, "Enabling wrap scroll on bar: %s",
17 config->current_bar->id); 17 config->current_bar->id);
18 } else if (strcasecmp("no", argv[0]) == 0) { 18 } else if (strcasecmp("no", argv[0]) == 0) {
19 config->current_bar->wrap_scroll = false; 19 config->current_bar->wrap_scroll = false;
20 wlr_log(L_DEBUG, "Disabling wrap scroll on bar: %s", 20 wlr_log(WLR_DEBUG, "Disabling wrap scroll on bar: %s",
21 config->current_bar->id); 21 config->current_bar->id);
22 } else { 22 } else {
23 return cmd_results_new(CMD_INVALID, 23 return cmd_results_new(CMD_INVALID,
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 821f9cd1..83e9e432 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -184,7 +184,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
184 for (int i = 0; i < mode_bindings->length; ++i) { 184 for (int i = 0; i < mode_bindings->length; ++i) {
185 struct sway_binding *config_binding = mode_bindings->items[i]; 185 struct sway_binding *config_binding = mode_bindings->items[i];
186 if (binding_key_compare(binding, config_binding)) { 186 if (binding_key_compare(binding, config_binding)) {
187 wlr_log(L_DEBUG, "overwriting old binding with command '%s'", 187 wlr_log(WLR_DEBUG, "overwriting old binding with command '%s'",
188 config_binding->command); 188 config_binding->command);
189 free_sway_binding(config_binding); 189 free_sway_binding(config_binding);
190 mode_bindings->items[i] = binding; 190 mode_bindings->items[i] = binding;
@@ -196,7 +196,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
196 list_add(mode_bindings, binding); 196 list_add(mode_bindings, binding);
197 } 197 }
198 198
199 wlr_log(L_DEBUG, "%s - Bound %s to command %s", 199 wlr_log(WLR_DEBUG, "%s - Bound %s to command %s",
200 bindtype, argv[0], binding->command); 200 bindtype, argv[0], binding->command);
201 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 201 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
202 202
diff --git a/sway/commands/border.c b/sway/commands/border.c
index 6db85395..9c19e20a 100644
--- a/sway/commands/border.c
+++ b/sway/commands/border.c
@@ -42,7 +42,7 @@ struct cmd_results *cmd_border(int argc, char **argv) {
42 container_set_geometry_from_floating_view(view->swayc); 42 container_set_geometry_from_floating_view(view->swayc);
43 } 43 }
44 44
45 arrange_and_commit(view->swayc); 45 arrange_windows(view->swayc);
46 46
47 struct sway_seat *seat = input_manager_current_seat(input_manager); 47 struct sway_seat *seat = input_manager_current_seat(input_manager);
48 if (seat->cursor) { 48 if (seat->cursor) {
diff --git a/sway/commands/default_floating_border.c b/sway/commands/default_floating_border.c
new file mode 100644
index 00000000..1bfc24af
--- /dev/null
+++ b/sway/commands/default_floating_border.c
@@ -0,0 +1,29 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/container.h"
5
6struct cmd_results *cmd_default_floating_border(int argc, char **argv) {
7 struct cmd_results *error = NULL;
8 if ((error = checkarg(argc, "default_floating_border",
9 EXPECTED_AT_LEAST, 1))) {
10 return error;
11 }
12
13 if (strcmp(argv[0], "none") == 0) {
14 config->floating_border = B_NONE;
15 } else if (strcmp(argv[0], "normal") == 0) {
16 config->floating_border = B_NORMAL;
17 } else if (strcmp(argv[0], "pixel") == 0) {
18 config->floating_border = B_PIXEL;
19 } else {
20 return cmd_results_new(CMD_INVALID, "default_floating_border",
21 "Expected 'default_floating_border <none|normal|pixel>' "
22 "or 'default_floating_border <normal|pixel> <px>'");
23 }
24 if (argc == 2) {
25 config->floating_border_thickness = atoi(argv[1]);
26 }
27
28 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
29}
diff --git a/sway/commands/exec.c b/sway/commands/exec.c
index 363d5bef..7fc54123 100644
--- a/sway/commands/exec.c
+++ b/sway/commands/exec.c
@@ -8,7 +8,7 @@ struct cmd_results *cmd_exec(int argc, char **argv) {
8 if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); 8 if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL);
9 if (config->reloading) { 9 if (config->reloading) {
10 char *args = join_args(argv, argc); 10 char *args = join_args(argv, argc);
11 wlr_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); 11 wlr_log(WLR_DEBUG, "Ignoring 'exec %s' due to reload", args);
12 free(args); 12 free(args);
13 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 13 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
14 } 14 }
diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c
index abd52e59..9bf2b320 100644
--- a/sway/commands/exec_always.c
+++ b/sway/commands/exec_always.c
@@ -20,7 +20,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) {
20 20
21 char *tmp = NULL; 21 char *tmp = NULL;
22 if (strcmp((char*)*argv, "--no-startup-id") == 0) { 22 if (strcmp((char*)*argv, "--no-startup-id") == 0) {
23 wlr_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); 23 wlr_log(WLR_INFO, "exec switch '--no-startup-id' not supported, ignored.");
24 if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { 24 if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) {
25 return error; 25 return error;
26 } 26 }
@@ -35,50 +35,49 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) {
35 strncpy(cmd, tmp, sizeof(cmd) - 1); 35 strncpy(cmd, tmp, sizeof(cmd) - 1);
36 cmd[sizeof(cmd) - 1] = 0; 36 cmd[sizeof(cmd) - 1] = 0;
37 free(tmp); 37 free(tmp);
38 wlr_log(L_DEBUG, "Executing %s", cmd); 38 wlr_log(WLR_DEBUG, "Executing %s", cmd);
39 39
40 int fd[2]; 40 int fd[2];
41 if (pipe(fd) != 0) { 41 if (pipe(fd) != 0) {
42 wlr_log(L_ERROR, "Unable to create pipe for fork"); 42 wlr_log(WLR_ERROR, "Unable to create pipe for fork");
43 } 43 }
44 44
45 pid_t pid; 45 pid_t pid, child;
46 pid_t *child = malloc(sizeof(pid_t)); // malloc'd so that Linux can avoid copying the process space
47 if (!child) {
48 return cmd_results_new(CMD_FAILURE, "exec_always", "Unable to allocate child pid");
49 }
50 // Fork process 46 // Fork process
51 if ((pid = fork()) == 0) { 47 if ((pid = fork()) == 0) {
52 // Fork child process again 48 // Fork child process again
53 setsid(); 49 setsid();
54 if ((*child = fork()) == 0) { 50 close(fd[0]);
51 if ((child = fork()) == 0) {
52 close(fd[1]);
55 execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL); 53 execl("/bin/sh", "/bin/sh", "-c", cmd, (void *)NULL);
56 // Not reached 54 _exit(0);
57 } 55 }
58 close(fd[0]);
59 ssize_t s = 0; 56 ssize_t s = 0;
60 while ((size_t)s < sizeof(pid_t)) { 57 while ((size_t)s < sizeof(pid_t)) {
61 s += write(fd[1], ((uint8_t *)child) + s, sizeof(pid_t) - s); 58 s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
62 } 59 }
63 close(fd[1]); 60 close(fd[1]);
64 _exit(0); // Close child process 61 _exit(0); // Close child process
65 } else if (pid < 0) { 62 } else if (pid < 0) {
66 free(child); 63 close(fd[0]);
64 close(fd[1]);
67 return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed"); 65 return cmd_results_new(CMD_FAILURE, "exec_always", "fork() failed");
68 } 66 }
69 close(fd[1]); // close write 67 close(fd[1]); // close write
70 ssize_t s = 0; 68 ssize_t s = 0;
71 while ((size_t)s < sizeof(pid_t)) { 69 while ((size_t)s < sizeof(pid_t)) {
72 s += read(fd[0], ((uint8_t *)child) + s, sizeof(pid_t) - s); 70 s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
73 } 71 }
74 close(fd[0]); 72 close(fd[0]);
75 // cleanup child process 73 // cleanup child process
76 waitpid(pid, NULL, 0); 74 waitpid(pid, NULL, 0);
77 if (*child > 0) { 75 if (child > 0) {
78 wlr_log(L_DEBUG, "Child process created with pid %d", *child); 76 wlr_log(WLR_DEBUG, "Child process created with pid %d", child);
79 workspace_record_pid(*child); 77 workspace_record_pid(child);
80 } else { 78 } else {
81 free(child); 79 return cmd_results_new(CMD_FAILURE, "exec_always",
80 "Second fork() failed");
82 } 81 }
83 82
84 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 83 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/floating.c b/sway/commands/floating.c
index e6003521..6ab56c3b 100644
--- a/sway/commands/floating.c
+++ b/sway/commands/floating.c
@@ -37,7 +37,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) {
37 container_set_floating(container, wants_floating); 37 container_set_floating(container, wants_floating);
38 38
39 struct sway_container *workspace = container_parent(container, C_WORKSPACE); 39 struct sway_container *workspace = container_parent(container, C_WORKSPACE);
40 arrange_and_commit(workspace); 40 arrange_windows(workspace);
41 41
42 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 42 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
43} 43}
diff --git a/sway/commands/floating_minmax_size.c b/sway/commands/floating_minmax_size.c
new file mode 100644
index 00000000..0af78908
--- /dev/null
+++ b/sway/commands/floating_minmax_size.c
@@ -0,0 +1,53 @@
1#include <errno.h>
2#include <math.h>
3#include <stdbool.h>
4#include <stdlib.h>
5#include <string.h>
6#include <strings.h>
7#include <wlr/util/log.h>
8#include "sway/commands.h"
9#include "log.h"
10
11static const char* min_usage =
12 "Expected 'floating_minimum_size <width> x <height>'";
13
14static const char* max_usage =
15 "Expected 'floating_maximum_size <width> x <height>'";
16
17static struct cmd_results *handle_command(int argc, char **argv, char *cmd_name,
18 const char *usage, int *config_width, int *config_height) {
19 struct cmd_results *error;
20 if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 3))) {
21 return error;
22 }
23
24 char *err;
25 int width = (int)strtol(argv[0], &err, 10);
26 if (*err) {
27 return cmd_results_new(CMD_INVALID, cmd_name, usage);
28 }
29
30 if (strcmp(argv[1], "x") != 0) {
31 return cmd_results_new(CMD_INVALID, cmd_name, usage);
32 }
33
34 int height = (int)strtol(argv[2], &err, 10);
35 if (*err) {
36 return cmd_results_new(CMD_INVALID, cmd_name, usage);
37 }
38
39 *config_width = width;
40 *config_height = height;
41
42 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
43}
44
45struct cmd_results *cmd_floating_minimum_size(int argc, char **argv) {
46 return handle_command(argc, argv, "floating_minimum_size", min_usage,
47 &config->floating_minimum_width, &config->floating_minimum_height);
48}
49
50struct cmd_results *cmd_floating_maximum_size(int argc, char **argv) {
51 return handle_command(argc, argv, "floating_maximum_size", max_usage,
52 &config->floating_maximum_width, &config->floating_maximum_height);
53}
diff --git a/sway/commands/floating_modifier.c b/sway/commands/floating_modifier.c
new file mode 100644
index 00000000..9432c9f1
--- /dev/null
+++ b/sway/commands/floating_modifier.c
@@ -0,0 +1,20 @@
1#include "sway/commands.h"
2#include "sway/config.h"
3#include "util.h"
4
5struct cmd_results *cmd_floating_modifier(int argc, char **argv) {
6 struct cmd_results *error = NULL;
7 if ((error = checkarg(argc, "floating_modifier", EXPECTED_EQUAL_TO, 1))) {
8 return error;
9 }
10
11 uint32_t mod = get_modifier_mask_by_name(argv[0]);
12 if (!mod) {
13 return cmd_results_new(CMD_INVALID, "floating_modifier",
14 "Invalid modifier");
15 }
16
17 config->floating_mod = mod;
18
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
20}
diff --git a/sway/commands/focus.c b/sway/commands/focus.c
index 74d9d535..9cd8bfae 100644
--- a/sway/commands/focus.c
+++ b/sway/commands/focus.c
@@ -1,10 +1,14 @@
1#include <strings.h> 1#include <strings.h>
2#include <wlr/util/log.h> 2#include <wlr/util/log.h>
3#include "log.h" 3#include "log.h"
4#include "sway/commands.h"
4#include "sway/input/input-manager.h" 5#include "sway/input/input-manager.h"
5#include "sway/input/seat.h" 6#include "sway/input/seat.h"
7#include "sway/output.h"
8#include "sway/tree/arrange.h"
6#include "sway/tree/view.h" 9#include "sway/tree/view.h"
7#include "sway/commands.h" 10#include "sway/tree/workspace.h"
11#include "stringop.h"
8 12
9static bool parse_movement_direction(const char *name, 13static bool parse_movement_direction(const char *name,
10 enum movement_direction *out) { 14 enum movement_direction *out) {
@@ -27,7 +31,55 @@ static bool parse_movement_direction(const char *name,
27 return true; 31 return true;
28} 32}
29 33
34static struct cmd_results *focus_mode(struct sway_container *con,
35 struct sway_seat *seat, bool floating) {
36 struct sway_container *ws = con->type == C_WORKSPACE ?
37 con : container_parent(con, C_WORKSPACE);
38 struct sway_container *new_focus = ws;
39 if (floating) {
40 new_focus = ws->sway_workspace->floating;
41 if (new_focus->children->length == 0) {
42 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
43 }
44 }
45 seat_set_focus(seat, seat_get_active_child(seat, new_focus));
46 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
47}
48
49static struct cmd_results *focus_output(struct sway_container *con,
50 struct sway_seat *seat, int argc, char **argv) {
51 if (!argc) {
52 return cmd_results_new(CMD_INVALID, "focus",
53 "Expected 'focus output <direction|name>'");
54 }
55 char *identifier = join_args(argv, argc);
56 struct sway_container *output = output_by_name(identifier);
57
58 if (!output) {
59 enum movement_direction direction;
60 if (!parse_movement_direction(identifier, &direction) ||
61 direction == MOVE_PARENT || direction == MOVE_CHILD) {
62 free(identifier);
63 return cmd_results_new(CMD_INVALID, "focus",
64 "There is no output with that name");
65 }
66 struct sway_container *focus = seat_get_focus(seat);
67 focus = container_parent(focus, C_OUTPUT);
68 output = container_get_in_direction(focus, seat, direction);
69 }
70
71 free(identifier);
72 if (output) {
73 seat_set_focus(seat, seat_get_focus_inactive(seat, output));
74 }
75
76 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
77}
78
30struct cmd_results *cmd_focus(int argc, char **argv) { 79struct cmd_results *cmd_focus(int argc, char **argv) {
80 if (config->reading || !config->active) {
81 return cmd_results_new(CMD_DEFER, NULL, NULL);
82 }
31 struct sway_container *con = config->handler_context.current_container; 83 struct sway_container *con = config->handler_context.current_container;
32 struct sway_seat *seat = config->handler_context.seat; 84 struct sway_seat *seat = config->handler_context.seat;
33 if (con->type < C_WORKSPACE) { 85 if (con->type < C_WORKSPACE) {
@@ -40,11 +92,24 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
40 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 92 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
41 } 93 }
42 94
43 // TODO mode_toggle 95 if (strcmp(argv[0], "floating") == 0) {
96 return focus_mode(con, seat, true);
97 } else if (strcmp(argv[0], "tiling") == 0) {
98 return focus_mode(con, seat, false);
99 } else if (strcmp(argv[0], "mode_toggle") == 0) {
100 return focus_mode(con, seat, !container_is_floating(con));
101 }
102
103 if (strcmp(argv[0], "output") == 0) {
104 argc--; argv++;
105 return focus_output(con, seat, argc, argv);
106 }
107
44 enum movement_direction direction = 0; 108 enum movement_direction direction = 0;
45 if (!parse_movement_direction(argv[0], &direction)) { 109 if (!parse_movement_direction(argv[0], &direction)) {
46 return cmd_results_new(CMD_INVALID, "focus", 110 return cmd_results_new(CMD_INVALID, "focus",
47 "Expected 'focus <direction|parent|child|mode_toggle>' or 'focus output <direction|name>'"); 111 "Expected 'focus <direction|parent|child|mode_toggle|floating|tiling>' "
112 "or 'focus output <direction|name>'");
48 } 113 }
49 114
50 struct sway_container *next_focus = container_get_in_direction( 115 struct sway_container *next_focus = container_get_in_direction(
diff --git a/sway/commands/for_window.c b/sway/commands/for_window.c
index 8c425a1d..ac4d6563 100644
--- a/sway/commands/for_window.c
+++ b/sway/commands/for_window.c
@@ -24,7 +24,7 @@ struct cmd_results *cmd_for_window(int argc, char **argv) {
24 criteria->cmdlist = join_args(argv + 1, argc - 1); 24 criteria->cmdlist = join_args(argv + 1, argc - 1);
25 25
26 list_add(config->criteria, criteria); 26 list_add(config->criteria, criteria);
27 wlr_log(L_DEBUG, "for_window: '%s' -> '%s' added", criteria->raw, criteria->cmdlist); 27 wlr_log(WLR_DEBUG, "for_window: '%s' -> '%s' added", criteria->raw, criteria->cmdlist);
28 28
29 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 29 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
30} 30}
diff --git a/sway/commands/force_display_urgency_hint.c b/sway/commands/force_display_urgency_hint.c
new file mode 100644
index 00000000..5e5e2d55
--- /dev/null
+++ b/sway/commands/force_display_urgency_hint.c
@@ -0,0 +1,23 @@
1#include "sway/commands.h"
2#include "sway/config.h"
3
4struct cmd_results *cmd_force_display_urgency_hint(int argc, char **argv) {
5 struct cmd_results *error = NULL;
6 if ((error = checkarg(argc, "force_display_urgency_hint",
7 EXPECTED_AT_LEAST, 1))) {
8 return error;
9 }
10
11 char *err;
12 int timeout = (int)strtol(argv[0], &err, 10);
13 if (*err) {
14 if (strcmp(err, "ms") != 0) {
15 return cmd_results_new(CMD_INVALID, "force_display_urgency_hint",
16 "Expected 'force_display_urgency_hint <timeout> ms'");
17 }
18 }
19
20 config->urgent_timeout = timeout > 0 ? timeout : 0;
21
22 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
23}
diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c
index 1a4d8b41..0b5beaa2 100644
--- a/sway/commands/fullscreen.c
+++ b/sway/commands/fullscreen.c
@@ -34,7 +34,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) {
34 view_set_fullscreen(view, wants_fullscreen); 34 view_set_fullscreen(view, wants_fullscreen);
35 35
36 struct sway_container *workspace = container_parent(container, C_WORKSPACE); 36 struct sway_container *workspace = container_parent(container, C_WORKSPACE);
37 arrange_and_commit(workspace->parent); 37 arrange_windows(workspace->parent);
38 38
39 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 39 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
40} 40}
diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c
index 801fb179..3906eb70 100644
--- a/sway/commands/gaps.c
+++ b/sway/commands/gaps.c
@@ -43,7 +43,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
43 return cmd_results_new(CMD_INVALID, "gaps", 43 return cmd_results_new(CMD_INVALID, "gaps",
44 "gaps edge_gaps on|off|toggle"); 44 "gaps edge_gaps on|off|toggle");
45 } 45 }
46 arrange_and_commit(&root_container); 46 arrange_windows(&root_container);
47 } else { 47 } else {
48 int amount_idx = 0; // the current index in argv 48 int amount_idx = 0; // the current index in argv
49 enum gaps_op op = GAPS_OP_SET; 49 enum gaps_op op = GAPS_OP_SET;
@@ -124,7 +124,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
124 if (amount_idx == 0) { // gaps <amount> 124 if (amount_idx == 0) { // gaps <amount>
125 config->gaps_inner = val; 125 config->gaps_inner = val;
126 config->gaps_outer = val; 126 config->gaps_outer = val;
127 arrange_and_commit(&root_container); 127 arrange_windows(&root_container);
128 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 128 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
129 } 129 }
130 // Other variants. The middle-length variant (gaps inner|outer <amount>) 130 // Other variants. The middle-length variant (gaps inner|outer <amount>)
@@ -155,7 +155,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
155 } else { 155 } else {
156 config->gaps_outer = total; 156 config->gaps_outer = total;
157 } 157 }
158 arrange_and_commit(&root_container); 158 arrange_windows(&root_container);
159 } else { 159 } else {
160 struct sway_container *c = 160 struct sway_container *c =
161 config->handler_context.current_container; 161 config->handler_context.current_container;
@@ -169,7 +169,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) {
169 c->gaps_outer = total; 169 c->gaps_outer = total;
170 } 170 }
171 171
172 arrange_and_commit(c->parent ? c->parent : &root_container); 172 arrange_windows(c->parent ? c->parent : &root_container);
173 } 173 }
174 } 174 }
175 175
diff --git a/sway/commands/input.c b/sway/commands/input.c
index 678c57c4..5b203ea0 100644
--- a/sway/commands/input.c
+++ b/sway/commands/input.c
@@ -20,8 +20,10 @@ static struct cmd_handler input_handlers[] = {
20 { "pointer_accel", input_cmd_pointer_accel }, 20 { "pointer_accel", input_cmd_pointer_accel },
21 { "repeat_delay", input_cmd_repeat_delay }, 21 { "repeat_delay", input_cmd_repeat_delay },
22 { "repeat_rate", input_cmd_repeat_rate }, 22 { "repeat_rate", input_cmd_repeat_rate },
23 { "scroll_button", input_cmd_scroll_button },
23 { "scroll_method", input_cmd_scroll_method }, 24 { "scroll_method", input_cmd_scroll_method },
24 { "tap", input_cmd_tap }, 25 { "tap", input_cmd_tap },
26 { "tap_button_map", input_cmd_tap_button_map },
25 { "xkb_layout", input_cmd_xkb_layout }, 27 { "xkb_layout", input_cmd_xkb_layout },
26 { "xkb_model", input_cmd_xkb_model }, 28 { "xkb_model", input_cmd_xkb_model },
27 { "xkb_options", input_cmd_xkb_options }, 29 { "xkb_options", input_cmd_xkb_options },
@@ -35,7 +37,7 @@ struct cmd_results *cmd_input(int argc, char **argv) {
35 return error; 37 return error;
36 } 38 }
37 39
38 wlr_log(L_DEBUG, "entering input block: %s", argv[0]); 40 wlr_log(WLR_DEBUG, "entering input block: %s", argv[0]);
39 41
40 config->handler_context.input_config = new_input_config(argv[0]); 42 config->handler_context.input_config = new_input_config(argv[0]);
41 if (!config->handler_context.input_config) { 43 if (!config->handler_context.input_config) {
diff --git a/sway/commands/input/accel_profile.c b/sway/commands/input/accel_profile.c
index 37d6e133..a4108ec3 100644
--- a/sway/commands/input/accel_profile.c
+++ b/sway/commands/input/accel_profile.c
@@ -23,6 +23,7 @@ struct cmd_results *input_cmd_accel_profile(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "flat") == 0) { 23 } else if (strcasecmp(argv[0], "flat") == 0) {
24 new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; 24 new_config->accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
25 } else { 25 } else {
26 free_input_config(new_config);
26 return cmd_results_new(CMD_INVALID, "accel_profile", 27 return cmd_results_new(CMD_INVALID, "accel_profile",
27 "Expected 'accel_profile <adaptive|flat>'"); 28 "Expected 'accel_profile <adaptive|flat>'");
28 } 29 }
diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c
index 8f1f0aa7..5d0d8cc2 100644
--- a/sway/commands/input/click_method.c
+++ b/sway/commands/input/click_method.c
@@ -26,6 +26,7 @@ struct cmd_results *input_cmd_click_method(int argc, char **argv) {
26 } else if (strcasecmp(argv[0], "clickfinger") == 0) { 26 } else if (strcasecmp(argv[0], "clickfinger") == 0) {
27 new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; 27 new_config->click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER;
28 } else { 28 } else {
29 free_input_config(new_config);
29 return cmd_results_new(CMD_INVALID, "click_method", 30 return cmd_results_new(CMD_INVALID, "click_method",
30 "Expected 'click_method <none|button_areas|clickfinger'"); 31 "Expected 'click_method <none|button_areas|clickfinger'");
31 } 32 }
diff --git a/sway/commands/input/drag_lock.c b/sway/commands/input/drag_lock.c
index 8273a7d4..9e32816f 100644
--- a/sway/commands/input/drag_lock.c
+++ b/sway/commands/input/drag_lock.c
@@ -23,6 +23,7 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled") == 0) { 23 } else if (strcasecmp(argv[0], "disabled") == 0) {
24 new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED; 24 new_config->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_DISABLED;
25 } else { 25 } else {
26 free_input_config(new_config);
26 return cmd_results_new(CMD_INVALID, "drag_lock", 27 return cmd_results_new(CMD_INVALID, "drag_lock",
27 "Expected 'drag_lock <enabled|disabled>'"); 28 "Expected 'drag_lock <enabled|disabled>'");
28 } 29 }
diff --git a/sway/commands/input/dwt.c b/sway/commands/input/dwt.c
index 995a2f47..73937507 100644
--- a/sway/commands/input/dwt.c
+++ b/sway/commands/input/dwt.c
@@ -22,6 +22,7 @@ struct cmd_results *input_cmd_dwt(int argc, char **argv) {
22 } else if (strcasecmp(argv[0], "disabled") == 0) { 22 } else if (strcasecmp(argv[0], "disabled") == 0) {
23 new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED; 23 new_config->dwt = LIBINPUT_CONFIG_DWT_DISABLED;
24 } else { 24 } else {
25 free_input_config(new_config);
25 return cmd_results_new(CMD_INVALID, "dwt", 26 return cmd_results_new(CMD_INVALID, "dwt",
26 "Expected 'dwt <enabled|disabled>'"); 27 "Expected 'dwt <enabled|disabled>'");
27 } 28 }
diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c
index 2217f5ce..abfe3b12 100644
--- a/sway/commands/input/events.c
+++ b/sway/commands/input/events.c
@@ -16,7 +16,7 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
16 return cmd_results_new(CMD_FAILURE, "events", 16 return cmd_results_new(CMD_FAILURE, "events",
17 "No input device defined."); 17 "No input device defined.");
18 } 18 }
19 wlr_log(L_DEBUG, "events for device: %s", 19 wlr_log(WLR_DEBUG, "events for device: %s",
20 current_input_config->identifier); 20 current_input_config->identifier);
21 struct input_config *new_config = 21 struct input_config *new_config =
22 new_input_config(current_input_config->identifier); 22 new_input_config(current_input_config->identifier);
@@ -29,6 +29,7 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
29 new_config->send_events = 29 new_config->send_events =
30 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; 30 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE;
31 } else { 31 } else {
32 free_input_config(new_config);
32 return cmd_results_new(CMD_INVALID, "events", 33 return cmd_results_new(CMD_INVALID, "events",
33 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'"); 34 "Expected 'events <enabled|disabled|disabled_on_external_mouse>'");
34 } 35 }
diff --git a/sway/commands/input/left_handed.c b/sway/commands/input/left_handed.c
index 94b8e03e..769ce98c 100644
--- a/sway/commands/input/left_handed.c
+++ b/sway/commands/input/left_handed.c
@@ -23,6 +23,7 @@ struct cmd_results *input_cmd_left_handed(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled") == 0) { 23 } else if (strcasecmp(argv[0], "disabled") == 0) {
24 new_config->left_handed = 0; 24 new_config->left_handed = 0;
25 } else { 25 } else {
26 free_input_config(new_config);
26 return cmd_results_new(CMD_INVALID, "left_handed", 27 return cmd_results_new(CMD_INVALID, "left_handed",
27 "Expected 'left_handed <enabled|disabled>'"); 28 "Expected 'left_handed <enabled|disabled>'");
28 } 29 }
diff --git a/sway/commands/input/map_from_region.c b/sway/commands/input/map_from_region.c
index 80bb856d..40f04214 100644
--- a/sway/commands/input/map_from_region.c
+++ b/sway/commands/input/map_from_region.c
@@ -54,20 +54,28 @@ struct cmd_results *input_cmd_map_from_region(int argc, char **argv) {
54 bool mm1, mm2; 54 bool mm1, mm2;
55 if (!parse_coords(argv[0], &new_config->mapped_from_region->x1, 55 if (!parse_coords(argv[0], &new_config->mapped_from_region->x1,
56 &new_config->mapped_from_region->y1, &mm1)) { 56 &new_config->mapped_from_region->y1, &mm1)) {
57 free(new_config->mapped_from_region);
58 free_input_config(new_config);
57 return cmd_results_new(CMD_FAILURE, "map_from_region", 59 return cmd_results_new(CMD_FAILURE, "map_from_region",
58 "Invalid top-left coordinates"); 60 "Invalid top-left coordinates");
59 } 61 }
60 if (!parse_coords(argv[1], &new_config->mapped_from_region->x2, 62 if (!parse_coords(argv[1], &new_config->mapped_from_region->x2,
61 &new_config->mapped_from_region->y2, &mm2)) { 63 &new_config->mapped_from_region->y2, &mm2)) {
64 free(new_config->mapped_from_region);
65 free_input_config(new_config);
62 return cmd_results_new(CMD_FAILURE, "map_from_region", 66 return cmd_results_new(CMD_FAILURE, "map_from_region",
63 "Invalid bottom-right coordinates"); 67 "Invalid bottom-right coordinates");
64 } 68 }
65 if (new_config->mapped_from_region->x1 > new_config->mapped_from_region->x2 || 69 if (new_config->mapped_from_region->x1 > new_config->mapped_from_region->x2 ||
66 new_config->mapped_from_region->y1 > new_config->mapped_from_region->y2) { 70 new_config->mapped_from_region->y1 > new_config->mapped_from_region->y2) {
71 free(new_config->mapped_from_region);
72 free_input_config(new_config);
67 return cmd_results_new(CMD_FAILURE, "map_from_region", 73 return cmd_results_new(CMD_FAILURE, "map_from_region",
68 "Invalid rectangle"); 74 "Invalid rectangle");
69 } 75 }
70 if (mm1 != mm2) { 76 if (mm1 != mm2) {
77 free(new_config->mapped_from_region);
78 free_input_config(new_config);
71 return cmd_results_new(CMD_FAILURE, "map_from_region", 79 return cmd_results_new(CMD_FAILURE, "map_from_region",
72 "Both coordinates must be in the same unit"); 80 "Both coordinates must be in the same unit");
73 } 81 }
diff --git a/sway/commands/input/middle_emulation.c b/sway/commands/input/middle_emulation.c
index a551fd51..7ca01629 100644
--- a/sway/commands/input/middle_emulation.c
+++ b/sway/commands/input/middle_emulation.c
@@ -24,6 +24,7 @@ struct cmd_results *input_cmd_middle_emulation(int argc, char **argv) {
24 new_config->middle_emulation = 24 new_config->middle_emulation =
25 LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED; 25 LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED;
26 } else { 26 } else {
27 free_input_config(new_config);
27 return cmd_results_new(CMD_INVALID, "middle_emulation", 28 return cmd_results_new(CMD_INVALID, "middle_emulation",
28 "Expected 'middle_emulation <enabled|disabled>'"); 29 "Expected 'middle_emulation <enabled|disabled>'");
29 } 30 }
diff --git a/sway/commands/input/natural_scroll.c b/sway/commands/input/natural_scroll.c
index c4e19b78..55236790 100644
--- a/sway/commands/input/natural_scroll.c
+++ b/sway/commands/input/natural_scroll.c
@@ -23,6 +23,7 @@ struct cmd_results *input_cmd_natural_scroll(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled") == 0) { 23 } else if (strcasecmp(argv[0], "disabled") == 0) {
24 new_config->natural_scroll = 0; 24 new_config->natural_scroll = 0;
25 } else { 25 } else {
26 free_input_config(new_config);
26 return cmd_results_new(CMD_INVALID, "natural_scroll", 27 return cmd_results_new(CMD_INVALID, "natural_scroll",
27 "Expected 'natural_scroll <enabled|disabled>'"); 28 "Expected 'natural_scroll <enabled|disabled>'");
28 } 29 }
diff --git a/sway/commands/input/pointer_accel.c b/sway/commands/input/pointer_accel.c
index 171063aa..8bbd0724 100644
--- a/sway/commands/input/pointer_accel.c
+++ b/sway/commands/input/pointer_accel.c
@@ -20,6 +20,7 @@ struct cmd_results *input_cmd_pointer_accel(int argc, char **argv) {
20 20
21 float pointer_accel = atof(argv[0]); 21 float pointer_accel = atof(argv[0]);
22 if (pointer_accel < -1 || pointer_accel > 1) { 22 if (pointer_accel < -1 || pointer_accel > 1) {
23 free_input_config(new_config);
23 return cmd_results_new(CMD_INVALID, "pointer_accel", 24 return cmd_results_new(CMD_INVALID, "pointer_accel",
24 "Input out of range [-1, 1]"); 25 "Input out of range [-1, 1]");
25 } 26 }
diff --git a/sway/commands/input/repeat_delay.c b/sway/commands/input/repeat_delay.c
index ce265841..c9ddbf0e 100644
--- a/sway/commands/input/repeat_delay.c
+++ b/sway/commands/input/repeat_delay.c
@@ -20,6 +20,7 @@ struct cmd_results *input_cmd_repeat_delay(int argc, char **argv) {
20 20
21 int repeat_delay = atoi(argv[0]); 21 int repeat_delay = atoi(argv[0]);
22 if (repeat_delay < 0) { 22 if (repeat_delay < 0) {
23 free_input_config(new_config);
23 return cmd_results_new(CMD_INVALID, "repeat_delay", 24 return cmd_results_new(CMD_INVALID, "repeat_delay",
24 "Repeat delay cannot be negative"); 25 "Repeat delay cannot be negative");
25 } 26 }
diff --git a/sway/commands/input/repeat_rate.c b/sway/commands/input/repeat_rate.c
index f2ea2e69..56878176 100644
--- a/sway/commands/input/repeat_rate.c
+++ b/sway/commands/input/repeat_rate.c
@@ -20,6 +20,7 @@ struct cmd_results *input_cmd_repeat_rate(int argc, char **argv) {
20 20
21 int repeat_rate = atoi(argv[0]); 21 int repeat_rate = atoi(argv[0]);
22 if (repeat_rate < 0) { 22 if (repeat_rate < 0) {
23 free_input_config(new_config);
23 return cmd_results_new(CMD_INVALID, "repeat_rate", 24 return cmd_results_new(CMD_INVALID, "repeat_rate",
24 "Repeat rate cannot be negative"); 25 "Repeat rate cannot be negative");
25 } 26 }
diff --git a/sway/commands/input/scroll_button.c b/sway/commands/input/scroll_button.c
new file mode 100644
index 00000000..350fcca2
--- /dev/null
+++ b/sway/commands/input/scroll_button.c
@@ -0,0 +1,44 @@
1#include <string.h>
2#include <strings.h>
3#include <errno.h>
4#include "sway/config.h"
5#include "sway/commands.h"
6#include "sway/input/input-manager.h"
7
8struct cmd_results *input_cmd_scroll_button(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "scroll_button", EXPECTED_AT_LEAST, 1))) {
11 return error;
12 }
13 struct input_config *current_input_config =
14 config->handler_context.input_config;
15 if (!current_input_config) {
16 return cmd_results_new(CMD_FAILURE, "scroll_button",
17 "No input device defined.");
18 }
19 struct input_config *new_config =
20 new_input_config(current_input_config->identifier);
21
22 errno = 0;
23 char *endptr;
24 int scroll_button = strtol(*argv, &endptr, 10);
25 if (endptr == *argv && scroll_button == 0) {
26 free_input_config(new_config);
27 return cmd_results_new(CMD_INVALID, "scroll_button",
28 "Scroll button identifier must be an integer.");
29 }
30 if (errno == ERANGE) {
31 free_input_config(new_config);
32 return cmd_results_new(CMD_INVALID, "scroll_button",
33 "Scroll button identifier out of range.");
34 }
35 if (scroll_button < 0) {
36 free_input_config(new_config);
37 return cmd_results_new(CMD_INVALID, "scroll_button",
38 "Scroll button identifier cannot be negative.");
39 }
40 new_config->scroll_button = scroll_button;
41
42 apply_input_config(new_config);
43 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
44}
diff --git a/sway/commands/input/scroll_method.c b/sway/commands/input/scroll_method.c
index 0a1c57ac..4c6ac6b6 100644
--- a/sway/commands/input/scroll_method.c
+++ b/sway/commands/input/scroll_method.c
@@ -27,6 +27,7 @@ struct cmd_results *input_cmd_scroll_method(int argc, char **argv) {
27 } else if (strcasecmp(argv[0], "on_button_down") == 0) { 27 } else if (strcasecmp(argv[0], "on_button_down") == 0) {
28 new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; 28 new_config->scroll_method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
29 } else { 29 } else {
30 free_input_config(new_config);
30 return cmd_results_new(CMD_INVALID, "scroll_method", 31 return cmd_results_new(CMD_INVALID, "scroll_method",
31 "Expected 'scroll_method <none|two_finger|edge|on_button_down>'"); 32 "Expected 'scroll_method <none|two_finger|edge|on_button_down>'");
32 } 33 }
diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c
index e7f03058..a8d1a10c 100644
--- a/sway/commands/input/tap.c
+++ b/sway/commands/input/tap.c
@@ -23,11 +23,12 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) {
23 } else if (strcasecmp(argv[0], "disabled") == 0) { 23 } else if (strcasecmp(argv[0], "disabled") == 0) {
24 new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED; 24 new_config->tap = LIBINPUT_CONFIG_TAP_DISABLED;
25 } else { 25 } else {
26 free_input_config(new_config);
26 return cmd_results_new(CMD_INVALID, "tap", 27 return cmd_results_new(CMD_INVALID, "tap",
27 "Expected 'tap <enabled|disabled>'"); 28 "Expected 'tap <enabled|disabled>'");
28 } 29 }
29 30
30 wlr_log(L_DEBUG, "apply-tap for device: %s", 31 wlr_log(WLR_DEBUG, "apply-tap for device: %s",
31 current_input_config->identifier); 32 current_input_config->identifier);
32 apply_input_config(new_config); 33 apply_input_config(new_config);
33 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 34 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/input/tap_button_map.c b/sway/commands/input/tap_button_map.c
new file mode 100644
index 00000000..bdbba472
--- /dev/null
+++ b/sway/commands/input/tap_button_map.c
@@ -0,0 +1,33 @@
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
7struct cmd_results *input_cmd_tap_button_map(int argc, char **argv) {
8 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "tap_button_map", EXPECTED_AT_LEAST, 1))) {
10 return error;
11 }
12 struct input_config *current_input_config =
13 config->handler_context.input_config;
14 if (!current_input_config) {
15 return cmd_results_new(CMD_FAILURE, "tap_button_map",
16 "No input device defined.");
17 }
18 struct input_config *new_config =
19 new_input_config(current_input_config->identifier);
20
21 if (strcasecmp(argv[0], "lrm") == 0) {
22 new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LRM;
23 } else if (strcasecmp(argv[0], "lmr") == 0) {
24 new_config->tap_button_map = LIBINPUT_CONFIG_TAP_MAP_LMR;
25 } else {
26 free_input_config(new_config);
27 return cmd_results_new(CMD_INVALID, "tap_button_map",
28 "Expected 'tap_button_map <lrm|lmr>'");
29 }
30
31 apply_input_config(new_config);
32 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
33}
diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c
index 867e65d3..9fa5a344 100644
--- a/sway/commands/input/xkb_layout.c
+++ b/sway/commands/input/xkb_layout.c
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) {
19 19
20 new_config->xkb_layout = strdup(argv[0]); 20 new_config->xkb_layout = strdup(argv[0]);
21 21
22 wlr_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", 22 wlr_log(WLR_DEBUG, "apply-xkb_layout for device: %s layout: %s",
23 current_input_config->identifier, new_config->xkb_layout); 23 current_input_config->identifier, new_config->xkb_layout);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c
index e8c8e04e..0d082625 100644
--- a/sway/commands/input/xkb_model.c
+++ b/sway/commands/input/xkb_model.c
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) {
19 19
20 new_config->xkb_model = strdup(argv[0]); 20 new_config->xkb_model = strdup(argv[0]);
21 21
22 wlr_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", 22 wlr_log(WLR_DEBUG, "apply-xkb_model for device: %s model: %s",
23 current_input_config->identifier, new_config->xkb_model); 23 current_input_config->identifier, new_config->xkb_model);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c
index e9ddd6e3..3059d941 100644
--- a/sway/commands/input/xkb_options.c
+++ b/sway/commands/input/xkb_options.c
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) {
19 19
20 new_config->xkb_options = strdup(argv[0]); 20 new_config->xkb_options = strdup(argv[0]);
21 21
22 wlr_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", 22 wlr_log(WLR_DEBUG, "apply-xkb_options for device: %s options: %s",
23 current_input_config->identifier, new_config->xkb_options); 23 current_input_config->identifier, new_config->xkb_options);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c
index 926d0ac1..560f088e 100644
--- a/sway/commands/input/xkb_rules.c
+++ b/sway/commands/input/xkb_rules.c
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) {
19 19
20 new_config->xkb_rules = strdup(argv[0]); 20 new_config->xkb_rules = strdup(argv[0]);
21 21
22 wlr_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", 22 wlr_log(WLR_DEBUG, "apply-xkb_rules for device: %s rules: %s",
23 current_input_config->identifier, new_config->xkb_rules); 23 current_input_config->identifier, new_config->xkb_rules);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c
index 0e3ffd41..0aa03440 100644
--- a/sway/commands/input/xkb_variant.c
+++ b/sway/commands/input/xkb_variant.c
@@ -19,7 +19,7 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) {
19 19
20 new_config->xkb_variant = strdup(argv[0]); 20 new_config->xkb_variant = strdup(argv[0]);
21 21
22 wlr_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", 22 wlr_log(WLR_DEBUG, "apply-xkb_variant for device: %s variant: %s",
23 current_input_config->identifier, new_config->xkb_variant); 23 current_input_config->identifier, new_config->xkb_variant);
24 apply_input_config(new_config); 24 apply_input_config(new_config);
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 9945fa5c..c446f1f9 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -49,7 +49,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
49 } 49 }
50 50
51 container_notify_subtree_changed(parent); 51 container_notify_subtree_changed(parent);
52 arrange_and_commit(parent); 52 arrange_windows(parent);
53 53
54 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 54 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
55} 55}
diff --git a/sway/commands/mode.c b/sway/commands/mode.c
index 00331ccc..b460fcb5 100644
--- a/sway/commands/mode.c
+++ b/sway/commands/mode.c
@@ -26,7 +26,17 @@ struct cmd_results *cmd_mode(int argc, char **argv) {
26 "mode", "Can only be used in config file."); 26 "mode", "Can only be used in config file.");
27 } 27 }
28 28
29 const char *mode_name = argv[0]; 29 bool pango = strcmp(*argv, "--pango_markup") == 0;
30 if (pango) {
31 argc--; argv++;
32 if (argc == 0) {
33 return cmd_results_new(CMD_FAILURE, "mode",
34 "Mode name is missing");
35 }
36 }
37
38 char *mode_name = *argv;
39 strip_quotes(mode_name);
30 struct sway_mode *mode = NULL; 40 struct sway_mode *mode = NULL;
31 // Find mode 41 // Find mode
32 for (int i = 0; i < config->modes->length; ++i) { 42 for (int i = 0; i < config->modes->length; ++i) {
@@ -46,6 +56,7 @@ struct cmd_results *cmd_mode(int argc, char **argv) {
46 mode->name = strdup(mode_name); 56 mode->name = strdup(mode_name);
47 mode->keysym_bindings = create_list(); 57 mode->keysym_bindings = create_list();
48 mode->keycode_bindings = create_list(); 58 mode->keycode_bindings = create_list();
59 mode->pango = pango;
49 list_add(config->modes, mode); 60 list_add(config->modes, mode);
50 } 61 }
51 if (!mode) { 62 if (!mode) {
@@ -54,13 +65,15 @@ struct cmd_results *cmd_mode(int argc, char **argv) {
54 return error; 65 return error;
55 } 66 }
56 if ((config->reading && argc > 1) || (!config->reading && argc == 1)) { 67 if ((config->reading && argc > 1) || (!config->reading && argc == 1)) {
57 wlr_log(L_DEBUG, "Switching to mode `%s'",mode->name); 68 wlr_log(WLR_DEBUG, "Switching to mode `%s' (pango=%d)",
69 mode->name, mode->pango);
58 } 70 }
59 // Set current mode 71 // Set current mode
60 config->current_mode = mode; 72 config->current_mode = mode;
61 if (argc == 1) { 73 if (argc == 1) {
62 // trigger IPC mode event 74 // trigger IPC mode event
63 ipc_event_mode(config->current_mode->name); 75 ipc_event_mode(config->current_mode->name,
76 config->current_mode->pango);
64 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 77 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
65 } 78 }
66 79
diff --git a/sway/commands/move.c b/sway/commands/move.c
index a4fae388..1940043d 100644
--- a/sway/commands/move.c
+++ b/sway/commands/move.c
@@ -1,13 +1,15 @@
1#define _XOPEN_SOURCE 500 1#define _XOPEN_SOURCE 500
2#include <string.h> 2#include <string.h>
3#include <strings.h> 3#include <strings.h>
4#include <wlr/types/wlr_cursor.h>
4#include <wlr/types/wlr_output.h> 5#include <wlr/types/wlr_output.h>
5#include <wlr/types/wlr_output_layout.h> 6#include <wlr/types/wlr_output_layout.h>
6#include <wlr/util/log.h> 7#include <wlr/util/log.h>
7#include "sway/commands.h" 8#include "sway/commands.h"
8#include "sway/desktop/transaction.h" 9#include "sway/input/cursor.h"
9#include "sway/input/seat.h" 10#include "sway/input/seat.h"
10#include "sway/output.h" 11#include "sway/output.h"
12#include "sway/scratchpad.h"
11#include "sway/tree/arrange.h" 13#include "sway/tree/arrange.h"
12#include "sway/tree/container.h" 14#include "sway/tree/container.h"
13#include "sway/tree/layout.h" 15#include "sway/tree/layout.h"
@@ -103,10 +105,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
103 // TODO: Ideally we would arrange the surviving parent after reaping, 105 // TODO: Ideally we would arrange the surviving parent after reaping,
104 // but container_reap_empty does not return it, so we arrange the 106 // but container_reap_empty does not return it, so we arrange the
105 // workspace instead. 107 // workspace instead.
106 struct sway_transaction *txn = transaction_create(); 108 arrange_windows(old_ws);
107 arrange_windows(old_ws, txn); 109 arrange_windows(destination->parent);
108 arrange_windows(destination->parent, txn);
109 transaction_commit(txn);
110 110
111 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 111 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
112 } else if (strcasecmp(argv[1], "to") == 0 112 } else if (strcasecmp(argv[1], "to") == 0
@@ -142,10 +142,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
142 // TODO: Ideally we would arrange the surviving parent after reaping, 142 // TODO: Ideally we would arrange the surviving parent after reaping,
143 // but container_reap_empty does not return it, so we arrange the 143 // but container_reap_empty does not return it, so we arrange the
144 // workspace instead. 144 // workspace instead.
145 struct sway_transaction *txn = transaction_create(); 145 arrange_windows(old_ws);
146 arrange_windows(old_ws, txn); 146 arrange_windows(focus->parent);
147 arrange_windows(focus->parent, txn);
148 transaction_commit(txn);
149 147
150 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 148 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
151 } 149 }
@@ -175,20 +173,56 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current,
175 } 173 }
176 container_move_to(current, destination); 174 container_move_to(current, destination);
177 175
178 struct sway_transaction *txn = transaction_create(); 176 arrange_windows(source);
179 arrange_windows(source, txn); 177 arrange_windows(destination);
180 arrange_windows(destination, txn);
181 transaction_commit(txn);
182 178
183 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 179 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
184} 180}
185 181
186static struct cmd_results *move_in_direction(struct sway_container *container, 182static struct cmd_results *move_in_direction(struct sway_container *container,
187 enum movement_direction direction, int move_amt) { 183 enum movement_direction direction, int argc, char **argv) {
184 int move_amt = 10;
185 if (argc > 1) {
186 char *inv;
187 move_amt = (int)strtol(argv[1], &inv, 10);
188 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
189 return cmd_results_new(CMD_FAILURE, "move",
190 "Invalid distance specified");
191 }
192 }
193
188 if (container->type == C_WORKSPACE) { 194 if (container->type == C_WORKSPACE) {
189 return cmd_results_new(CMD_FAILURE, "move", 195 return cmd_results_new(CMD_FAILURE, "move",
190 "Cannot move workspaces in a direction"); 196 "Cannot move workspaces in a direction");
191 } 197 }
198 if (container_is_floating(container)) {
199 if (container->type == C_VIEW && container->sway_view->is_fullscreen) {
200 return cmd_results_new(CMD_FAILURE, "move",
201 "Cannot move fullscreen floating container");
202 }
203 double lx = container->x;
204 double ly = container->y;
205 switch (direction) {
206 case MOVE_LEFT:
207 lx -= move_amt;
208 break;
209 case MOVE_RIGHT:
210 lx += move_amt;
211 break;
212 case MOVE_UP:
213 ly -= move_amt;
214 break;
215 case MOVE_DOWN:
216 ly += move_amt;
217 break;
218 case MOVE_PARENT:
219 case MOVE_CHILD:
220 return cmd_results_new(CMD_FAILURE, "move",
221 "Cannot move floating container to parent or child");
222 }
223 container_floating_move_to(container, lx, ly);
224 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
225 }
192 // For simplicity, we'll arrange the entire workspace. The reason for this 226 // For simplicity, we'll arrange the entire workspace. The reason for this
193 // is moving the container might reap the old parent, and container_move 227 // is moving the container might reap the old parent, and container_move
194 // does not return a surviving parent. 228 // does not return a surviving parent.
@@ -198,54 +232,112 @@ static struct cmd_results *move_in_direction(struct sway_container *container,
198 container_move(container, direction, move_amt); 232 container_move(container, direction, move_amt);
199 struct sway_container *new_ws = container_parent(container, C_WORKSPACE); 233 struct sway_container *new_ws = container_parent(container, C_WORKSPACE);
200 234
201 struct sway_transaction *txn = transaction_create(); 235 arrange_windows(old_ws);
202 arrange_windows(old_ws, txn);
203 if (new_ws != old_ws) { 236 if (new_ws != old_ws) {
204 arrange_windows(new_ws, txn); 237 arrange_windows(new_ws);
205 } 238 }
206 transaction_commit(txn);
207 239
208 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 240 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
209} 241}
210 242
243static const char* expected_position_syntax =
244 "Expected 'move [absolute] position <x> <y>' or "
245 "'move [absolute] position mouse'";
246
247static struct cmd_results *move_to_position(struct sway_container *container,
248 int argc, char **argv) {
249 if (!container_is_floating(container)) {
250 return cmd_results_new(CMD_FAILURE, "move",
251 "Only floating containers "
252 "can be moved to an absolute position");
253 }
254 if (!argc) {
255 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
256 }
257 if (strcmp(argv[0], "absolute") == 0) {
258 --argc;
259 ++argv;
260 }
261 if (!argc) {
262 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
263 }
264 if (strcmp(argv[0], "position") == 0) {
265 --argc;
266 ++argv;
267 }
268 if (!argc) {
269 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
270 }
271 if (strcmp(argv[0], "mouse") == 0) {
272 struct sway_seat *seat = config->handler_context.seat;
273 if (!seat->cursor) {
274 return cmd_results_new(CMD_FAILURE, "move", "No cursor device");
275 }
276 double lx = seat->cursor->cursor->x - container->width / 2;
277 double ly = seat->cursor->cursor->y - container->height / 2;
278 container_floating_move_to(container, lx, ly);
279 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
280 }
281 if (argc != 2) {
282 return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax);
283 }
284 double lx, ly;
285 char *inv;
286 lx = (double)strtol(argv[0], &inv, 10);
287 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
288 return cmd_results_new(CMD_FAILURE, "move",
289 "Invalid position specified");
290 }
291 ly = (double)strtol(argv[1], &inv, 10);
292 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
293 return cmd_results_new(CMD_FAILURE, "move",
294 "Invalid position specified");
295 }
296 container_floating_move_to(container, lx, ly);
297 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
298}
299
300static struct cmd_results *move_to_scratchpad(struct sway_container *con) {
301 if (con->type != C_CONTAINER && con->type != C_VIEW) {
302 return cmd_results_new(CMD_INVALID, "move",
303 "Only views and containers can be moved to the scratchpad");
304 }
305 if (con->scratchpad) {
306 return cmd_results_new(CMD_INVALID, "move",
307 "Container is already in the scratchpad");
308 }
309 scratchpad_add_container(con);
310 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
311}
312
211struct cmd_results *cmd_move(int argc, char **argv) { 313struct cmd_results *cmd_move(int argc, char **argv) {
212 struct cmd_results *error = NULL; 314 struct cmd_results *error = NULL;
213 int move_amt = 10;
214 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { 315 if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) {
215 return error; 316 return error;
216 } 317 }
217 struct sway_container *current = config->handler_context.current_container; 318 struct sway_container *current = config->handler_context.current_container;
218 319
219 if (argc == 2 || (argc == 3 && strcasecmp(argv[2], "px") == 0)) {
220 char *inv;
221 move_amt = (int)strtol(argv[1], &inv, 10);
222 if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
223 return cmd_results_new(CMD_FAILURE, "move",
224 "Invalid distance specified");
225 }
226 }
227
228 if (strcasecmp(argv[0], "left") == 0) { 320 if (strcasecmp(argv[0], "left") == 0) {
229 return move_in_direction(current, MOVE_LEFT, move_amt); 321 return move_in_direction(current, MOVE_LEFT, argc, argv);
230 } else if (strcasecmp(argv[0], "right") == 0) { 322 } else if (strcasecmp(argv[0], "right") == 0) {
231 return move_in_direction(current, MOVE_RIGHT, move_amt); 323 return move_in_direction(current, MOVE_RIGHT, argc, argv);
232 } else if (strcasecmp(argv[0], "up") == 0) { 324 } else if (strcasecmp(argv[0], "up") == 0) {
233 return move_in_direction(current, MOVE_UP, move_amt); 325 return move_in_direction(current, MOVE_UP, argc, argv);
234 } else if (strcasecmp(argv[0], "down") == 0) { 326 } else if (strcasecmp(argv[0], "down") == 0) {
235 return move_in_direction(current, MOVE_DOWN, move_amt); 327 return move_in_direction(current, MOVE_DOWN, argc, argv);
236 } else if (strcasecmp(argv[0], "container") == 0 328 } else if (strcasecmp(argv[0], "container") == 0
237 || strcasecmp(argv[0], "window") == 0) { 329 || strcasecmp(argv[0], "window") == 0) {
238 return cmd_move_container(current, argc, argv); 330 return cmd_move_container(current, argc, argv);
239 } else if (strcasecmp(argv[0], "workspace") == 0) { 331 } else if (strcasecmp(argv[0], "workspace") == 0) {
240 return cmd_move_workspace(current, argc, argv); 332 return cmd_move_workspace(current, argc, argv);
241 } else if (strcasecmp(argv[0], "scratchpad") == 0 333 } else if (strcasecmp(argv[0], "scratchpad") == 0
242 || (strcasecmp(argv[0], "to") == 0 334 || (strcasecmp(argv[0], "to") == 0 && argc == 2
243 && strcasecmp(argv[1], "scratchpad") == 0)) { 335 && strcasecmp(argv[1], "scratchpad") == 0)) {
244 // TODO: scratchpad 336 return move_to_scratchpad(current);
245 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented");
246 } else if (strcasecmp(argv[0], "position") == 0) { 337 } else if (strcasecmp(argv[0], "position") == 0) {
247 // TODO: floating 338 return move_to_position(current, argc, argv);
248 return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); 339 } else if (strcasecmp(argv[0], "absolute") == 0) {
340 return move_to_position(current, argc, argv);
249 } else { 341 } else {
250 return cmd_results_new(CMD_INVALID, "move", expected_syntax); 342 return cmd_results_new(CMD_INVALID, "move", expected_syntax);
251 } 343 }
diff --git a/sway/commands/no_focus.c b/sway/commands/no_focus.c
new file mode 100644
index 00000000..61a8de7e
--- /dev/null
+++ b/sway/commands/no_focus.c
@@ -0,0 +1,26 @@
1#define _XOPEN_SOURCE 500
2#include <string.h>
3#include "sway/commands.h"
4#include "sway/criteria.h"
5#include "list.h"
6#include "log.h"
7
8struct cmd_results *cmd_no_focus(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if ((error = checkarg(argc, "no_focus", EXPECTED_AT_LEAST, 1))) {
11 return error;
12 }
13
14 char *err_str = NULL;
15 struct criteria *criteria = criteria_parse(argv[0], &err_str);
16 if (!criteria) {
17 error = cmd_results_new(CMD_INVALID, "no_focus", err_str);
18 free(err_str);
19 return error;
20 }
21
22 criteria->type = CT_NO_FOCUS;
23 list_add(config->criteria, criteria);
24
25 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
26}
diff --git a/sway/commands/output.c b/sway/commands/output.c
index f955bf90..ef1b7a69 100644
--- a/sway/commands/output.c
+++ b/sway/commands/output.c
@@ -29,7 +29,7 @@ struct cmd_results *cmd_output(int argc, char **argv) {
29 29
30 struct output_config *output = new_output_config(argv[0]); 30 struct output_config *output = new_output_config(argv[0]);
31 if (!output) { 31 if (!output) {
32 wlr_log(L_ERROR, "Failed to allocate output config"); 32 wlr_log(WLR_ERROR, "Failed to allocate output config");
33 return NULL; 33 return NULL;
34 } 34 }
35 argc--; argv++; 35 argc--; argv++;
@@ -60,53 +60,13 @@ struct cmd_results *cmd_output(int argc, char **argv) {
60 config->handler_context.leftovers.argc = 0; 60 config->handler_context.leftovers.argc = 0;
61 config->handler_context.leftovers.argv = NULL; 61 config->handler_context.leftovers.argv = NULL;
62 62
63 int i = list_seq_find(config->output_configs, output_name_cmp, output->name); 63 output = store_output_config(output);
64 if (i >= 0) {
65 // Merge existing config
66 struct output_config *current = config->output_configs->items[i];
67 merge_output_config(current, output);
68 free_output_config(output);
69 output = current;
70 } else {
71 list_add(config->output_configs, output);
72 }
73
74 wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz "
75 "position %d,%d scale %f transform %d) (bg %s %s) (dpms %d)",
76 output->name, output->enabled, output->width, output->height,
77 output->refresh_rate, output->x, output->y, output->scale,
78 output->transform, output->background, output->background_option, output->dpms_state);
79
80 // Try to find the output container and apply configuration now. If
81 // this is during startup then there will be no container and config
82 // will be applied during normal "new output" event from wlroots.
83 char identifier[128];
84 bool all = strcmp(output->name, "*") == 0;
85 struct sway_output *sway_output;
86 wl_list_for_each(sway_output, &root_container.sway_root->outputs, link) {
87 output_get_identifier(identifier, sizeof(identifier), sway_output);
88 wlr_log(L_DEBUG, "Checking identifier %s", identifier);
89 if (all || strcmp(sway_output->wlr_output->name, output->name) == 0
90 || strcmp(identifier, output->name) == 0) {
91 if (!sway_output->swayc) {
92 if (!output->enabled) {
93 if (!all) {
94 break;
95 }
96 continue;
97 }
98 64
99 output_enable(sway_output); 65 // If reloading, the output configs will be applied after reading the
100 } 66 // entire config and before the deferred commands so that an auto generated
101 67 // workspace name is not given to re-enabled outputs.
102 apply_output_config(output, sway_output->swayc); 68 if (!config->reloading) {
103 69 apply_output_config_to_outputs(output);
104 if (!all) {
105 // Stop looking if the output config isn't applicable to all
106 // outputs
107 break;
108 }
109 }
110 } 70 }
111 71
112 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 72 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c
index 55cbdff0..4ed56c2a 100644
--- a/sway/commands/output/background.c
+++ b/sway/commands/output/background.c
@@ -72,7 +72,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
72 src = strdup(p.we_wordv[0]); 72 src = strdup(p.we_wordv[0]);
73 wordfree(&p); 73 wordfree(&p);
74 if (!src) { 74 if (!src) {
75 wlr_log(L_ERROR, "Failed to duplicate string"); 75 wlr_log(WLR_ERROR, "Failed to duplicate string");
76 return cmd_results_new(CMD_FAILURE, "output", 76 return cmd_results_new(CMD_FAILURE, "output",
77 "Unable to allocate resource"); 77 "Unable to allocate resource");
78 } 78 }
@@ -80,9 +80,10 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
80 if (config->reading && *src != '/') { 80 if (config->reading && *src != '/') {
81 // src file is inside configuration dir 81 // src file is inside configuration dir
82 82
83 char *conf = strdup(config->current_config); 83 char *conf = strdup(config->current_config_path);
84 if(!conf) { 84 if (!conf) {
85 wlr_log(L_ERROR, "Failed to duplicate string"); 85 wlr_log(WLR_ERROR, "Failed to duplicate string");
86 free(src);
86 return cmd_results_new(CMD_FAILURE, "output", 87 return cmd_results_new(CMD_FAILURE, "output",
87 "Unable to allocate resources"); 88 "Unable to allocate resources");
88 } 89 }
@@ -93,7 +94,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
93 if (!src) { 94 if (!src) {
94 free(rel_path); 95 free(rel_path);
95 free(conf); 96 free(conf);
96 wlr_log(L_ERROR, "Unable to allocate memory"); 97 wlr_log(WLR_ERROR, "Unable to allocate memory");
97 return cmd_results_new(CMD_FAILURE, "output", 98 return cmd_results_new(CMD_FAILURE, "output",
98 "Unable to allocate resources"); 99 "Unable to allocate resources");
99 } 100 }
diff --git a/sway/commands/output/mode.c b/sway/commands/output/mode.c
index daec6d44..ef56ae9e 100644
--- a/sway/commands/output/mode.c
+++ b/sway/commands/output/mode.c
@@ -36,11 +36,11 @@ struct cmd_results *output_cmd_mode(int argc, char **argv) {
36 } 36 }
37 } else { 37 } else {
38 // Format is 1234 4321 38 // Format is 1234 4321
39 argc--; argv++;
39 if (!argc) { 40 if (!argc) {
40 return cmd_results_new(CMD_INVALID, "output", 41 return cmd_results_new(CMD_INVALID, "output",
41 "Missing mode argument (height)."); 42 "Missing mode argument (height).");
42 } 43 }
43 argc--; argv++;
44 output->height = strtol(*argv, &end, 10); 44 output->height = strtol(*argv, &end, 10);
45 if (*end) { 45 if (*end) {
46 return cmd_results_new(CMD_INVALID, "output", 46 return cmd_results_new(CMD_INVALID, "output",
diff --git a/sway/commands/output/position.c b/sway/commands/output/position.c
index c2aeb281..449767b1 100644
--- a/sway/commands/output/position.c
+++ b/sway/commands/output/position.c
@@ -27,11 +27,11 @@ struct cmd_results *output_cmd_position(int argc, char **argv) {
27 } 27 }
28 } else { 28 } else {
29 // Format is 1234 4321 (legacy) 29 // Format is 1234 4321 (legacy)
30 argc--; argv++;
30 if (!argc) { 31 if (!argc) {
31 return cmd_results_new(CMD_INVALID, "output", 32 return cmd_results_new(CMD_INVALID, "output",
32 "Missing position argument (y)."); 33 "Missing position argument (y).");
33 } 34 }
34 argc--; argv++;
35 config->handler_context.output_config->y = strtol(*argv, &end, 10); 35 config->handler_context.output_config->y = strtol(*argv, &end, 10);
36 if (*end) { 36 if (*end) {
37 return cmd_results_new(CMD_INVALID, "output", 37 return cmd_results_new(CMD_INVALID, "output",
diff --git a/sway/commands/reload.c b/sway/commands/reload.c
index 9fc213c4..cea6a94b 100644
--- a/sway/commands/reload.c
+++ b/sway/commands/reload.c
@@ -7,11 +7,11 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
7 if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { 7 if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) {
8 return error; 8 return error;
9 } 9 }
10 if (!load_main_config(config->current_config, true)) { 10 if (!load_main_config(config->current_config_path, true)) {
11 return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); 11 return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config.");
12 } 12 }
13 13
14 load_swaybars(); 14 load_swaybars();
15 arrange_and_commit(&root_container); 15 arrange_windows(&root_container);
16 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 16 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
17} 17}
diff --git a/sway/commands/rename.c b/sway/commands/rename.c
index 104a3392..a380ff9c 100644
--- a/sway/commands/rename.c
+++ b/sway/commands/rename.c
@@ -68,7 +68,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) {
68 "Workspace already exists"); 68 "Workspace already exists");
69 } 69 }
70 70
71 wlr_log(L_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name); 71 wlr_log(WLR_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name);
72 free(workspace->name); 72 free(workspace->name);
73 workspace->name = new_name; 73 workspace->name = new_name;
74 74
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index 6357343e..e657864c 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -1,4 +1,5 @@
1#include <errno.h> 1#include <errno.h>
2#include <limits.h>
2#include <math.h> 3#include <math.h>
3#include <stdbool.h> 4#include <stdbool.h>
4#include <stdlib.h> 5#include <stdlib.h>
@@ -7,6 +8,7 @@
7#include <wlr/util/log.h> 8#include <wlr/util/log.h>
8#include "sway/commands.h" 9#include "sway/commands.h"
9#include "sway/tree/arrange.h" 10#include "sway/tree/arrange.h"
11#include "sway/tree/view.h"
10#include "log.h" 12#include "log.h"
11 13
12static const int MIN_SANE_W = 100, MIN_SANE_H = 60; 14static const int MIN_SANE_W = 100, MIN_SANE_H = 60;
@@ -21,9 +23,18 @@ enum resize_unit {
21enum resize_axis { 23enum resize_axis {
22 RESIZE_AXIS_HORIZONTAL, 24 RESIZE_AXIS_HORIZONTAL,
23 RESIZE_AXIS_VERTICAL, 25 RESIZE_AXIS_VERTICAL,
26 RESIZE_AXIS_UP,
27 RESIZE_AXIS_DOWN,
28 RESIZE_AXIS_LEFT,
29 RESIZE_AXIS_RIGHT,
24 RESIZE_AXIS_INVALID, 30 RESIZE_AXIS_INVALID,
25}; 31};
26 32
33struct resize_amount {
34 int amount;
35 enum resize_unit unit;
36};
37
27static enum resize_unit parse_resize_unit(const char *unit) { 38static enum resize_unit parse_resize_unit(const char *unit) {
28 if (strcasecmp(unit, "px") == 0) { 39 if (strcasecmp(unit, "px") == 0) {
29 return RESIZE_UNIT_PX; 40 return RESIZE_UNIT_PX;
@@ -37,6 +48,69 @@ static enum resize_unit parse_resize_unit(const char *unit) {
37 return RESIZE_UNIT_INVALID; 48 return RESIZE_UNIT_INVALID;
38} 49}
39 50
51// Parse arguments such as "10", "10px" or "10 px".
52// Returns the number of arguments consumed.
53static int parse_resize_amount(int argc, char **argv,
54 struct resize_amount *amount) {
55 char *err;
56 amount->amount = (int)strtol(argv[0], &err, 10);
57 if (*err) {
58 // e.g. 10px
59 amount->unit = parse_resize_unit(err);
60 return 1;
61 }
62 if (argc == 1) {
63 amount->unit = RESIZE_UNIT_DEFAULT;
64 return 1;
65 }
66 // Try the second argument
67 amount->unit = parse_resize_unit(argv[1]);
68 if (amount->unit == RESIZE_UNIT_INVALID) {
69 amount->unit = RESIZE_UNIT_DEFAULT;
70 return 1;
71 }
72 return 2;
73}
74
75static void calculate_constraints(int *min_width, int *max_width,
76 int *min_height, int *max_height) {
77 struct sway_container *con = config->handler_context.current_container;
78
79 if (config->floating_minimum_width == -1) { // no minimum
80 *min_width = 0;
81 } else if (config->floating_minimum_width == 0) { // automatic
82 *min_width = 75;
83 } else {
84 *min_width = config->floating_minimum_width;
85 }
86
87 if (config->floating_minimum_height == -1) { // no minimum
88 *min_height = 0;
89 } else if (config->floating_minimum_height == 0) { // automatic
90 *min_height = 50;
91 } else {
92 *min_height = config->floating_minimum_height;
93 }
94
95 if (config->floating_maximum_width == -1) { // no maximum
96 *max_width = INT_MAX;
97 } else if (config->floating_maximum_width == 0) { // automatic
98 struct sway_container *ws = container_parent(con, C_WORKSPACE);
99 *max_width = ws->width;
100 } else {
101 *max_width = config->floating_maximum_width;
102 }
103
104 if (config->floating_maximum_height == -1) { // no maximum
105 *max_height = INT_MAX;
106 } else if (config->floating_maximum_height == 0) { // automatic
107 struct sway_container *ws = container_parent(con, C_WORKSPACE);
108 *max_height = ws->height;
109 } else {
110 *max_height = config->floating_maximum_height;
111 }
112}
113
40static enum resize_axis parse_resize_axis(const char *axis) { 114static enum resize_axis parse_resize_axis(const char *axis) {
41 if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) { 115 if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) {
42 return RESIZE_AXIS_HORIZONTAL; 116 return RESIZE_AXIS_HORIZONTAL;
@@ -44,6 +118,18 @@ static enum resize_axis parse_resize_axis(const char *axis) {
44 if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) { 118 if (strcasecmp(axis, "height") == 0 || strcasecmp(axis, "vertical") == 0) {
45 return RESIZE_AXIS_VERTICAL; 119 return RESIZE_AXIS_VERTICAL;
46 } 120 }
121 if (strcasecmp(axis, "up") == 0) {
122 return RESIZE_AXIS_UP;
123 }
124 if (strcasecmp(axis, "down") == 0) {
125 return RESIZE_AXIS_DOWN;
126 }
127 if (strcasecmp(axis, "left") == 0) {
128 return RESIZE_AXIS_LEFT;
129 }
130 if (strcasecmp(axis, "right") == 0) {
131 return RESIZE_AXIS_RIGHT;
132 }
47 return RESIZE_AXIS_INVALID; 133 return RESIZE_AXIS_INVALID;
48} 134}
49 135
@@ -95,7 +181,7 @@ static void resize_tiled(int amount, enum resize_axis axis) {
95 return; 181 return;
96 } 182 }
97 183
98 wlr_log(L_DEBUG, 184 wlr_log(WLR_DEBUG,
99 "Found the proper parent: %p. It has %d l conts, and %d r conts", 185 "Found the proper parent: %p. It has %d l conts, and %d r conts",
100 parent->parent, minor_weight, major_weight); 186 parent->parent, minor_weight, major_weight);
101 187
@@ -182,105 +268,315 @@ static void resize_tiled(int amount, enum resize_axis axis) {
182 } 268 }
183 } 269 }
184 270
185 arrange_and_commit(parent->parent); 271 arrange_windows(parent->parent);
186} 272}
187 273
188static void resize(int amount, enum resize_axis axis, enum resize_unit unit) { 274/**
189 struct sway_container *current = config->handler_context.current_container; 275 * Implement `resize <grow|shrink>` for a floating container.
190 if (unit == RESIZE_UNIT_DEFAULT) { 276 */
191 // Default for tiling; TODO floating should be px 277static struct cmd_results *resize_adjust_floating(enum resize_axis axis,
192 unit = RESIZE_UNIT_PPT; 278 struct resize_amount *amount) {
279 struct sway_container *con = config->handler_context.current_container;
280 int grow_width = 0, grow_height = 0;
281 switch (axis) {
282 case RESIZE_AXIS_HORIZONTAL:
283 case RESIZE_AXIS_LEFT:
284 case RESIZE_AXIS_RIGHT:
285 grow_width = amount->amount;
286 break;
287 case RESIZE_AXIS_VERTICAL:
288 case RESIZE_AXIS_UP:
289 case RESIZE_AXIS_DOWN:
290 grow_height = amount->amount;
291 break;
292 case RESIZE_AXIS_INVALID:
293 return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction");
294 }
295 // Make sure we're not adjusting beyond floating min/max size
296 int min_width, max_width, min_height, max_height;
297 calculate_constraints(&min_width, &max_width, &min_height, &max_height);
298 if (con->width + grow_width < min_width) {
299 grow_width = min_width - con->width;
300 } else if (con->width + grow_width > max_width) {
301 grow_width = max_width - con->width;
193 } 302 }
303 if (con->height + grow_height < min_height) {
304 grow_height = min_height - con->height;
305 } else if (con->height + grow_height > max_height) {
306 grow_height = max_height - con->height;
307 }
308 int grow_x = 0, grow_y = 0;
309 switch (axis) {
310 case RESIZE_AXIS_HORIZONTAL:
311 grow_x = -grow_width / 2;
312 break;
313 case RESIZE_AXIS_VERTICAL:
314 grow_y = -grow_height / 2;
315 break;
316 case RESIZE_AXIS_UP:
317 grow_y = -grow_height;
318 break;
319 case RESIZE_AXIS_LEFT:
320 grow_x = -grow_width;
321 break;
322 case RESIZE_AXIS_DOWN:
323 case RESIZE_AXIS_RIGHT:
324 break;
325 case RESIZE_AXIS_INVALID:
326 return cmd_results_new(CMD_INVALID, "resize", "Invalid axis/direction");
327 }
328 con->x += grow_x;
329 con->y += grow_y;
330 con->width += grow_width;
331 con->height += grow_height;
332
333 if (con->type == C_VIEW) {
334 struct sway_view *view = con->sway_view;
335 view->x += grow_x;
336 view->y += grow_y;
337 view->width += grow_width;
338 view->height += grow_height;
339 }
340
341 arrange_windows(con);
342
343 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
344}
194 345
195 if (unit == RESIZE_UNIT_PPT) { 346/**
196 float pct = amount / 100.0f; 347 * Implement `resize <grow|shrink>` for a tiled container.
348 */
349static struct cmd_results *resize_adjust_tiled(enum resize_axis axis,
350 struct resize_amount *amount) {
351 struct sway_container *current = config->handler_context.current_container;
352
353 if (amount->unit == RESIZE_UNIT_DEFAULT) {
354 amount->unit = RESIZE_UNIT_PPT;
355 }
356 if (amount->unit == RESIZE_UNIT_PPT) {
357 float pct = amount->amount / 100.0f;
358 // TODO: Make left/right/up/down resize in that direction?
197 switch (axis) { 359 switch (axis) {
360 case RESIZE_AXIS_LEFT:
361 case RESIZE_AXIS_RIGHT:
198 case RESIZE_AXIS_HORIZONTAL: 362 case RESIZE_AXIS_HORIZONTAL:
199 amount = (float)current->width * pct; 363 amount->amount = (float)current->width * pct;
200 break; 364 break;
365 case RESIZE_AXIS_UP:
366 case RESIZE_AXIS_DOWN:
201 case RESIZE_AXIS_VERTICAL: 367 case RESIZE_AXIS_VERTICAL:
202 amount = (float)current->height * pct; 368 amount->amount = (float)current->height * pct;
203 break; 369 break;
204 default: 370 case RESIZE_AXIS_INVALID:
205 sway_assert(0, "invalid resize axis"); 371 return cmd_results_new(CMD_INVALID, "resize",
206 return; 372 "Invalid resize axis/direction");
207 } 373 }
208 } 374 }
209 375
210 return resize_tiled(amount, axis); 376 resize_tiled(amount->amount, axis);
377 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
211} 378}
212 379
213struct cmd_results *cmd_resize(int argc, char **argv) { 380/**
214 struct sway_container *current = config->handler_context.current_container; 381 * Implement `resize set` for a tiled container.
215 if (!current) { 382 */
216 return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing"); 383static struct cmd_results *resize_set_tiled(struct sway_container *con,
217 } 384 struct resize_amount *width, struct resize_amount *height) {
218 if (current->type != C_VIEW && current->type != C_CONTAINER) { 385 return cmd_results_new(CMD_INVALID, "resize",
219 return cmd_results_new(CMD_INVALID, "resize", 386 "'resize set' is not implemented for tiled views");
220 "Can only resize views/containers"); 387}
388
389/**
390 * Implement `resize set` for a floating container.
391 */
392static struct cmd_results *resize_set_floating(struct sway_container *con,
393 struct resize_amount *width, struct resize_amount *height) {
394 int min_width, max_width, min_height, max_height;
395 calculate_constraints(&min_width, &max_width, &min_height, &max_height);
396 width->amount = fmax(min_width, fmin(width->amount, max_width));
397 height->amount = fmax(min_height, fmin(height->amount, max_height));
398 int grow_width = width->amount - con->width;
399 int grow_height = height->amount - con->height;
400 con->x -= grow_width / 2;
401 con->y -= grow_height / 2;
402 con->width = width->amount;
403 con->height = height->amount;
404
405 if (con->type == C_VIEW) {
406 struct sway_view *view = con->sway_view;
407 view->x -= grow_width / 2;
408 view->y -= grow_height / 2;
409 view->width += grow_width;
410 view->height += grow_height;
221 } 411 }
222 412
413 arrange_windows(con);
414
415 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
416}
417
418/**
419 * resize set <args>
420 *
421 * args: <width> [px|ppt] <height> [px|ppt]
422 */
423static struct cmd_results *cmd_resize_set(int argc, char **argv) {
223 struct cmd_results *error; 424 struct cmd_results *error;
224 if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { 425 if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) {
225 return error; 426 return error;
226 } 427 }
227 428 const char *usage = "Expected 'resize set <width> <height>'";
228 if (strcasecmp(argv[0], "set") == 0) { 429
229 // TODO 430 // Width
230 //return cmd_resize_set(argc - 1, &argv[1]); 431 struct resize_amount width;
231 return cmd_results_new(CMD_INVALID, "resize", "resize set unimplemented"); 432 int num_consumed_args = parse_resize_amount(argc, argv, &width);
433 argc -= num_consumed_args;
434 argv += num_consumed_args;
435 if (width.unit == RESIZE_UNIT_INVALID) {
436 return cmd_results_new(CMD_INVALID, "resize", usage);
437 }
438 if (!argc) {
439 return cmd_results_new(CMD_INVALID, "resize", usage);
232 } 440 }
233 441
234 // TODO: resize grow|shrink left|right|up|down 442 // Height
443 struct resize_amount height;
444 num_consumed_args = parse_resize_amount(argc, argv, &height);
445 argc -= num_consumed_args;
446 argv += num_consumed_args;
447 if (height.unit == RESIZE_UNIT_INVALID) {
448 return cmd_results_new(CMD_INVALID, "resize", usage);
449 }
235 450
236 const char *usage = "Expected 'resize <shrink|grow> " 451 // If 0, don't resize that dimension
237 "<width|height> [<amount>] [px|ppt]'"; 452 struct sway_container *con = config->handler_context.current_container;
453 if (width.amount <= 0) {
454 width.amount = con->width;
455 }
456 if (height.amount <= 0) {
457 height.amount = con->height;
458 }
238 459
239 int multiplier = 0; 460 if (container_is_floating(con)) {
240 if (strcasecmp(*argv, "grow") == 0) { 461 return resize_set_floating(con, &width, &height);
241 multiplier = 1;
242 } else if (strcasecmp(*argv, "shrink") == 0) {
243 multiplier = -1;
244 } else {
245 return cmd_results_new(CMD_INVALID, "resize", usage);
246 } 462 }
247 --argc; ++argv; 463 return resize_set_tiled(con, &width, &height);
464}
248 465
466/**
467 * resize <grow|shrink> <args>
468 *
469 * args: <direction>
470 * args: <direction> <amount> <unit>
471 * args: <direction> <amount> <unit> or <amount> <other_unit>
472 */
473static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
474 int multiplier) {
475 const char *usage = "Expected 'resize grow|shrink <direction> "
476 "[<amount> px|ppt [or <amount> px|ppt]]'";
249 enum resize_axis axis = parse_resize_axis(*argv); 477 enum resize_axis axis = parse_resize_axis(*argv);
250 if (axis == RESIZE_AXIS_INVALID) { 478 if (axis == RESIZE_AXIS_INVALID) {
251 return cmd_results_new(CMD_INVALID, "resize", usage); 479 return cmd_results_new(CMD_INVALID, "resize", usage);
252 } 480 }
253 --argc; ++argv; 481 --argc; ++argv;
254 482
255 int amount = 10; // Default amount 483 // First amount
256 enum resize_unit unit = RESIZE_UNIT_DEFAULT; 484 struct resize_amount first_amount;
257
258 if (argc) { 485 if (argc) {
259 char *err; 486 int num_consumed_args = parse_resize_amount(argc, argv, &first_amount);
260 amount = (int)strtol(*argv, &err, 10); 487 argc -= num_consumed_args;
261 if (*err) { 488 argv += num_consumed_args;
262 // e.g. `resize grow width 10px` 489 if (first_amount.unit == RESIZE_UNIT_INVALID) {
263 unit = parse_resize_unit(err); 490 return cmd_results_new(CMD_INVALID, "resize", usage);
264 if (unit == RESIZE_UNIT_INVALID) {
265 return cmd_results_new(CMD_INVALID, "resize", usage);
266 }
267 } 491 }
268 --argc; ++argv; 492 } else {
493 first_amount.amount = 10;
494 first_amount.unit = RESIZE_UNIT_DEFAULT;
269 } 495 }
270 496
497 // "or"
271 if (argc) { 498 if (argc) {
272 unit = parse_resize_unit(*argv); 499 if (strcmp(*argv, "or") != 0) {
273 if (unit == RESIZE_UNIT_INVALID) {
274 return cmd_results_new(CMD_INVALID, "resize", usage); 500 return cmd_results_new(CMD_INVALID, "resize", usage);
275 } 501 }
276 --argc; ++argv; 502 --argc; ++argv;
277 } 503 }
278 504
505 // Second amount
506 struct resize_amount second_amount;
279 if (argc) { 507 if (argc) {
280 // Provied too many args, the bastard 508 int num_consumed_args = parse_resize_amount(argc, argv, &second_amount);
281 return cmd_results_new(CMD_INVALID, "resize", usage); 509 argc -= num_consumed_args;
510 argv += num_consumed_args;
511 if (second_amount.unit == RESIZE_UNIT_INVALID) {
512 return cmd_results_new(CMD_INVALID, "resize", usage);
513 }
514 } else {
515 second_amount.unit = RESIZE_UNIT_INVALID;
282 } 516 }
283 517
284 resize(amount * multiplier, axis, unit); 518 first_amount.amount *= multiplier;
285 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 519 second_amount.amount *= multiplier;
520
521 struct sway_container *con = config->handler_context.current_container;
522 if (container_is_floating(con)) {
523 // Floating containers can only resize in px. Choose an amount which
524 // uses px, with fallback to an amount that specified no unit.
525 if (first_amount.unit == RESIZE_UNIT_PX) {
526 return resize_adjust_floating(axis, &first_amount);
527 } else if (second_amount.unit == RESIZE_UNIT_PX) {
528 return resize_adjust_floating(axis, &second_amount);
529 } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
530 return resize_adjust_floating(axis, &first_amount);
531 } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
532 return resize_adjust_floating(axis, &second_amount);
533 } else {
534 return cmd_results_new(CMD_INVALID, "resize",
535 "Floating containers cannot use ppt measurements");
536 }
537 }
538
539 // For tiling, prefer ppt -> default -> px
540 if (first_amount.unit == RESIZE_UNIT_PPT) {
541 return resize_adjust_tiled(axis, &first_amount);
542 } else if (second_amount.unit == RESIZE_UNIT_PPT) {
543 return resize_adjust_tiled(axis, &second_amount);
544 } else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
545 return resize_adjust_tiled(axis, &first_amount);
546 } else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
547 return resize_adjust_tiled(axis, &second_amount);
548 } else {
549 return resize_adjust_tiled(axis, &first_amount);
550 }
551}
552
553struct cmd_results *cmd_resize(int argc, char **argv) {
554 struct sway_container *current = config->handler_context.current_container;
555 if (!current) {
556 return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing");
557 }
558 if (current->type != C_VIEW && current->type != C_CONTAINER) {
559 return cmd_results_new(CMD_INVALID, "resize",
560 "Can only resize views/containers");
561 }
562
563 struct cmd_results *error;
564 if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) {
565 return error;
566 }
567
568 if (strcasecmp(argv[0], "set") == 0) {
569 return cmd_resize_set(argc - 1, &argv[1]);
570 }
571 if (strcasecmp(argv[0], "grow") == 0) {
572 return cmd_resize_adjust(argc - 1, &argv[1], 1);
573 }
574 if (strcasecmp(argv[0], "shrink") == 0) {
575 return cmd_resize_adjust(argc - 1, &argv[1], -1);
576 }
577
578 const char *usage = "Expected 'resize <shrink|grow> "
579 "<width|height|up|down|left|right> [<amount>] [px|ppt]'";
580
581 return cmd_results_new(CMD_INVALID, "resize", usage);
286} 582}
diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c
new file mode 100644
index 00000000..ccc07c87
--- /dev/null
+++ b/sway/commands/scratchpad.c
@@ -0,0 +1,36 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/scratchpad.h"
5#include "sway/tree/container.h"
6
7struct cmd_results *cmd_scratchpad(int argc, char **argv) {
8 struct cmd_results *error = NULL;
9 if ((error = checkarg(argc, "scratchpad", EXPECTED_EQUAL_TO, 1))) {
10 return error;
11 }
12 if (strcmp(argv[0], "show") != 0) {
13 return cmd_results_new(CMD_INVALID, "scratchpad",
14 "Expected 'scratchpad show'");
15 }
16 if (!root_container.sway_root->scratchpad->length) {
17 return cmd_results_new(CMD_INVALID, "scratchpad",
18 "Scratchpad is empty");
19 }
20
21 if (config->handler_context.using_criteria) {
22 // If using criteria, this command is executed for every container which
23 // matches the criteria. If this container isn't in the scratchpad,
24 // we'll just silently return a success.
25 struct sway_container *con = config->handler_context.current_container;
26 wlr_log(WLR_INFO, "cmd_scratchpad(%s)", con->name);
27 if (!con->scratchpad) {
28 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
29 }
30 scratchpad_toggle_container(con);
31 } else {
32 scratchpad_toggle_auto();
33 }
34
35 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
36}
diff --git a/sway/commands/set.c b/sway/commands/set.c
index 84e9b792..ea388d3b 100644
--- a/sway/commands/set.c
+++ b/sway/commands/set.c
@@ -32,7 +32,7 @@ struct cmd_results *cmd_set(int argc, char **argv) {
32 } 32 }
33 33
34 if (argv[0][0] != '$') { 34 if (argv[0][0] != '$') {
35 wlr_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); 35 wlr_log(WLR_INFO, "Warning: variable '%s' doesn't start with $", argv[0]);
36 36
37 size_t size = snprintf(NULL, 0, "$%s", argv[0]); 37 size_t size = snprintf(NULL, 0, "$%s", argv[0]);
38 tmp = malloc(size + 1); 38 tmp = malloc(size + 1);
diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c
index f687e78e..7d27e571 100644
--- a/sway/commands/smart_gaps.c
+++ b/sway/commands/smart_gaps.c
@@ -23,7 +23,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) {
23 "Expected 'smart_gaps <on|off>' "); 23 "Expected 'smart_gaps <on|off>' ");
24 } 24 }
25 25
26 arrange_and_commit(&root_container); 26 arrange_windows(&root_container);
27 27
28 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 28 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
29} 29}
diff --git a/sway/commands/split.c b/sway/commands/split.c
index c40f4d9f..313799da 100644
--- a/sway/commands/split.c
+++ b/sway/commands/split.c
@@ -16,7 +16,7 @@ static struct cmd_results *do_split(int layout) {
16 } 16 }
17 struct sway_container *parent = container_split(con, layout); 17 struct sway_container *parent = container_split(con, layout);
18 container_create_notify(parent); 18 container_create_notify(parent);
19 arrange_and_commit(parent->parent); 19 arrange_windows(parent->parent);
20 20
21 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 21 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
22} 22}
diff --git a/sway/commands/swap.c b/sway/commands/swap.c
index e052058f..2fc88308 100644
--- a/sway/commands/swap.c
+++ b/sway/commands/swap.c
@@ -1,7 +1,6 @@
1#include <strings.h> 1#include <strings.h>
2#include <wlr/util/log.h> 2#include <wlr/util/log.h>
3#include "sway/commands.h" 3#include "sway/commands.h"
4#include "sway/desktop/transaction.h"
5#include "sway/tree/arrange.h" 4#include "sway/tree/arrange.h"
6#include "sway/tree/layout.h" 5#include "sway/tree/layout.h"
7#include "sway/tree/view.h" 6#include "sway/tree/view.h"
@@ -79,14 +78,10 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
79 78
80 container_swap(current, other); 79 container_swap(current, other);
81 80
82 struct sway_transaction *txn = transaction_create(); 81 arrange_windows(current->parent);
83 arrange_windows(current->parent, txn);
84
85 if (other->parent != current->parent) { 82 if (other->parent != current->parent) {
86 arrange_windows(other->parent, txn); 83 arrange_windows(other->parent);
87 } 84 }
88 85
89 transaction_commit(txn);
90
91 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 86 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
92} 87}
diff --git a/sway/commands/swaybg_command.c b/sway/commands/swaybg_command.c
index 770d4821..36f7fdcd 100644
--- a/sway/commands/swaybg_command.c
+++ b/sway/commands/swaybg_command.c
@@ -13,7 +13,7 @@ struct cmd_results *cmd_swaybg_command(int argc, char **argv) {
13 free(config->swaybg_command); 13 free(config->swaybg_command);
14 } 14 }
15 config->swaybg_command = join_args(argv, argc); 15 config->swaybg_command = join_args(argv, argc);
16 wlr_log(L_DEBUG, "Using custom swaybg command: %s", 16 wlr_log(WLR_DEBUG, "Using custom swaybg command: %s",
17 config->swaybg_command); 17 config->swaybg_command);
18 18
19 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 19 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
diff --git a/sway/commands/urgent.c b/sway/commands/urgent.c
new file mode 100644
index 00000000..d199858a
--- /dev/null
+++ b/sway/commands/urgent.c
@@ -0,0 +1,36 @@
1#include "log.h"
2#include "sway/commands.h"
3#include "sway/config.h"
4#include "sway/tree/arrange.h"
5#include "sway/tree/container.h"
6#include "sway/tree/view.h"
7#include "sway/tree/layout.h"
8
9struct cmd_results *cmd_urgent(int argc, char **argv) {
10 struct cmd_results *error = NULL;
11 if ((error = checkarg(argc, "urgent", EXPECTED_EQUAL_TO, 1))) {
12 return error;
13 }
14 struct sway_container *container =
15 config->handler_context.current_container;
16 if (container->type != C_VIEW) {
17 return cmd_results_new(CMD_INVALID, "urgent",
18 "Only views can be urgent");
19 }
20 struct sway_view *view = container->sway_view;
21
22 if (strcmp(argv[0], "enable") == 0) {
23 view_set_urgent(view, true);
24 } else if (strcmp(argv[0], "disable") == 0) {
25 view_set_urgent(view, false);
26 } else if (strcmp(argv[0], "allow") == 0) {
27 view->allow_request_urgent = true;
28 } else if (strcmp(argv[0], "deny") == 0) {
29 view->allow_request_urgent = false;
30 } else {
31 return cmd_results_new(CMD_INVALID, "urgent",
32 "Expected 'urgent <enable|disable|allow|deny>'");
33 }
34
35 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
36}
diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c
index d15be571..e8b37182 100644
--- a/sway/commands/workspace.c
+++ b/sway/commands/workspace.c
@@ -51,7 +51,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
51 free(old); // workspaces can only be assigned to a single output 51 free(old); // workspaces can only be assigned to a single output
52 list_del(config->workspace_outputs, i); 52 list_del(config->workspace_outputs, i);
53 } 53 }
54 wlr_log(L_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output); 54 wlr_log(WLR_DEBUG, "Assigning workspace %s to output %s", wso->workspace, wso->output);
55 list_add(config->workspace_outputs, wso); 55 list_add(config->workspace_outputs, wso);
56 } else { 56 } else {
57 if (config->reading || !config->active) { 57 if (config->reading || !config->active) {