diff options
Diffstat (limited to 'sway/layout.c')
-rw-r--r-- | sway/layout.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/sway/layout.c b/sway/layout.c index 0428ecf9..a8ad7ed5 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -251,7 +251,7 @@ void swap_geometry(swayc_t *a, swayc_t *b) { | |||
251 | } | 251 | } |
252 | 252 | ||
253 | void move_container(swayc_t *container, enum movement_direction dir) { | 253 | void move_container(swayc_t *container, enum movement_direction dir) { |
254 | enum swayc_layouts layout; | 254 | enum swayc_layouts layout = L_NONE; |
255 | if (container->is_floating | 255 | if (container->is_floating |
256 | || (container->type != C_VIEW && container->type != C_CONTAINER)) { | 256 | || (container->type != C_VIEW && container->type != C_CONTAINER)) { |
257 | return; | 257 | return; |
@@ -260,7 +260,7 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
260 | layout = L_VERT; | 260 | layout = L_VERT; |
261 | } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { | 261 | } else if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { |
262 | layout = L_HORIZ; | 262 | layout = L_HORIZ; |
263 | } else { | 263 | } else if (! (dir == MOVE_NEXT || dir == MOVE_PREV)) { |
264 | return; | 264 | return; |
265 | } | 265 | } |
266 | swayc_t *parent = container->parent; | 266 | swayc_t *parent = container->parent; |
@@ -284,18 +284,51 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
284 | container,parent,child); | 284 | container,parent,child); |
285 | if (parent->layout == layout | 285 | if (parent->layout == layout |
286 | || (parent->layout == L_TABBED && layout == L_HORIZ) | 286 | || (parent->layout == L_TABBED && layout == L_HORIZ) |
287 | || (parent->layout == L_STACKED && layout == L_VERT)) { | 287 | || (parent->layout == L_STACKED && layout == L_VERT) |
288 | || is_auto_layout(parent->layout)) { | ||
288 | int diff; | 289 | int diff; |
289 | // If it has ascended (parent has moved up), no container is removed | 290 | // If it has ascended (parent has moved up), no container is removed |
290 | // so insert it at index, or index+1. | 291 | // so insert it at index, or index+1. |
291 | // if it has not, the moved container is removed, so it needs to be | 292 | // if it has not, the moved container is removed, so it needs to be |
292 | // inserted at index-1, or index+1 | 293 | // inserted at index-1, or index+1 |
293 | if (ascended) { | 294 | if (ascended) { |
294 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; | 295 | diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? 0 : 1; |
295 | } else { | 296 | } else { |
296 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; | 297 | diff = dir == MOVE_LEFT || dir == MOVE_UP || dir == MOVE_PREV ? -1 : 1; |
298 | } | ||
299 | int idx = index_child(child); | ||
300 | int desired = idx + diff; | ||
301 | if (dir == MOVE_NEXT || dir == MOVE_PREV) { | ||
302 | // Next/Prev always wrap. | ||
303 | if (desired < 0) { | ||
304 | desired += parent->children->length; | ||
305 | } else if (desired >= parent->children->length) { | ||
306 | desired = 0; | ||
307 | } | ||
308 | // if move command makes container change from master to slave | ||
309 | // (or the contrary), reset its geometry an the one of the replaced item. | ||
310 | if (parent->nb_master && | ||
311 | (uint_fast32_t) parent->children->length > parent->nb_master) { | ||
312 | swayc_t *swap_geom = NULL; | ||
313 | // if child is being promoted/demoted, it will swap geometry | ||
314 | // with the sibling being demoted/promoted. | ||
315 | if ((dir == MOVE_NEXT && desired == 0) | ||
316 | || (dir == MOVE_PREV && (uint_fast32_t) desired == parent->nb_master - 1)) { | ||
317 | swap_geom = parent->children->items[parent->nb_master - 1]; | ||
318 | } else if ((dir == MOVE_NEXT && (uint_fast32_t) desired == parent->nb_master) | ||
319 | || (dir == MOVE_PREV && desired == parent->children->length - 1)) { | ||
320 | swap_geom = parent->children->items[parent->nb_master]; | ||
321 | } | ||
322 | if (swap_geom) { | ||
323 | double h = child->height; | ||
324 | double w = child->width; | ||
325 | child->width = swap_geom->width; | ||
326 | child->height = swap_geom->height; | ||
327 | swap_geom->width = w; | ||
328 | swap_geom->height = h; | ||
329 | } | ||
330 | } | ||
297 | } | 331 | } |
298 | int desired = index_child(child) + diff; | ||
299 | // when it has ascended, legal insertion position is 0:len | 332 | // when it has ascended, legal insertion position is 0:len |
300 | // when it has not, legal insertion position is 0:len-1 | 333 | // when it has not, legal insertion position is 0:len-1 |
301 | if (desired >= 0 && desired - ascended < parent->children->length) { | 334 | if (desired >= 0 && desired - ascended < parent->children->length) { |
@@ -308,7 +341,8 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
308 | // insert it next to focused container | 341 | // insert it next to focused container |
309 | if (parent->layout == layout | 342 | if (parent->layout == layout |
310 | || (parent->layout == L_TABBED && layout == L_HORIZ) | 343 | || (parent->layout == L_TABBED && layout == L_HORIZ) |
311 | || (parent->layout == L_STACKED && layout == L_VERT)) { | 344 | || (parent->layout == L_STACKED && layout == L_VERT) |
345 | || is_auto_layout(parent->layout)) { | ||
312 | desired = (diff < 0) * parent->children->length; | 346 | desired = (diff < 0) * parent->children->length; |
313 | } else { | 347 | } else { |
314 | desired = index_child(child->focused) + 1; | 348 | desired = index_child(child->focused) + 1; |
@@ -325,7 +359,7 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
325 | } | 359 | } |
326 | } | 360 | } |
327 | // Change parent layout if we need to | 361 | // Change parent layout if we need to |
328 | if (parent->children->length == 1 && parent->layout != layout) { | 362 | if (parent->children->length == 1 && parent->layout != layout && layout != L_NONE) { |
329 | /* swayc_change_layout(parent, layout); */ | 363 | /* swayc_change_layout(parent, layout); */ |
330 | parent->layout = layout; | 364 | parent->layout = layout; |
331 | continue; | 365 | continue; |
@@ -1310,6 +1344,21 @@ swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_directio | |||
1310 | return parent; | 1344 | return parent; |
1311 | } | 1345 | } |
1312 | } | 1346 | } |
1347 | |||
1348 | if (dir == MOVE_PREV || dir == MOVE_NEXT) { | ||
1349 | int focused_idx = index_child(container); | ||
1350 | if (focused_idx == -1) { | ||
1351 | return NULL; | ||
1352 | } else { | ||
1353 | int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % | ||
1354 | parent->children->length; | ||
1355 | if (desired < 0) { | ||
1356 | desired += parent->children->length; | ||
1357 | } | ||
1358 | return parent->children->items[desired]; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1313 | // If moving to an adjacent output we need a starting position (since this | 1362 | // If moving to an adjacent output we need a starting position (since this |
1314 | // output might border to multiple outputs). | 1363 | // output might border to multiple outputs). |
1315 | struct wlc_point abs_pos; | 1364 | struct wlc_point abs_pos; |