aboutsummaryrefslogtreecommitdiffstats
path: root/sway/commands/resize.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-01-14 21:22:53 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2019-01-15 08:01:21 +1000
commit2024f1da72d5144a30864d815608e2e856639bf6 (patch)
treee924279ea83525a67b25367baa68a8fb38116324 /sway/commands/resize.c
parentDisarm key repeat on reload (diff)
downloadsway-2024f1da72d5144a30864d815608e2e856639bf6.tar.gz
sway-2024f1da72d5144a30864d815608e2e856639bf6.tar.zst
sway-2024f1da72d5144a30864d815608e2e856639bf6.zip
Resize only current and immediate siblings rather than all siblings
For example, create layout V[view view view] and resize the leftmost view using mod+rightclick. Previously, the edge between view 2 and 3 would be adjusted as well. Now this edge will remain constant, which matches the behaviour of i3. To do this operation correctly, the resize tiling seatop now keeps track of two containers, as the container that resizes horizontally will be a different container to the one which resizes vertically (one will be an ancestor). The tiling resize seatop now figures out these containers during the start of the operation and keeps references to them in the event. A new function container_find_resize_parent has been introduced to do this. This function is also used by the resize command. During cursor motion, the seatop logic is similar to before, but now has to choose the correct container to resize. In resize.c, container_resize_tiled and resize_tiled have been merged into one. One of them originally did nothing except pass the values through to the other. container_resize_tiled now takes a simplified approach where it just finds the immediate siblings on either side and resizes them without worrying about the others. The parellel_coord and parallel_size functions are no longer needed and have been removed.
Diffstat (limited to 'sway/commands/resize.c')
-rw-r--r--sway/commands/resize.c239
1 files changed, 86 insertions, 153 deletions
diff --git a/sway/commands/resize.c b/sway/commands/resize.c
index fad1ecb1..f6141afc 100644
--- a/sway/commands/resize.c
+++ b/sway/commands/resize.c
@@ -130,177 +130,108 @@ static bool is_horizontal(uint32_t axis) {
130 return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT); 130 return axis & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
131} 131}
132 132
133static int parallel_coord(struct sway_container *c, uint32_t axis) { 133struct sway_container *container_find_resize_parent(struct sway_container *con,
134 return is_horizontal(axis) ? c->x : c->y; 134 uint32_t axis) {
135} 135 enum sway_container_layout parallel_layout =
136 136 is_horizontal(axis) ? L_HORIZ : L_VERT;
137static int parallel_size(struct sway_container *c, uint32_t axis) { 137 bool allow_first = axis != WLR_EDGE_TOP && axis != WLR_EDGE_LEFT;
138 return is_horizontal(axis) ? c->width : c->height; 138 bool allow_last = axis != WLR_EDGE_RIGHT && axis != WLR_EDGE_BOTTOM;
139} 139
140 140 while (con) {
141static void container_recursive_resize(struct sway_container *container, 141 list_t *siblings = container_get_siblings(con);
142 double amount, enum wlr_edges edge) { 142 int index = container_sibling_index(con);
143 bool layout_match = true; 143 if (container_parent_layout(con) == parallel_layout &&
144 wlr_log(WLR_DEBUG, "Resizing %p with amount: %f", container, amount); 144 siblings->length > 1 && (allow_first || index > 0) &&
145 if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) { 145 (allow_last || index < siblings->length - 1)) {
146 container->width += amount; 146 return con;
147 layout_match = container->layout == L_HORIZ;
148 } else if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
149 container->height += amount;
150 layout_match = container->layout == L_VERT;
151 }
152 if (container->children) {
153 for (int i = 0; i < container->children->length; i++) {
154 struct sway_container *child = container->children->items[i];
155 double amt = layout_match ?
156 amount / container->children->length : amount;
157 container_recursive_resize(child, amt, edge);
158 } 147 }
148 con = con->parent;
159 } 149 }
150
151 return NULL;
160} 152}
161 153
162static void resize_tiled(struct sway_container *parent, int amount, 154void container_resize_tiled(struct sway_container *con,
163 uint32_t axis) { 155 uint32_t axis, int amount) {
164 struct sway_container *focused = parent; 156 if (!con) {
165 if (!parent) {
166 return; 157 return;
167 } 158 }
168 159
169 enum sway_container_layout parallel_layout = 160 con = container_find_resize_parent(con, axis);
170 is_horizontal(axis) ? L_HORIZ : L_VERT; 161 if (!con) {
171 int minor_weight = 0;
172 int major_weight = 0;
173 while (parent) {
174 list_t *siblings = container_get_siblings(parent);
175 if (container_parent_layout(parent) == parallel_layout) {
176 for (int i = 0; i < siblings->length; i++) {
177 struct sway_container *sibling = siblings->items[i];
178
179 int sibling_pos = parallel_coord(sibling, axis);
180 int focused_pos = parallel_coord(focused, axis);
181 int parent_pos = parallel_coord(parent, axis);
182
183 if (sibling_pos != focused_pos) {
184 if (sibling_pos < parent_pos) {
185 minor_weight++;
186 } else if (sibling_pos > parent_pos) {
187 major_weight++;
188 }
189 }
190 }
191 if (major_weight || minor_weight) {
192 break;
193 }
194 }
195 parent = parent->parent;
196 }
197 if (!parent) {
198 // Can't resize in this direction 162 // Can't resize in this direction
199 return; 163 return;
200 } 164 }
201 165
202 // Implement up/down/left/right direction by zeroing one of the weights 166 // For HORIZONTAL or VERTICAL, we are growing in two directions so select
203 if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) { 167 // both adjacent siblings. For RIGHT or DOWN, just select the next sibling.
204 major_weight = 0; 168 // For LEFT or UP, convert it to a RIGHT or DOWN resize and reassign con to
205 } else if (axis == WLR_EDGE_RIGHT || axis == WLR_EDGE_BOTTOM) { 169 // the previous sibling.
206 minor_weight = 0; 170 struct sway_container *prev = NULL;
207 } 171 struct sway_container *next = NULL;
208 172 list_t *siblings = container_get_siblings(con);
209 bool horizontal = is_horizontal(axis); 173 int index = container_sibling_index(con);
210 int min_sane = horizontal ? MIN_SANE_W : MIN_SANE_H; 174
211 175 if (axis == AXIS_HORIZONTAL || axis == AXIS_VERTICAL) {
212 //TODO: Ensure rounding is done in such a way that there are NO pixel leaks 176 prev = siblings->items[index - 1];
213 // ^ ????? 177 next = siblings->items[index + 1];
214 list_t *siblings = container_get_siblings(parent); 178 } else if (axis == WLR_EDGE_TOP || axis == WLR_EDGE_LEFT) {
215 179 if (!sway_assert(index > 0, "Didn't expect first child")) {
216 for (int i = 0; i < siblings->length; i++) { 180 return;
217 struct sway_container *sibling = siblings->items[i];
218
219 int sibling_pos = parallel_coord(sibling, axis);
220 int focused_pos = parallel_coord(focused, axis);
221 int parent_pos = parallel_coord(parent, axis);
222
223 int sibling_size = parallel_size(sibling, axis);
224 int parent_size = parallel_size(parent, axis);
225
226 if (sibling_pos != focused_pos) {
227 if (sibling_pos < parent_pos && minor_weight) {
228 double pixels = -amount / minor_weight;
229 if (major_weight && (sibling_size + pixels / 2) < min_sane) {
230 return; // Too small
231 } else if (!major_weight && sibling_size + pixels < min_sane) {
232 return; // Too small
233 }
234 } else if (sibling_pos > parent_pos && major_weight) {
235 double pixels = -amount / major_weight;
236 if (minor_weight && (sibling_size + pixels / 2) < min_sane) {
237 return; // Too small
238 } else if (!minor_weight && sibling_size + pixels < min_sane) {
239 return; // Too small
240 }
241 }
242 } else {
243 double pixels = amount;
244 if (parent_size + pixels < min_sane) {
245 return; // Too small
246 }
247 } 181 }
182 next = con;
183 con = siblings->items[index - 1];
184 amount = -amount;
185 } else {
186 if (!sway_assert(index < siblings->length - 1,
187 "Didn't expect last child")) {
188 return;
189 }
190 next = siblings->items[index + 1];
248 } 191 }
249 192
250 enum wlr_edges minor_edge = horizontal ? WLR_EDGE_LEFT : WLR_EDGE_TOP; 193 // Apply new dimensions
251 enum wlr_edges major_edge = horizontal ? WLR_EDGE_RIGHT : WLR_EDGE_BOTTOM; 194 int sibling_amount = prev ? amount / 2 : amount;
252 195
253 for (int i = 0; i < siblings->length; i++) { 196 if (is_horizontal(axis)) {
254 struct sway_container *sibling = siblings->items[i]; 197 if (con->width + amount < MIN_SANE_W) {
255 198 return;
256 int sibling_pos = parallel_coord(sibling, axis); 199 }
257 int focused_pos = parallel_coord(focused, axis); 200 if (next->width - sibling_amount < MIN_SANE_W) {
258 int parent_pos = parallel_coord(parent, axis); 201 return;
259 202 }
260 if (sibling_pos != focused_pos) { 203 if (prev && prev->width - sibling_amount < MIN_SANE_W) {
261 if (sibling_pos < parent_pos && minor_weight) { 204 return;
262 double pixels = -1 * amount; 205 }
263 pixels /= minor_weight; 206 con->width += amount;
264 if (major_weight) { 207 next->width -= sibling_amount;
265 container_recursive_resize(sibling, pixels / 2, major_edge); 208 if (prev) {
266 } else { 209 prev->width -= sibling_amount;
267 container_recursive_resize(sibling, pixels, major_edge); 210 }
268 } 211 } else {
269 } else if (sibling_pos > parent_pos && major_weight) { 212 if (con->height + amount < MIN_SANE_H) {
270 double pixels = -1 * amount; 213 return;
271 pixels /= major_weight; 214 }
272 if (minor_weight) { 215 if (next->height - sibling_amount < MIN_SANE_H) {
273 container_recursive_resize(sibling, pixels / 2, minor_edge); 216 return;
274 } else { 217 }
275 container_recursive_resize(sibling, pixels, minor_edge); 218 if (prev && prev->height - sibling_amount < MIN_SANE_H) {
276 } 219 return;
277 } 220 }
278 } else { 221 con->height += amount;
279 if (major_weight != 0 && minor_weight != 0) { 222 next->height -= sibling_amount;
280 double pixels = amount; 223 if (prev) {
281 pixels /= 2; 224 prev->height -= sibling_amount;
282 container_recursive_resize(parent, pixels, minor_edge);
283 container_recursive_resize(parent, pixels, major_edge);
284 } else if (major_weight) {
285 container_recursive_resize(parent, amount, major_edge);
286 } else if (minor_weight) {
287 container_recursive_resize(parent, amount, minor_edge);
288 }
289 } 225 }
290 } 226 }
291 227
292 if (parent->parent) { 228 if (con->parent) {
293 arrange_container(parent->parent); 229 arrange_container(con->parent);
294 } else { 230 } else {
295 arrange_workspace(parent->workspace); 231 arrange_workspace(con->workspace);
296 } 232 }
297} 233}
298 234
299void container_resize_tiled(struct sway_container *parent,
300 enum wlr_edges edge, int amount) {
301 resize_tiled(parent, amount, edge);
302}
303
304/** 235/**
305 * Implement `resize <grow|shrink>` for a floating container. 236 * Implement `resize <grow|shrink>` for a floating container.
306 */ 237 */
@@ -379,7 +310,7 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
379 310
380 double old_width = current->width; 311 double old_width = current->width;
381 double old_height = current->height; 312 double old_height = current->height;
382 resize_tiled(current, amount->amount, axis); 313 container_resize_tiled(current, axis, amount->amount);
383 if (current->width == old_width && current->height == old_height) { 314 if (current->width == old_width && current->height == old_height) {
384 return cmd_results_new(CMD_INVALID, "Cannot resize any further"); 315 return cmd_results_new(CMD_INVALID, "Cannot resize any further");
385 } 316 }
@@ -407,7 +338,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
407 width->unit = RESIZE_UNIT_PX; 338 width->unit = RESIZE_UNIT_PX;
408 } 339 }
409 if (width->unit == RESIZE_UNIT_PX) { 340 if (width->unit == RESIZE_UNIT_PX) {
410 resize_tiled(con, width->amount - con->width, AXIS_HORIZONTAL); 341 container_resize_tiled(con, AXIS_HORIZONTAL,
342 width->amount - con->width);
411 } 343 }
412 } 344 }
413 345
@@ -427,7 +359,8 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
427 height->unit = RESIZE_UNIT_PX; 359 height->unit = RESIZE_UNIT_PX;
428 } 360 }
429 if (height->unit == RESIZE_UNIT_PX) { 361 if (height->unit == RESIZE_UNIT_PX) {
430 resize_tiled(con, height->amount - con->height, AXIS_VERTICAL); 362 container_resize_tiled(con, AXIS_VERTICAL,
363 height->amount - con->height);
431 } 364 }
432 } 365 }
433 366