summaryrefslogtreecommitdiffstats
path: root/sway/handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/handlers.c')
-rw-r--r--sway/handlers.c235
1 files changed, 128 insertions, 107 deletions
diff --git a/sway/handlers.c b/sway/handlers.c
index e17aefee..99f597af 100644
--- a/sway/handlers.c
+++ b/sway/handlers.c
@@ -3,18 +3,18 @@
3#include <stdbool.h> 3#include <stdbool.h>
4#include <wlc/wlc.h> 4#include <wlc/wlc.h>
5#include <ctype.h> 5#include <ctype.h>
6#include "layout.h" 6
7#include "handlers.h"
7#include "log.h" 8#include "log.h"
9#include "layout.h"
8#include "config.h" 10#include "config.h"
9#include "commands.h" 11#include "commands.h"
10#include "handlers.h"
11#include "stringop.h" 12#include "stringop.h"
12#include "workspace.h" 13#include "workspace.h"
13#include "container.h" 14#include "container.h"
15#include "focus.h"
14 16
15static struct wlc_origin mouse_origin; 17static struct wlc_origin mouse_origin;
16//Keyboard input is being overrided by window (dmenu)
17static bool override_redirect = false;
18 18
19static bool pointer_test(swayc_t *view, void *_origin) { 19static bool pointer_test(swayc_t *view, void *_origin) {
20 const struct wlc_origin *origin = _origin; 20 const struct wlc_origin *origin = _origin;
@@ -23,27 +23,57 @@ static bool pointer_test(swayc_t *view, void *_origin) {
23 while (parent->type != C_OUTPUT) { 23 while (parent->type != C_OUTPUT) {
24 parent = parent->parent; 24 parent = parent->parent;
25 } 25 }
26 if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y 26 if (origin->x >= view->x && origin->y >= view->y
27 && origin->x < view->x + view->width && origin->y < view->y + view->height 27 && origin->x < view->x + view->width && origin->y < view->y + view->height
28 && view->visible && parent == root_container.focused) { 28 && view->visible && parent == root_container.focused) {
29 return true; 29 return true;
30 } 30 }
31 return false; 31 return false;
32} 32}
33 33
34swayc_t *focus_pointer(void) { 34swayc_t *container_under_pointer(void) {
35 swayc_t *focused = get_focused_container(&root_container); 35 //root.output->workspace
36 if (!(wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)) { 36 swayc_t *lookup = root_container.focused->focused;
37 swayc_t *pointer = find_container(&root_container, pointer_test, &mouse_origin); 37 //Case of empty workspace
38 if (pointer && focused != pointer) { 38 if (lookup->children == 0) {
39 unfocus_all(&root_container); 39 return NULL;
40 focus_view(pointer); 40 }
41 } else if (!focused) { 41 while (lookup->type != C_VIEW) {
42 focus_view(active_workspace); 42 int i;
43 int len;
44 //if tabbed/stacked go directly to focused container, otherwise search
45 //children
46 if (lookup->layout == L_TABBED || lookup->layout == L_STACKED) {
47 lookup = lookup->focused;
48 continue;
49 }
50 //if workspace, search floating
51 if (lookup->type == C_WORKSPACE) {
52 len = lookup->floating->length;
53 for (i = 0; i < len; ++i) {
54 if (pointer_test(lookup->floating->items[i], &mouse_origin)) {
55 lookup = lookup->floating->items[i];
56 break;
57 }
58 }
59 if (i < len) {
60 continue;
61 }
62 }
63 //search children
64 len = lookup->children->length;
65 for (i = 0; i < len; ++i) {
66 if (pointer_test(lookup->children->items[i], &mouse_origin)) {
67 lookup = lookup->children->items[i];
68 break;
69 }
70 }
71 //when border and titles are done, this could happen
72 if (i == len) {
73 break;
43 } 74 }
44 focused = pointer;
45 } 75 }
46 return focused; 76 return lookup;
47} 77}
48 78
49static bool handle_output_created(wlc_handle output) { 79static bool handle_output_created(wlc_handle output) {
@@ -81,90 +111,79 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_
81 111
82static void handle_output_focused(wlc_handle output, bool focus) { 112static void handle_output_focused(wlc_handle output, bool focus) {
83 swayc_t *c = get_swayc_for_handle(output, &root_container); 113 swayc_t *c = get_swayc_for_handle(output, &root_container);
84 if (!c) return; 114 //if for some reason this output doesnt exist, create it.
115 if (!c) {
116 handle_output_created(output);
117 }
85 if (focus) { 118 if (focus) {
86 unfocus_all(&root_container); 119 set_focused_container(c);
87 focus_view(c);
88 } 120 }
89} 121}
90 122
91static bool handle_view_created(wlc_handle handle) { 123static bool handle_view_created(wlc_handle handle) {
92 swayc_t *focused = get_focused_container(&root_container); 124 swayc_t *focused = get_focused_container(&root_container);
93 uint32_t type = wlc_view_get_type(handle); 125 swayc_t *newview = NULL;
94 // If override_redirect/unmanaged/popup/modal/splach 126 switch (wlc_view_get_type(handle)) {
95 if (type) { 127 //regular view created regularly
96 sway_log(L_DEBUG,"Unmanaged window of type %x left alone", type); 128 case 0:
97 wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); 129 newview = new_view(focused, handle);
98 if (type & WLC_BIT_UNMANAGED) {
99 return true;
100 }
101 // For things like Dmenu
102 if (type & WLC_BIT_OVERRIDE_REDIRECT) {
103 override_redirect = true;
104 wlc_view_focus(handle);
105 }
106
107 // Float popups
108 if (type & WLC_BIT_POPUP) {
109 swayc_t *view = new_floating_view(handle);
110 wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, false);
111 focus_view(view);
112 arrange_windows(active_workspace, -1, -1);
113 }
114 } else {
115 swayc_t *view = new_view(focused, handle);
116 //Set maximize flag for windows.
117 //TODO: floating windows have this unset
118 wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true); 130 wlc_view_set_state(handle, WLC_BIT_MAXIMIZED, true);
119 unfocus_all(&root_container); 131 break;
120 focus_view(view); 132 //takes keyboard focus
121 arrange_windows(view->parent, -1, -1); 133 case WLC_BIT_OVERRIDE_REDIRECT:
134 sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT", handle);
135 locked_view_focus = true;
136 wlc_view_focus(handle);
137 wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
138 wlc_view_bring_to_front(handle);
139 break;
140 //Takes container focus
141 case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
142 sway_log(L_DEBUG, "view %ld with OVERRIDE_REDIRECT|WLC_BIT_MANAGED", handle);
143 wlc_view_bring_to_front(handle);
144 locked_container_focus = true;
145 break;
146 //set modals as floating containers
147 case WLC_BIT_POPUP:
148 case WLC_BIT_MODAL:
149 wlc_view_bring_to_front(handle);
150 newview = new_floating_view(handle);
151 break;
122 } 152 }
123 if (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { 153 if (newview) {
124 unfocus_all(&root_container); 154 set_focused_container(newview);
125 focus_view(focused); 155 arrange_windows(newview->parent, -1, -1);
126 arrange_windows(focused, -1, -1);
127 } 156 }
128 return true; 157 return true;
129} 158}
130 159
131static void handle_view_destroyed(wlc_handle handle) { 160static void handle_view_destroyed(wlc_handle handle) {
132 sway_log(L_DEBUG, "Destroying window %u", (unsigned int)handle); 161 sway_log(L_DEBUG, "Destroying window %lu", handle);
133
134 // Properly handle unmanaged views
135 uint32_t type = wlc_view_get_type(handle);
136 if (type) {
137 wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true);
138 sway_log(L_DEBUG,"Unmanaged window of type %x was destroyed", type);
139 if (type & WLC_BIT_UNMANAGED) {
140 // We need to call focus_view() on focus_pointer because unmanaged windows
141 // do not alter the focus structure of the container tree. This makes focus_pointer()
142 // think that it doesn't need to do anything, so we manually focus the result.
143 focus_view(focus_pointer());
144 return;
145 }
146
147 if (type & WLC_BIT_OVERRIDE_REDIRECT) {
148 override_redirect = false;
149 focus_view(focus_pointer());
150 return;
151 }
152
153 // WLC_BIT_POPUP doesn't need to be dealt with since it's
154 // treated as a floating view.
155 }
156
157 swayc_t *view = get_swayc_for_handle(handle, &root_container); 162 swayc_t *view = get_swayc_for_handle(handle, &root_container);
158 swayc_t *parent;
159 swayc_t *focused = get_focused_container(&root_container); 163 swayc_t *focused = get_focused_container(&root_container);
160 164
161 if (view) { 165 switch (wlc_view_get_type(handle)) {
162 parent = destroy_view(view); 166 //regular view created regularly
163 arrange_windows(parent, -1, -1); 167 case 0:
164 } 168 case WLC_BIT_MODAL:
165 if (!focused || focused == view) { 169 case WLC_BIT_POPUP:
166 focus_pointer(); 170 if (view) {
171 arrange_windows(destroy_view(view), -1, -1);
172 if (!focused || focused == view) {
173 set_focused_container(container_under_pointer());
174 }
175 }
176 break;
177 //takes keyboard focus
178 case WLC_BIT_OVERRIDE_REDIRECT:
179 locked_view_focus = false;
180 break;
181 //Takes container focus
182 case WLC_BIT_OVERRIDE_REDIRECT|WLC_BIT_UNMANAGED:
183 locked_container_focus = false;
184 break;
167 } 185 }
186 set_focused_container(get_focused_view(&root_container));
168} 187}
169 188
170static void handle_view_focus(wlc_handle view, bool focus) { 189static void handle_view_focus(wlc_handle view, bool focus) {
@@ -172,6 +191,8 @@ static void handle_view_focus(wlc_handle view, bool focus) {
172} 191}
173 192
174static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { 193static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) {
194 sway_log(L_DEBUG, "geometry request %d x %d : %d x %d",
195 geometry->origin.x, geometry->origin.y, geometry->size.w, geometry->size.h);
175 // If the view is floating, then apply the geometry. 196 // If the view is floating, then apply the geometry.
176 // Otherwise save the desired width/height for the view. 197 // Otherwise save the desired width/height for the view.
177 // This will not do anything for the time being as WLC improperly sends geometry requests 198 // This will not do anything for the time being as WLC improperly sends geometry requests
@@ -186,33 +207,32 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo
186 view->x = geometry->origin.x; 207 view->x = geometry->origin.x;
187 view->y = geometry->origin.y; 208 view->y = geometry->origin.y;
188 arrange_windows(view->parent, -1, -1); 209 arrange_windows(view->parent, -1, -1);
189 } 210 }
190 } 211 }
191} 212}
192 213
193static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { 214static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) {
194 switch(state) { 215 swayc_t *c = NULL;
216 switch (state) {
195 case WLC_BIT_FULLSCREEN: 217 case WLC_BIT_FULLSCREEN:
196 { 218 //I3 just lets it become fullscreen
197 //I3 just lets it become fullscreen 219 wlc_view_set_state(view, state, toggle);
198 wlc_view_set_state(view,state,toggle); 220 c = get_swayc_for_handle(view, &root_container);
199 swayc_t *c = get_swayc_for_handle(view, &root_container); 221 sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d", view, c->name, toggle);
200 sway_log(L_DEBUG, "setting view %ld %s, fullscreen %d",view,c->name,toggle); 222 if (c) {
201 if (c) { 223 arrange_windows(c->parent, -1, -1);
202 arrange_windows(c->parent, -1, -1); 224 //Set it as focused window for that workspace if its going
203 //Set it as focused window for that workspace if its going 225 //fullscreen
204 //fullscreen 226 if (toggle) {
205 if (toggle) { 227 swayc_t *ws = c;
206 swayc_t *ws = c; 228 while (ws->type != C_WORKSPACE) {
207 while (ws->type != C_WORKSPACE) { 229 ws = ws->parent;
208 ws = ws->parent;
209 }
210 //Set ws focus to c
211 focus_view_for(ws, c);
212 } 230 }
231 //Set ws focus to c
232 set_focused_container_for(ws, c);
213 } 233 }
214 break;
215 } 234 }
235 break;
216 case WLC_BIT_MAXIMIZED: 236 case WLC_BIT_MAXIMIZED:
217 case WLC_BIT_RESIZING: 237 case WLC_BIT_RESIZING:
218 case WLC_BIT_MOVING: 238 case WLC_BIT_MOVING:
@@ -226,7 +246,7 @@ static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit s
226static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers 246static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers
227 *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) { 247 *modifiers, uint32_t key, uint32_t sym, enum wlc_key_state state) {
228 enum { QSIZE = 32 }; 248 enum { QSIZE = 32 };
229 if (override_redirect) { 249 if (locked_view_focus) {
230 return false; 250 return false;
231 } 251 }
232 static uint8_t head = 0; 252 static uint8_t head = 0;
@@ -295,7 +315,7 @@ static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct w
295 static wlc_handle prev_view = 0; 315 static wlc_handle prev_view = 0;
296 mouse_origin = *origin; 316 mouse_origin = *origin;
297 if (config->focus_follows_mouse && prev_view != view) { 317 if (config->focus_follows_mouse && prev_view != view) {
298 focus_pointer(); 318 set_focused_container(container_under_pointer());
299 } 319 }
300 prev_view = view; 320 prev_view = view;
301 return false; 321 return false;
@@ -305,7 +325,8 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w
305 uint32_t button, enum wlc_button_state state) { 325 uint32_t button, enum wlc_button_state state) {
306 swayc_t *focused = get_focused_container(&root_container); 326 swayc_t *focused = get_focused_container(&root_container);
307 if (state == WLC_BUTTON_STATE_PRESSED) { 327 if (state == WLC_BUTTON_STATE_PRESSED) {
308 swayc_t *pointer = focus_pointer(); 328 swayc_t *pointer = container_under_pointer();
329 set_focused_container(pointer);
309 return (pointer && pointer != focused); 330 return (pointer && pointer != focused);
310 } 331 }
311 return false; 332 return false;