diff options
Diffstat (limited to 'sway/handlers.c')
-rw-r--r-- | sway/handlers.c | 235 |
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 | ||
15 | static struct wlc_origin mouse_origin; | 17 | static struct wlc_origin mouse_origin; |
16 | //Keyboard input is being overrided by window (dmenu) | ||
17 | static bool override_redirect = false; | ||
18 | 18 | ||
19 | static bool pointer_test(swayc_t *view, void *_origin) { | 19 | static 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 | ||
34 | swayc_t *focus_pointer(void) { | 34 | swayc_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 | ||
49 | static bool handle_output_created(wlc_handle output) { | 79 | static 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 | ||
82 | static void handle_output_focused(wlc_handle output, bool focus) { | 112 | static 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 | ||
91 | static bool handle_view_created(wlc_handle handle) { | 123 | static 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 | ||
131 | static void handle_view_destroyed(wlc_handle handle) { | 160 | static 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 | ||
170 | static void handle_view_focus(wlc_handle view, bool focus) { | 189 | static 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 | ||
174 | static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geometry* geometry) { | 193 | static 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 | ||
193 | static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { | 214 | static 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 | |||
226 | static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifiers | 246 | static 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; |