summaryrefslogtreecommitdiffstats
path: root/sway/commands/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/commands/layout.c')
-rw-r--r--sway/commands/layout.c127
1 files changed, 126 insertions, 1 deletions
diff --git a/sway/commands/layout.c b/sway/commands/layout.c
index 08336150..d04bb4dc 100644
--- a/sway/commands/layout.c
+++ b/sway/commands/layout.c
@@ -3,6 +3,11 @@
3#include "sway/container.h" 3#include "sway/container.h"
4#include "sway/layout.h" 4#include "sway/layout.h"
5 5
6/**
7 * handle "layout auto" command group
8 */
9static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv);
10
6struct cmd_results *cmd_layout(int argc, char **argv) { 11struct cmd_results *cmd_layout(int argc, char **argv) {
7 struct cmd_results *error = NULL; 12 struct cmd_results *error = NULL;
8 if (config->reading) return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file."); 13 if (config->reading) return cmd_results_new(CMD_FAILURE, "layout", "Can't be used in config file.");
@@ -49,11 +54,14 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
49 } else if (strcasecmp(argv[0], "splitv") == 0) { 54 } else if (strcasecmp(argv[0], "splitv") == 0) {
50 swayc_change_layout(parent, L_VERT); 55 swayc_change_layout(parent, L_VERT);
51 } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { 56 } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) {
52 if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE || parent->workspace_layout == L_HORIZ)) { 57 if (parent->layout == L_HORIZ && (parent->workspace_layout == L_NONE
58 || parent->workspace_layout == L_HORIZ)) {
53 swayc_change_layout(parent, L_VERT); 59 swayc_change_layout(parent, L_VERT);
54 } else { 60 } else {
55 swayc_change_layout(parent, L_HORIZ); 61 swayc_change_layout(parent, L_HORIZ);
56 } 62 }
63 } else if (strcasecmp(argv[0], "auto") == 0) {
64 return cmd_layout_auto(parent, argc, argv);
57 } 65 }
58 } 66 }
59 67
@@ -64,3 +72,120 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
64 72
65 return cmd_results_new(CMD_SUCCESS, NULL, NULL); 73 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
66} 74}
75
76static struct cmd_results *cmd_layout_auto(swayc_t *container, int argc, char **argv) {
77 // called after checking that argv[0] is auto, so just continue parsing from there
78 struct cmd_results *error = NULL;
79 const char *cmd_name = "layout auto";
80 const char *set_inc_cmd_name = "layout auto [master|ncol] [set|inc]";
81 const char *err_msg = "Allowed arguments are <right|left|top|bottom|next|prev|master|ncol>";
82
83 bool need_layout_update = false;
84 enum swayc_layouts old_layout = container->layout;
85 enum swayc_layouts layout = old_layout;
86
87 if (strcasecmp(argv[1], "left") == 0) {
88 layout = L_AUTO_LEFT;
89 } else if (strcasecmp(argv[1], "right") == 0) {
90 layout = L_AUTO_RIGHT;
91 } else if (strcasecmp(argv[1], "top") == 0) {
92 layout = L_AUTO_TOP;
93 } else if (strcasecmp(argv[1], "bottom") == 0) {
94 layout = L_AUTO_BOTTOM;
95 } else if (strcasecmp(argv[1], "next") == 0) {
96 if (is_auto_layout(container->layout) && container->layout < L_AUTO_LAST) {
97 layout = container->layout + 1;
98 } else {
99 layout = L_AUTO_FIRST;
100 }
101 } else if (strcasecmp(argv[1], "prev") == 0) {
102 if (is_auto_layout(container->layout) && container->layout > L_AUTO_FIRST) {
103 layout = container->layout - 1;
104 } else {
105 layout = L_AUTO_LAST;
106 }
107 } else {
108 bool is_nmaster;
109 bool is_set;
110 if (strcasecmp(argv[1], "master") == 0) {
111 is_nmaster = true;
112 } else if (strcasecmp(argv[1], "ncol") == 0) {
113 is_nmaster = false;
114 } else {
115 return cmd_results_new(CMD_INVALID, cmd_name, "Invalid %s command. %s",
116 cmd_name, err_msg);
117 }
118 if ((error = checkarg(argc, "auto <master|ncol>", EXPECTED_EQUAL_TO, 4))) {
119 return error;
120 }
121 if (strcasecmp(argv[2], "set") == 0) {
122 is_set = true;
123 } else if (strcasecmp(argv[2], "inc") == 0) {
124 is_set = false;
125 } else {
126 return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command. %s, "
127 "Argument must be on of <set|inc>",
128 set_inc_cmd_name);
129 }
130 char *end;
131 int n = (int)strtol(argv[3], &end, 10);
132 if (*end) {
133 return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command "
134 "(argument must be an integer)", set_inc_cmd_name);
135 }
136 if (is_auto_layout(container->layout)) {
137 int inc = 0; /* difference between current master/ncol and requested value */
138 if (is_nmaster) {
139 if (is_set) {
140 if (n < 0) {
141 return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command "
142 "(master must be >= 0)", set_inc_cmd_name);
143 }
144 inc = n - (int)container->nb_master;
145 } else { /* inc command */
146 if ((int)container->nb_master + n >= 0) {
147 inc = n;
148 }
149 }
150 if (inc) {
151 for (int i = container->nb_master;
152 i >= 0 && i < container->children->length
153 && i != (int)container->nb_master + inc;) {
154 ((swayc_t *)container->children->items[i])->height = -1;
155 ((swayc_t *)container->children->items[i])->width = -1;
156 i += inc > 0 ? 1 : -1;
157 }
158 container->nb_master += inc;
159 need_layout_update = true;
160 }
161 } else { /* ncol modification */
162 if (is_set) {
163 if (n <= 0) {
164 return cmd_results_new(CMD_INVALID, set_inc_cmd_name, "Invalid %s command "
165 "(ncol must be > 0)", set_inc_cmd_name);
166 }
167 inc = n - (int)container->nb_slave_groups;
168 } else { /* inc command */
169 if ((int)container->nb_slave_groups + n > 0) {
170 inc = n;
171 }
172 }
173 if (inc) {
174 container->nb_slave_groups += inc;
175 need_layout_update = true;
176 }
177 }
178 }
179 }
180
181 if (layout != old_layout) {
182 swayc_change_layout(container, layout);
183 update_layout_geometry(container, old_layout);
184 need_layout_update = true;
185 }
186 if (need_layout_update) {
187 update_geometry(container);
188 arrange_windows(container, container->width, container->height);
189 }
190 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
191}