diff options
Diffstat (limited to 'sway/focus.c')
-rw-r--r-- | sway/focus.c | 79 |
1 files changed, 58 insertions, 21 deletions
diff --git a/sway/focus.c b/sway/focus.c index 99cb2570..628316dd 100644 --- a/sway/focus.c +++ b/sway/focus.c | |||
@@ -14,11 +14,15 @@ static void update_focus(swayc_t *c) { | |||
14 | swayc_t *parent = c->parent; | 14 | swayc_t *parent = c->parent; |
15 | if (parent->focused != c) { | 15 | if (parent->focused != c) { |
16 | switch (c->type) { | 16 | switch (c->type) { |
17 | // Shouldnt happen | ||
17 | case C_ROOT: return; | 18 | case C_ROOT: return; |
19 | |||
20 | // Case where output changes | ||
18 | case C_OUTPUT: | 21 | case C_OUTPUT: |
19 | wlc_output_focus(c->parent->handle); | 22 | wlc_output_focus(c->handle); |
20 | break; | 23 | break; |
21 | // switching workspaces | 24 | |
25 | // Case where workspace changes | ||
22 | case C_WORKSPACE: | 26 | case C_WORKSPACE: |
23 | if (parent->focused) { | 27 | if (parent->focused) { |
24 | swayc_t *ws = parent->focused; | 28 | swayc_t *ws = parent->focused; |
@@ -29,10 +33,12 @@ static void update_focus(swayc_t *c) { | |||
29 | mask = 2; | 33 | mask = 2; |
30 | container_map(c, set_view_visibility, &mask); | 34 | container_map(c, set_view_visibility, &mask); |
31 | wlc_output_set_mask(parent->handle, 2); | 35 | wlc_output_set_mask(parent->handle, 2); |
36 | c->parent->focused = c; | ||
32 | destroy_workspace(ws); | 37 | destroy_workspace(ws); |
33 | } | 38 | } |
34 | active_workspace = c; | 39 | active_workspace = c; |
35 | break; | 40 | break; |
41 | |||
36 | default: | 42 | default: |
37 | case C_VIEW: | 43 | case C_VIEW: |
38 | case C_CONTAINER: | 44 | case C_CONTAINER: |
@@ -49,6 +55,10 @@ bool move_focus(enum movement_direction direction) { | |||
49 | return false; | 55 | return false; |
50 | } | 56 | } |
51 | swayc_t *current = get_focused_container(&root_container); | 57 | swayc_t *current = get_focused_container(&root_container); |
58 | if (current->type == C_VIEW | ||
59 | && wlc_view_get_state(current->handle) & WLC_BIT_FULLSCREEN) { | ||
60 | return false; | ||
61 | } | ||
52 | swayc_t *parent = current->parent; | 62 | swayc_t *parent = current->parent; |
53 | 63 | ||
54 | if (direction == MOVE_PARENT) { | 64 | if (direction == MOVE_PARENT) { |
@@ -128,23 +138,39 @@ void set_focused_container(swayc_t *c) { | |||
128 | return; | 138 | return; |
129 | } | 139 | } |
130 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); | 140 | sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); |
131 | if (c->type != C_ROOT && c->type != C_OUTPUT) { | 141 | |
132 | c->is_focused = true; | 142 | // Find previous focused view, and the new focused view, if they are the same return |
143 | swayc_t *focused = get_focused_view(&root_container); | ||
144 | swayc_t *workspace = active_workspace; | ||
145 | if (focused == get_focused_view(c)) { | ||
146 | return; | ||
133 | } | 147 | } |
134 | swayc_t *prev_view = get_focused_view(&root_container); | 148 | |
149 | // update container focus from here to root, making necessary changes along | ||
150 | // the way | ||
135 | swayc_t *p = c; | 151 | swayc_t *p = c; |
136 | while (p != &root_container) { | 152 | while (p != &root_container) { |
137 | update_focus(p); | 153 | update_focus(p); |
138 | p = p->parent; | 154 | p = p->parent; |
139 | p->is_focused = false; | 155 | p->is_focused = false; |
140 | } | 156 | } |
141 | if (!locked_view_focus) { | 157 | |
142 | p = get_focused_view(c); | 158 | // if the workspace is the same, and previous focus is fullscreen, dont |
143 | // Set focus to p | 159 | // change focus |
144 | if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | 160 | if (workspace == active_workspace |
145 | if (prev_view) { | 161 | && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { |
146 | wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); | 162 | return; |
147 | } | 163 | } |
164 | |||
165 | // get new focused view and set focus to it. | ||
166 | p = get_focused_view(c); | ||
167 | if (p->type == C_VIEW && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { | ||
168 | // unactivate previous focus | ||
169 | if (focused->type == C_VIEW) { | ||
170 | wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); | ||
171 | } | ||
172 | // activate current focus | ||
173 | if (p->type == C_VIEW) { | ||
148 | wlc_view_focus(p->handle); | 174 | wlc_view_focus(p->handle); |
149 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); | 175 | wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); |
150 | } | 176 | } |
@@ -156,12 +182,25 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { | |||
156 | return; | 182 | return; |
157 | } | 183 | } |
158 | swayc_t *find = c; | 184 | swayc_t *find = c; |
159 | //Ensure that a is an ancestor of c | 185 | // Ensure that a is an ancestor of c |
160 | while (find != a && (find = find->parent)) { | 186 | while (find != a && (find = find->parent)) { |
161 | if (find == &root_container) { | 187 | if (find == &root_container) { |
162 | return; | 188 | return; |
163 | } | 189 | } |
164 | } | 190 | } |
191 | // Check if we changing a parent container that will see chnage | ||
192 | bool effective = true; | ||
193 | while (find != &root_container) { | ||
194 | if (find->parent->focused != find) { | ||
195 | effective = false; | ||
196 | } | ||
197 | find = find->parent; | ||
198 | } | ||
199 | if (effective) { | ||
200 | // Go to set_focused_container | ||
201 | set_focused_container(c); | ||
202 | return; | ||
203 | } | ||
165 | 204 | ||
166 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", | 205 | sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", |
167 | a, a->handle, c, c->handle); | 206 | a, a->handle, c, c->handle); |
@@ -173,19 +212,17 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { | |||
173 | p = p->parent; | 212 | p = p->parent; |
174 | p->is_focused = false; | 213 | p->is_focused = false; |
175 | } | 214 | } |
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 | } | 215 | } |
185 | 216 | ||
186 | swayc_t *get_focused_view(swayc_t *parent) { | 217 | swayc_t *get_focused_view(swayc_t *parent) { |
187 | while (parent && parent->type != C_VIEW) { | 218 | while (parent && parent->type != C_VIEW) { |
219 | if (parent->type == C_WORKSPACE && parent->focused == NULL) { | ||
220 | return parent; | ||
221 | } | ||
188 | parent = parent->focused; | 222 | parent = parent->focused; |
189 | } | 223 | } |
224 | if (parent == NULL) { | ||
225 | return active_workspace; | ||
226 | } | ||
190 | return parent; | 227 | return parent; |
191 | } | 228 | } |