summaryrefslogtreecommitdiffstats
path: root/sway/focus.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/focus.c')
-rw-r--r--sway/focus.c79
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
186swayc_t *get_focused_view(swayc_t *parent) { 217swayc_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}