diff options
Diffstat (limited to 'sway/layout.c')
-rw-r--r-- | sway/layout.c | 59 |
1 files changed, 34 insertions, 25 deletions
diff --git a/sway/layout.c b/sway/layout.c index 103ede52..b558e704 100644 --- a/sway/layout.c +++ b/sway/layout.c | |||
@@ -195,7 +195,6 @@ void swap_geometry(swayc_t *a, swayc_t *b) { | |||
195 | // TODO fix workspace movement, as in | 195 | // TODO fix workspace movement, as in |
196 | // [a][b][c] => |move b| => [aa][cc] | 196 | // [a][b][c] => |move b| => [aa][cc] |
197 | // [a][b][c] => |down | => [bbbbbb] | 197 | // [a][b][c] => |down | => [bbbbbb] |
198 | // | ||
199 | void move_container(swayc_t *container, enum movement_direction dir) { | 198 | void move_container(swayc_t *container, enum movement_direction dir) { |
200 | enum swayc_layouts layout; | 199 | enum swayc_layouts layout; |
201 | if (container->is_floating) { | 200 | if (container->is_floating) { |
@@ -210,37 +209,37 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
210 | } | 209 | } |
211 | swayc_t *parent = container->parent; | 210 | swayc_t *parent = container->parent; |
212 | swayc_t *child = container; | 211 | swayc_t *child = container; |
212 | bool ascended = false; | ||
213 | while (true) { | 213 | while (true) { |
214 | sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", | 214 | sway_log(L_DEBUG, "container:%p, parent:%p, child %p,", |
215 | container,parent,child); | 215 | container,parent,child); |
216 | if (parent->layout == layout) { | 216 | if (parent->layout == layout) { |
217 | int diff; | 217 | int diff; |
218 | // When child == container the container is removed, | 218 | // If it has ascended (parent has moved up), no container is removed |
219 | // so when inserting it back in, it needs to be -1, or 1 | 219 | // so insert it at index, or index+1. |
220 | // inserts at 1-1 or 1+1 | 220 | // if it has not, the moved container is removed, so it needs to be |
221 | // 0 1 2 3 => 0 1 2 => 0 1 2 3 or 0 1 2 3 | 221 | // inserted at index-1, or index+1 |
222 | // |0|1|2| => |0|2| => |1|0|2| or |0|2|1| | 222 | if (ascended) { |
223 | // When child != container, no container is removed | ||
224 | // inserts at 1+0 or 1+1 | ||
225 | // 0 1 2 3 => 0 1 2 3 4 or 0 1 2 3 4 | ||
226 | // |0|1|2| => |0|n|1|2| or |0|1|n|2| | ||
227 | if (child == container) { | ||
228 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; | ||
229 | } else { | ||
230 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; | 223 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? 0 : 1; |
224 | } else { | ||
225 | diff = dir == MOVE_LEFT || dir == MOVE_UP ? -1 : 1; | ||
231 | } | 226 | } |
232 | int desired = index_child(child) + diff; | 227 | int desired = index_child(child) + diff; |
233 | // Legal position | 228 | // when it has ascended, legal insertion position is 0:len |
234 | // when child == container, desired must be less then parent, | 229 | // when it has not, legal insertion position is 0:len-1 |
235 | // when child != container, desired can be equal to parent length | 230 | if (desired >= 0 && desired - ascended < parent->children->length) { |
236 | if (desired >= 0 && desired - (child != container) < parent->children->length) { | 231 | if (!ascended) { |
237 | // Case where we descend into a container | ||
238 | if (child == container) { | ||
239 | child = parent->children->items[desired]; | 232 | child = parent->children->items[desired]; |
240 | // Move container Into child container. | 233 | // Move container into sibling container |
241 | if (child->type == C_CONTAINER) { | 234 | if (child->type == C_CONTAINER) { |
242 | parent = child; | 235 | parent = child; |
243 | desired = index_child(child->focused); | 236 | // Insert it in first/last if matching layout,otherwise |
237 | // inesrt it next to focused container | ||
238 | if (parent->layout == layout) { | ||
239 | desired = (diff < 0) * parent->children->length; | ||
240 | } else { | ||
241 | desired = index_child(child->focused); | ||
242 | } | ||
244 | //reset geometry | 243 | //reset geometry |
245 | container->width = container->height = 0; | 244 | container->width = container->height = 0; |
246 | } | 245 | } |
@@ -252,12 +251,22 @@ void move_container(swayc_t *container, enum movement_direction dir) { | |||
252 | break; | 251 | break; |
253 | } | 252 | } |
254 | } | 253 | } |
254 | // Change parent layout if we need to | ||
255 | if (parent->children->length == 1 && parent->layout != layout) { | ||
256 | parent->layout = layout; | ||
257 | continue; | ||
258 | } | ||
259 | if (parent->type == C_WORKSPACE) { | ||
260 | // We simply cannot move any further. | ||
261 | if (parent->layout == layout) { | ||
262 | break; | ||
263 | } | ||
264 | // Create container around workspace to insert child into | ||
265 | parent = new_container(parent, layout); | ||
266 | } | ||
267 | ascended = true; | ||
255 | child = parent; | 268 | child = parent; |
256 | parent = child->parent; | 269 | parent = child->parent; |
257 | if (!parent || child->type == C_WORKSPACE) { | ||
258 | sway_log(L_DEBUG, "Failed to move container"); | ||
259 | return; | ||
260 | } | ||
261 | } | 270 | } |
262 | // Dirty hack to fix a certain case | 271 | // Dirty hack to fix a certain case |
263 | arrange_windows(parent, -1, -1); | 272 | arrange_windows(parent, -1, -1); |