aboutsummaryrefslogtreecommitdiffstats
path: root/sway/movement.c
blob: a55d0350dc046adc7c9339774fd7037d2fd67c73 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdlib.h>
#include <stdbool.h>
#include "list.h"
#include "log.h"
#include "layout.h"
#include "movement.h"

int move_focus(enum movement_direction direction) {
	swayc_t *current = get_focused_container(&root_container);
	swayc_t *parent = current->parent;

	if (direction == MOVE_PARENT) {
		current = parent;
		parent  = parent->parent;
		if (parent->type == C_ROOT) {
			sway_log(L_DEBUG, "Focus cannot move to parent");
			return 1;
		} else {
			sway_log(L_DEBUG, "Moving focus away from %p", current);
			unfocus_all(parent);
			focus_view(parent);
			return 0;
		}
	}

	while (true) {
		sway_log(L_DEBUG, "Moving focus away from %p", current);

		// Test if we can even make a difference here
		bool can_move = false;
		int diff = 0;
		if (direction == MOVE_LEFT || direction == MOVE_RIGHT) {
			if (parent->layout == L_HORIZ) {
				can_move = true;
				diff = direction == MOVE_LEFT ? -1 : 1;
			}
		} else {
			if (parent->layout == L_VERT) {
				can_move = true;
				diff = direction == MOVE_UP ? -1 : 1;
			}
		}
		sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no");
		if (can_move) {
			int i;
			for (i = 0; i < parent->children->length; ++i) {
				swayc_t *child = parent->children->items[i];
				if (child == current) {
					break;
				}
			}
			int desired = i + diff;
			sway_log(L_DEBUG, "Moving from %d to %d", i, desired);
			if (desired < 0 || desired >= parent->children->length) {
				can_move = false;
			} else {
				unfocus_all(&root_container);
				focus_view(parent->children->items[desired]);
				return 0;
			}
		}
		if (!can_move) {
			sway_log(L_DEBUG, "Can't move at current level, moving up tree");
			current = parent;
			parent = parent->parent;
			if (parent->type == C_ROOT) {
				// Nothing we can do
				return 1;
			}
		}
	}
}