diff options
Diffstat (limited to 'sway/focus.c')
-rw-r--r-- | sway/focus.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/sway/focus.c b/sway/focus.c new file mode 100644 index 00000000..14d27184 --- /dev/null +++ b/sway/focus.c | |||
@@ -0,0 +1,192 @@ | |||
1 | #include <wlc/wlc.h> | ||
2 | |||
3 | #include "focus.h" | ||
4 | #include "log.h" | ||
5 | #include "workspace.h" | ||
6 | |||
7 | bool locked_container_focus = false; | ||
8 | bool locked_view_focus = false; | ||
9 | |||
10 | //switches parent focus to c. will switch it accordingly | ||
11 | //TODO, everything needs a handle, so we can set front/back position properly | ||
12 | static void update_focus(swayc_t *c) { | ||
13 | //Handle if focus switches | ||
14 | swayc_t *parent = c->parent; | ||
15 | if (parent->focused != c) { | ||
16 | switch (c->type) { | ||
17 | case C_ROOT: return; | ||
18 | case C_OUTPUT: | ||
19 | wlc_output_focus(c->parent->handle); | ||
20 | break; | ||
21 | //switching workspaces | ||
22 | case C_WORKSPACE: | ||
23 | if (parent->focused) { | ||
24 | swayc_t *ws = parent->focused; | ||
25 | //hide visibility of old workspace | ||
26 | uint32_t mask = 1; | ||
27 | container_map(ws, set_view_visibility, &mask); | ||
28 | //set visibility of new workspace | ||
29 | mask = 2; | ||
30 | container_map(c, set_view_visibility, &mask); | ||
31 | wlc_output_set_mask(parent->handle, 2); | ||
32 | destroy_workspace(ws); | ||
33 | } | ||
34 | active_workspace = c; | ||
35 | break; | ||
36 | default: | ||
37 | case C_VIEW: | ||
38 | case C_CONTAINER: | ||
39 | //TODO whatever to do when container changes | ||
40 | //for example, stacked and tabbing change stuff. | ||
41 | break; | ||
42 | } | ||
43 | } | ||
44 | c->parent->focused = c; | ||
45 | } | ||
46 | |||
47 | bool move_focus(enum movement_direction direction) { | ||
48 | if (locked_container_focus) { | ||
49 | return false; | ||
50 | } | ||
51 | swayc_t *current = get_focused_container(&root_container); | ||
52 | swayc_t *parent = current->parent; | ||
53 | |||
54 | if (direction == MOVE_PARENT) { | ||
55 | if (parent->type == C_OUTPUT) { | ||
56 | sway_log(L_DEBUG, "Focus cannot move to parent"); | ||
57 | return false; | ||
58 | } else { | ||
59 | sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld", | ||
60 | current, current->handle, parent, parent->handle); | ||
61 | set_focused_container(parent); | ||
62 | return true; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | while (true) { | ||
67 | sway_log(L_DEBUG, "Moving focus away from %p", current); | ||
68 | |||
69 | // Test if we can even make a difference here | ||
70 | bool can_move = false; | ||
71 | int diff = 0; | ||
72 | if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { | ||
73 | if (parent->layout == L_HORIZ || parent->type == C_ROOT) { | ||
74 | can_move = true; | ||
75 | diff = direction == MOVE_LEFT ? -1 : 1; | ||
76 | } | ||
77 | } else { | ||
78 | if (parent->layout == L_VERT) { | ||
79 | can_move = true; | ||
80 | diff = direction == MOVE_UP ? -1 : 1; | ||
81 | } | ||
82 | } | ||
83 | sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); | ||
84 | if (can_move) { | ||
85 | int i; | ||
86 | for (i = 0; i < parent->children->length; ++i) { | ||
87 | swayc_t *child = parent->children->items[i]; | ||
88 | if (child == current) { | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | int desired = i + diff; | ||
93 | sway_log(L_DEBUG, "Moving from %d to %d", i, desired); | ||
94 | if (desired < 0 || desired >= parent->children->length) { | ||
95 | can_move = false; | ||
96 | } else { | ||
97 | swayc_t *newview = parent->children->items[desired]; | ||
98 | set_focused_container(get_focused_view(newview)); | ||
99 | return true; | ||
100 | } | ||
101 | } | ||
102 | if (!can_move) { | ||
103 | sway_log(L_DEBUG, "Can't move at current level, moving up tree"); | ||
104 | current = parent; | ||
105 | parent = parent->parent; | ||
106 | if (!parent) { | ||
107 | // Nothing we can do | ||
108 | return false; | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | swayc_t *get_focused_container(swayc_t *parent) { | ||
115 | while (parent && !parent->is_focused) { | ||
116 | parent = parent->focused; | ||
117 | } | ||
118 | //just incase | ||
119 | if (parent == NULL) { | ||
120 | sway_log(L_DEBUG, "get_focused_container unable to find container"); | ||
121 | return active_workspace; | ||
122 | } | ||
123 | return parent; | ||
124 | } | ||
125 | |||
126 | void set_focused_container(swayc_t *c) { | ||
127 | if (locked_container_focus || !c) { | ||
128 | return; | ||
129 | } | ||
130 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); | ||
131 | if (c->type != C_ROOT && c->type != C_OUTPUT) { | ||
132 | c->is_focused = true; | ||
133 | } | ||
134 | swayc_t *prev_view = get_focused_view(&root_container); | ||
135 | swayc_t *p = c; | ||
136 | while (p != &root_container) { | ||
137 | update_focus(p); | ||
138 | p = p->parent; | ||
139 | p->is_focused = false; | ||
140 | } | ||
141 | if (!locked_view_focus) { | ||
142 | p = get_focused_view(c); | ||
143 | //Set focus to p | ||
144 | if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | ||
145 | if (prev_view) { | ||
146 | wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); | ||
147 | } | ||
148 | wlc_view_focus(p->handle); | ||
149 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
154 | void set_focused_container_for(swayc_t *a, swayc_t *c) { | ||
155 | if (locked_container_focus || !c) { | ||
156 | return; | ||
157 | } | ||
158 | swayc_t *find = c; | ||
159 | //Ensure that a is an ancestor of c | ||
160 | while (find != a && (find = find->parent)) { | ||
161 | if (find == &root_container) { | ||
162 | return; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", | ||
167 | a, a->handle, c, c->handle); | ||
168 | |||
169 | c->is_focused = true; | ||
170 | swayc_t *p = c; | ||
171 | while (p != a) { | ||
172 | update_focus(p); | ||
173 | p = p->parent; | ||
174 | p->is_focused = false; | ||
175 | } | ||
176 | if (!locked_view_focus) { | ||
177 | p = get_focused_view(c); | ||
178 | //Set focus to p | ||
179 | if (p) { | ||
180 | wlc_view_focus(p->handle); | ||
181 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | |||
186 | swayc_t *get_focused_view(swayc_t *parent) { | ||
187 | while (parent && parent->type != C_VIEW) { | ||
188 | parent = parent->focused; | ||
189 | } | ||
190 | return parent; | ||
191 | } | ||
192 | |||