aboutsummaryrefslogtreecommitdiffstats
path: root/sway/tree/layout.c
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-25 12:09:42 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-25 12:09:42 +1000
commitf4bc25bcc6c822e264938447940b7d75fa84319b (patch)
treeb04befcfad9b7c679b1dec388d168901fc5daf86 /sway/tree/layout.c
parentMerge pull request #2499 from RyanDwyer/refactor-destroy-functions (diff)
downloadsway-f4bc25bcc6c822e264938447940b7d75fa84319b.tar.gz
sway-f4bc25bcc6c822e264938447940b7d75fa84319b.tar.zst
sway-f4bc25bcc6c822e264938447940b7d75fa84319b.zip
Relocate container_move, container_move_to and container_get_in_direction
* container_move is only called from the move command * container_move_to was called from both the move command and the sticky command, but the sticky command can easily not call it * container_get_in_direction is only called from the focus command Moving these functions to their respective commands gives better separation of code and removes bloat from layout.c. These functions will need to be refactored to take advantage of type safety, so separating them will make this easier to refactor. The following static functions have also been moved: * is_parellel * invert_movement * move_offs * container_limit * workspace_rejigger * move_out_of_tabs_stacks * get_swayc_in_output_direction They were all used by the move functions, except for the last one which is used by focus. Other changes: * index_child has been renamed to container_sibling_index, moved to container.c and made public * sway_output_from_wlr has been renamed to output_from_wlr_output, moved to output.c and made public * container_handle_fullscreen_reparent has been made public * sway_dir_to_wlr has been made public No changes have been made to any of the moved functions, other than updating calls to functions that have been renamed.
Diffstat (limited to 'sway/tree/layout.c')
-rw-r--r--sway/tree/layout.c627
1 files changed, 5 insertions, 622 deletions
diff --git a/sway/tree/layout.c b/sway/tree/layout.c
index 12e7342b..601d0e91 100644
--- a/sway/tree/layout.c
+++ b/sway/tree/layout.c
@@ -18,11 +18,7 @@
18#include "list.h" 18#include "list.h"
19#include "log.h" 19#include "log.h"
20 20
21static int index_child(const struct sway_container *child) { 21void container_handle_fullscreen_reparent(struct sway_container *con,
22 return list_find(child->parent->children, child);
23}
24
25static void container_handle_fullscreen_reparent(struct sway_container *con,
26 struct sway_container *old_parent) { 22 struct sway_container *old_parent) {
27 if (!con->is_fullscreen) { 23 if (!con->is_fullscreen) {
28 return; 24 return;
@@ -86,7 +82,7 @@ struct sway_container *container_add_sibling(struct sway_container *fixed,
86 container_remove_child(active); 82 container_remove_child(active);
87 } 83 }
88 struct sway_container *parent = fixed->parent; 84 struct sway_container *parent = fixed->parent;
89 int i = index_child(fixed); 85 int i = container_sibling_index(fixed);
90 list_insert(parent->children, i + 1, active); 86 list_insert(parent->children, i + 1, active);
91 active->parent = parent; 87 active->parent = parent;
92 container_handle_fullscreen_reparent(active, old_parent); 88 container_handle_fullscreen_reparent(active, old_parent);
@@ -130,97 +126,7 @@ struct sway_container *container_remove_child(struct sway_container *child) {
130 return parent; 126 return parent;
131} 127}
132 128
133void container_move_to(struct sway_container *container, 129bool sway_dir_to_wlr(enum movement_direction dir, enum wlr_direction *out) {
134 struct sway_container *destination) {
135 if (!sway_assert(container->type == C_CONTAINER ||
136 container->type == C_VIEW, "Expected a container or view")) {
137 return;
138 }
139 if (container == destination
140 || container_has_ancestor(container, destination)) {
141 return;
142 }
143 struct sway_container *old_parent = NULL;
144 struct sway_container *new_parent = NULL;
145 if (container_is_floating(container)) {
146 // Resolve destination into a workspace
147 struct sway_container *new_ws = NULL;
148 if (destination->type == C_OUTPUT) {
149 new_ws = output_get_active_workspace(destination->sway_output);
150 } else if (destination->type == C_WORKSPACE) {
151 new_ws = destination;
152 } else {
153 new_ws = container_parent(destination, C_WORKSPACE);
154 }
155 if (!new_ws) {
156 // This can happen if the user has run "move container to mark foo",
157 // where mark foo is on a hidden scratchpad container.
158 return;
159 }
160 struct sway_container *old_output =
161 container_parent(container, C_OUTPUT);
162 old_parent = container_remove_child(container);
163 workspace_add_floating(new_ws, container);
164 container_handle_fullscreen_reparent(container, old_parent);
165 // If changing output, center it within the workspace
166 if (old_output != new_ws->parent && !container->is_fullscreen) {
167 container_floating_move_to_center(container);
168 }
169 } else {
170 old_parent = container_remove_child(container);
171 container->width = container->height = 0;
172 container->saved_width = container->saved_height = 0;
173
174 if (destination->type == C_VIEW) {
175 new_parent = container_add_sibling(destination, container);
176 } else {
177 new_parent = destination;
178 container_add_child(destination, container);
179 }
180 }
181
182 if (container->type == C_VIEW) {
183 ipc_event_window(container, "move");
184 }
185 container_notify_subtree_changed(old_parent);
186 container_notify_subtree_changed(new_parent);
187
188 // If view was moved to a fullscreen workspace, refocus the fullscreen view
189 struct sway_container *new_workspace = container;
190 if (new_workspace->type != C_WORKSPACE) {
191 new_workspace = container_parent(new_workspace, C_WORKSPACE);
192 }
193 if (new_workspace->sway_workspace->fullscreen) {
194 struct sway_seat *seat;
195 struct sway_container *focus, *focus_ws;
196 wl_list_for_each(seat, &input_manager->seats, link) {
197 focus = seat_get_focus(seat);
198 focus_ws = focus;
199 if (focus_ws->type != C_WORKSPACE) {
200 focus_ws = container_parent(focus_ws, C_WORKSPACE);
201 }
202 if (focus_ws == new_workspace) {
203 struct sway_container *new_focus = seat_get_focus_inactive(seat,
204 new_workspace->sway_workspace->fullscreen);
205 seat_set_focus(seat, new_focus);
206 }
207 }
208 }
209 // Update workspace urgent state
210 struct sway_container *old_workspace = old_parent;
211 if (old_workspace->type != C_WORKSPACE) {
212 old_workspace = container_parent(old_workspace, C_WORKSPACE);
213 }
214 if (new_workspace != old_workspace) {
215 workspace_detect_urgent(new_workspace);
216 if (old_workspace) {
217 workspace_detect_urgent(old_workspace);
218 }
219 }
220}
221
222static bool sway_dir_to_wlr(enum movement_direction dir,
223 enum wlr_direction *out) {
224 switch (dir) { 130 switch (dir) {
225 case MOVE_UP: 131 case MOVE_UP:
226 *out = WLR_DIRECTION_UP; 132 *out = WLR_DIRECTION_UP;
@@ -241,323 +147,6 @@ static bool sway_dir_to_wlr(enum movement_direction dir,
241 return true; 147 return true;
242} 148}
243 149
244static bool is_parallel(enum sway_container_layout layout,
245 enum movement_direction dir) {
246 switch (layout) {
247 case L_TABBED:
248 case L_HORIZ:
249 return dir == MOVE_LEFT || dir == MOVE_RIGHT;
250 case L_STACKED:
251 case L_VERT:
252 return dir == MOVE_UP || dir == MOVE_DOWN;
253 default:
254 return false;
255 }
256}
257
258static enum movement_direction invert_movement(enum movement_direction dir) {
259 switch (dir) {
260 case MOVE_LEFT:
261 return MOVE_RIGHT;
262 case MOVE_RIGHT:
263 return MOVE_LEFT;
264 case MOVE_UP:
265 return MOVE_DOWN;
266 case MOVE_DOWN:
267 return MOVE_UP;
268 default:
269 sway_assert(0, "This function expects left|right|up|down");
270 return MOVE_LEFT;
271 }
272}
273
274static int move_offs(enum movement_direction move_dir) {
275 return move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1;
276}
277
278/* Gets the index of the most extreme member based on the movement offset */
279static int container_limit(struct sway_container *container,
280 enum movement_direction move_dir) {
281 return move_offs(move_dir) < 0 ? 0 : container->children->length;
282}
283
284/* Takes one child, sets it aside, wraps the rest of the children in a new
285 * container, switches the layout of the workspace, and drops the child back in.
286 * In other words, rejigger it. */
287static void workspace_rejigger(struct sway_container *ws,
288 struct sway_container *child, enum movement_direction move_dir) {
289 struct sway_container *original_parent = child->parent;
290 struct sway_container *new_parent =
291 container_split(ws, ws->layout);
292
293 container_remove_child(child);
294 for (int i = 0; i < ws->children->length; ++i) {
295 struct sway_container *_child = ws->children->items[i];
296 container_move_to(new_parent, _child);
297 }
298
299 int index = move_offs(move_dir);
300 container_insert_child(ws, child, index < 0 ? 0 : 1);
301 ws->layout =
302 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
303
304 container_flatten(ws);
305 container_reap_empty(original_parent);
306 container_create_notify(new_parent);
307}
308
309static void move_out_of_tabs_stacks(struct sway_container *container,
310 struct sway_container *current, enum movement_direction move_dir,
311 int offs) {
312 if (container->parent == current->parent
313 && current->parent->children->length == 1) {
314 wlr_log(WLR_DEBUG, "Changing layout of %zd", current->parent->id);
315 current->parent->layout = move_dir ==
316 MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT;
317 return;
318 }
319
320 wlr_log(WLR_DEBUG, "Moving out of tab/stack into a split");
321 bool is_workspace = current->parent->type == C_WORKSPACE;
322 struct sway_container *new_parent = container_split(current->parent,
323 move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT);
324 if (is_workspace) {
325 container_insert_child(new_parent->parent, container, offs < 0 ? 0 : 1);
326 } else {
327 container_insert_child(new_parent, container, offs < 0 ? 0 : 1);
328 container_reap_empty(new_parent->parent);
329 container_flatten(new_parent->parent);
330 }
331 container_create_notify(new_parent);
332 container_notify_subtree_changed(new_parent);
333}
334
335void container_move(struct sway_container *container,
336 enum movement_direction move_dir, int move_amt) {
337 if (!sway_assert(
338 container->type != C_CONTAINER || container->type != C_VIEW,
339 "Can only move containers and views")) {
340 return;
341 }
342 int offs = move_offs(move_dir);
343
344 struct sway_container *sibling = NULL;
345 struct sway_container *current = container;
346 struct sway_container *parent = current->parent;
347 struct sway_container *top = &root_container;
348
349 // If moving a fullscreen view, only consider outputs
350 if (container->is_fullscreen) {
351 current = container_parent(container, C_OUTPUT);
352 } else if (container_is_fullscreen_or_child(container) ||
353 container_is_floating_or_child(container)) {
354 // If we've fullscreened a split container, only allow the child to move
355 // around within the fullscreen parent.
356 // Same with floating a split container.
357 struct sway_container *ws = container_parent(container, C_WORKSPACE);
358 top = ws->sway_workspace->fullscreen;
359 }
360
361 struct sway_container *new_parent = container_flatten(parent);
362 if (new_parent != parent) {
363 // Special case: we were the last one in this container, so leave
364 return;
365 }
366
367 while (!sibling) {
368 if (current == top) {
369 return;
370 }
371
372 parent = current->parent;
373 wlr_log(WLR_DEBUG, "Visiting %p %s '%s'", current,
374 container_type_to_str(current->type), current->name);
375
376 int index = index_child(current);
377
378 switch (current->type) {
379 case C_OUTPUT: {
380 enum wlr_direction wlr_dir = 0;
381 if (!sway_assert(sway_dir_to_wlr(move_dir, &wlr_dir),
382 "got invalid direction: %d", move_dir)) {
383 return;
384 }
385 double ref_lx = current->x + current->width / 2;
386 double ref_ly = current->y + current->height / 2;
387 struct wlr_output *next = wlr_output_layout_adjacent_output(
388 root_container.sway_root->output_layout, wlr_dir,
389 current->sway_output->wlr_output, ref_lx, ref_ly);
390 if (!next) {
391 wlr_log(WLR_DEBUG, "Hit edge of output, nowhere else to go");
392 return;
393 }
394 struct sway_output *next_output = next->data;
395 current = next_output->swayc;
396 wlr_log(WLR_DEBUG, "Selected next output (%s)", current->name);
397 // Select workspace and get outta here
398 current = seat_get_focus_inactive(
399 config->handler_context.seat, current);
400 if (current->type != C_WORKSPACE) {
401 current = container_parent(current, C_WORKSPACE);
402 }
403 sibling = current;
404 break;
405 }
406 case C_WORKSPACE:
407 if (!is_parallel(current->layout, move_dir)) {
408 if (current->children->length >= 2) {
409 wlr_log(WLR_DEBUG, "Rejiggering the workspace (%d kiddos)",
410 current->children->length);
411 workspace_rejigger(current, container, move_dir);
412 return;
413 } else {
414 wlr_log(WLR_DEBUG, "Selecting output");
415 current = current->parent;
416 }
417 } else if (current->layout == L_TABBED
418 || current->layout == L_STACKED) {
419 wlr_log(WLR_DEBUG, "Rejiggering out of tabs/stacks");
420 workspace_rejigger(current, container, move_dir);
421 } else {
422 wlr_log(WLR_DEBUG, "Selecting output");
423 current = current->parent;
424 }
425 break;
426 case C_CONTAINER:
427 case C_VIEW:
428 if (is_parallel(parent->layout, move_dir)) {
429 if ((index == parent->children->length - 1 && offs > 0)
430 || (index == 0 && offs < 0)) {
431 if (current->parent == container->parent) {
432 if (!parent->is_fullscreen &&
433 (parent->layout == L_TABBED ||
434 parent->layout == L_STACKED)) {
435 move_out_of_tabs_stacks(container, current,
436 move_dir, offs);
437 return;
438 } else {
439 wlr_log(WLR_DEBUG, "Hit limit, selecting parent");
440 current = current->parent;
441 }
442 } else {
443 wlr_log(WLR_DEBUG, "Hit limit, "
444 "promoting descendant to sibling");
445 // Special case
446 container_insert_child(current->parent, container,
447 index + (offs < 0 ? 0 : 1));
448 container->width = container->height = 0;
449 return;
450 }
451 } else {
452 sibling = parent->children->items[index + offs];
453 wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id);
454 }
455 } else if (!parent->is_fullscreen && (parent->layout == L_TABBED ||
456 parent->layout == L_STACKED)) {
457 move_out_of_tabs_stacks(container, current, move_dir, offs);
458 return;
459 } else {
460 wlr_log(WLR_DEBUG, "Moving up to find a parallel container");
461 current = current->parent;
462 }
463 break;
464 default:
465 sway_assert(0, "Not expecting to see container of type %s here",
466 container_type_to_str(current->type));
467 return;
468 }
469 }
470
471 // Part two: move stuff around
472 int index = index_child(container);
473 struct sway_container *old_parent = container->parent;
474
475 while (sibling) {
476 switch (sibling->type) {
477 case C_VIEW:
478 if (sibling->parent == container->parent) {
479 wlr_log(WLR_DEBUG, "Swapping siblings");
480 sibling->parent->children->items[index + offs] = container;
481 sibling->parent->children->items[index] = sibling;
482 } else {
483 wlr_log(WLR_DEBUG, "Promoting to sibling of cousin");
484 container_insert_child(sibling->parent, container,
485 index_child(sibling) + (offs > 0 ? 0 : 1));
486 container->width = container->height = 0;
487 }
488 sibling = NULL;
489 break;
490 case C_WORKSPACE: // Note: only in the case of moving between outputs
491 case C_CONTAINER:
492 if (is_parallel(sibling->layout, move_dir)) {
493 int limit = container_limit(sibling, invert_movement(move_dir));
494 wlr_log(WLR_DEBUG, "limit: %d", limit);
495 wlr_log(WLR_DEBUG,
496 "Reparenting container (parallel) to index %d "
497 "(move dir: %d)", limit, move_dir);
498 container_insert_child(sibling, container, limit);
499 container->width = container->height = 0;
500 sibling = NULL;
501 } else {
502 wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)");
503 struct sway_container *focus_inactive = seat_get_focus_inactive(
504 config->handler_context.seat, sibling);
505 if (focus_inactive && focus_inactive != sibling) {
506 while (focus_inactive->parent != sibling) {
507 focus_inactive = focus_inactive->parent;
508 }
509 wlr_log(WLR_DEBUG, "Focus inactive: id:%zd",
510 focus_inactive->id);
511 sibling = focus_inactive;
512 continue;
513 } else if (sibling->children->length) {
514 wlr_log(WLR_DEBUG, "No focus-inactive, adding arbitrarily");
515 container_remove_child(container);
516 container_add_sibling(sibling->children->items[0], container);
517 } else {
518 wlr_log(WLR_DEBUG, "No kiddos, adding container alone");
519 container_remove_child(container);
520 container_add_child(sibling, container);
521 }
522 container->width = container->height = 0;
523 sibling = NULL;
524 }
525 break;
526 default:
527 sway_assert(0, "Not expecting to see container of type %s here",
528 container_type_to_str(sibling->type));
529 return;
530 }
531 }
532
533 container_notify_subtree_changed(old_parent);
534 container_notify_subtree_changed(container->parent);
535
536 if (container->type == C_VIEW) {
537 ipc_event_window(container, "move");
538 }
539
540 if (old_parent) {
541 seat_set_focus(config->handler_context.seat, old_parent);
542 seat_set_focus(config->handler_context.seat, container);
543 }
544
545 struct sway_container *last_ws = old_parent;
546 struct sway_container *next_ws = container->parent;
547 if (last_ws && last_ws->type != C_WORKSPACE) {
548 last_ws = container_parent(last_ws, C_WORKSPACE);
549 }
550 if (next_ws && next_ws->type != C_WORKSPACE) {
551 next_ws = container_parent(next_ws, C_WORKSPACE);
552 }
553 if (last_ws && next_ws && last_ws != next_ws) {
554 ipc_event_workspace(last_ws, next_ws, "focus");
555 workspace_detect_urgent(last_ws);
556 workspace_detect_urgent(next_ws);
557 }
558 container_end_mouse_operation(container);
559}
560
561enum sway_container_layout container_get_default_layout( 150enum sway_container_layout container_get_default_layout(
562 struct sway_container *con) { 151 struct sway_container *con) {
563 if (con->type != C_OUTPUT) { 152 if (con->type != C_OUTPUT) {
@@ -581,212 +170,6 @@ enum sway_container_layout container_get_default_layout(
581 } 170 }
582} 171}
583 172
584/**
585 * Get swayc in the direction of newly entered output.
586 */
587static struct sway_container *get_swayc_in_output_direction(
588 struct sway_container *output, enum movement_direction dir,
589 struct sway_seat *seat) {
590 if (!output) {
591 return NULL;
592 }
593
594 struct sway_container *ws = seat_get_focus_inactive(seat, output);
595 if (ws->type != C_WORKSPACE) {
596 ws = container_parent(ws, C_WORKSPACE);
597 }
598
599 if (ws == NULL) {
600 wlr_log(WLR_ERROR, "got an output without a workspace");
601 return NULL;
602 }
603
604 if (ws->children->length > 0) {
605 switch (dir) {
606 case MOVE_LEFT:
607 if (ws->layout == L_HORIZ || ws->layout == L_TABBED) {
608 // get most right child of new output
609 return ws->children->items[ws->children->length-1];
610 } else {
611 return seat_get_focus_inactive(seat, ws);
612 }
613 case MOVE_RIGHT:
614 if (ws->layout == L_HORIZ || ws->layout == L_TABBED) {
615 // get most left child of new output
616 return ws->children->items[0];
617 } else {
618 return seat_get_focus_inactive(seat, ws);
619 }
620 case MOVE_UP:
621 case MOVE_DOWN: {
622 struct sway_container *focused =
623 seat_get_focus_inactive(seat, ws);
624 if (focused && focused->parent) {
625 struct sway_container *parent = focused->parent;
626 if (parent->layout == L_VERT) {
627 if (dir == MOVE_UP) {
628 // get child furthest down on new output
629 int idx = parent->children->length - 1;
630 return parent->children->items[idx];
631 } else if (dir == MOVE_DOWN) {
632 // get child furthest up on new output
633 return parent->children->items[0];
634 }
635 }
636 return focused;
637 }
638 break;
639 }
640 default:
641 break;
642 }
643 }
644
645 return ws;
646}
647
648static struct sway_container *sway_output_from_wlr(struct wlr_output *output) {
649 if (output == NULL) {
650 return NULL;
651 }
652 for (int i = 0; i < root_container.children->length; ++i) {
653 struct sway_container *o = root_container.children->items[i];
654 if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) {
655 return o;
656 }
657 }
658 return NULL;
659}
660
661struct sway_container *container_get_in_direction(
662 struct sway_container *container, struct sway_seat *seat,
663 enum movement_direction dir) {
664 struct sway_container *parent = container->parent;
665
666 if (dir == MOVE_CHILD) {
667 return seat_get_focus_inactive(seat, container);
668 }
669 if (container->is_fullscreen) {
670 if (dir == MOVE_PARENT) {
671 return NULL;
672 }
673 container = container_parent(container, C_OUTPUT);
674 parent = container->parent;
675 } else {
676 if (dir == MOVE_PARENT) {
677 if (parent->type == C_OUTPUT || container_is_floating(container)) {
678 return NULL;
679 } else {
680 return parent;
681 }
682 }
683 }
684
685 struct sway_container *wrap_candidate = NULL;
686 while (true) {
687 bool can_move = false;
688 int desired;
689 int idx = index_child(container);
690 if (idx == -1) {
691 return NULL;
692 }
693 if (parent->type == C_ROOT) {
694 enum wlr_direction wlr_dir = 0;
695 if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir),
696 "got invalid direction: %d", dir)) {
697 return NULL;
698 }
699 int lx = container->x + container->width / 2;
700 int ly = container->y + container->height / 2;
701 struct wlr_output_layout *layout =
702 root_container.sway_root->output_layout;
703 struct wlr_output *wlr_adjacent =
704 wlr_output_layout_adjacent_output(layout, wlr_dir,
705 container->sway_output->wlr_output, lx, ly);
706 struct sway_container *adjacent =
707 sway_output_from_wlr(wlr_adjacent);
708
709 if (!adjacent || adjacent == container) {
710 if (!wrap_candidate) {
711 return NULL;
712 }
713 return seat_get_focus_inactive_view(seat, wrap_candidate);
714 }
715 struct sway_container *next =
716 get_swayc_in_output_direction(adjacent, dir, seat);
717 if (next == NULL) {
718 return NULL;
719 }
720 struct sway_container *next_workspace = next;
721 if (next_workspace->type != C_WORKSPACE) {
722 next_workspace = container_parent(next_workspace, C_WORKSPACE);
723 }
724 sway_assert(next_workspace, "Next container has no workspace");
725 if (next_workspace->sway_workspace->fullscreen) {
726 return seat_get_focus_inactive(seat,
727 next_workspace->sway_workspace->fullscreen);
728 }
729 if (next->children && next->children->length) {
730 // TODO consider floating children as well
731 return seat_get_focus_inactive_view(seat, next);
732 } else {
733 return next;
734 }
735 } else {
736 if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
737 if (parent->layout == L_HORIZ || parent->layout == L_TABBED) {
738 can_move = true;
739 desired = idx + (dir == MOVE_LEFT ? -1 : 1);
740 }
741 } else {
742 if (parent->layout == L_VERT || parent->layout == L_STACKED) {
743 can_move = true;
744 desired = idx + (dir == MOVE_UP ? -1 : 1);
745 }
746 }
747 }
748
749 if (can_move) {
750 // TODO handle floating
751 if (desired < 0 || desired >= parent->children->length) {
752 can_move = false;
753 int len = parent->children->length;
754 if (config->focus_wrapping != WRAP_NO && !wrap_candidate
755 && len > 1) {
756 if (desired < 0) {
757 wrap_candidate = parent->children->items[len-1];
758 } else {
759 wrap_candidate = parent->children->items[0];
760 }
761 if (config->focus_wrapping == WRAP_FORCE) {
762 return seat_get_focus_inactive_view(seat,
763 wrap_candidate);
764 }
765 }
766 } else {
767 struct sway_container *desired_con =
768 parent->children->items[desired];
769 wlr_log(WLR_DEBUG,
770 "cont %d-%p dir %i sibling %d: %p", idx,
771 container, dir, desired, desired_con);
772 return seat_get_focus_inactive_view(seat, desired_con);
773 }
774 }
775
776 if (!can_move) {
777 container = parent;
778 parent = parent->parent;
779 if (!parent) {
780 // wrapping is the last chance
781 if (!wrap_candidate) {
782 return NULL;
783 }
784 return seat_get_focus_inactive_view(seat, wrap_candidate);
785 }
786 }
787 }
788}
789
790struct sway_container *container_replace_child(struct sway_container *child, 173struct sway_container *container_replace_child(struct sway_container *child,
791 struct sway_container *new_child) { 174 struct sway_container *new_child) {
792 struct sway_container *parent = child->parent; 175 struct sway_container *parent = child->parent;
@@ -915,8 +298,8 @@ static void swap_places(struct sway_container *con1,
915 con2->width = temp->width; 298 con2->width = temp->width;
916 con2->height = temp->height; 299 con2->height = temp->height;
917 300
918 int temp_index = index_child(con1); 301 int temp_index = container_sibling_index(con1);
919 container_insert_child(con2->parent, con1, index_child(con2)); 302 container_insert_child(con2->parent, con1, container_sibling_index(con2));
920 container_insert_child(temp->parent, con2, temp_index); 303 container_insert_child(temp->parent, con2, temp_index);
921 304
922 free(temp); 305 free(temp);