diff options
Diffstat (limited to 'sway/desktop/xdg_shell.c')
-rw-r--r-- | sway/desktop/xdg_shell.c | 105 |
1 files changed, 99 insertions, 6 deletions
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 98c16faf..b364663d 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 199309L | 1 | #define _POSIX_C_SOURCE 199309L |
2 | #include <float.h> | ||
2 | #include <stdbool.h> | 3 | #include <stdbool.h> |
3 | #include <stdlib.h> | 4 | #include <stdlib.h> |
4 | #include <wayland-server.h> | 5 | #include <wayland-server.h> |
@@ -95,6 +96,16 @@ static struct sway_xdg_shell_view *xdg_shell_view_from_view( | |||
95 | return (struct sway_xdg_shell_view *)view; | 96 | return (struct sway_xdg_shell_view *)view; |
96 | } | 97 | } |
97 | 98 | ||
99 | static void get_constraints(struct sway_view *view, double *min_width, | ||
100 | double *max_width, double *min_height, double *max_height) { | ||
101 | struct wlr_xdg_toplevel_state *state = | ||
102 | &view->wlr_xdg_surface->toplevel->current; | ||
103 | *min_width = state->min_width > 0 ? state->min_width : DBL_MIN; | ||
104 | *max_width = state->max_width > 0 ? state->max_width : DBL_MAX; | ||
105 | *min_height = state->min_height > 0 ? state->min_height : DBL_MIN; | ||
106 | *max_height = state->max_height > 0 ? state->max_height : DBL_MAX; | ||
107 | } | ||
108 | |||
98 | static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) { | 109 | static const char *get_string_prop(struct sway_view *view, enum sway_view_prop prop) { |
99 | if (xdg_shell_view_from_view(view) == NULL) { | 110 | if (xdg_shell_view_from_view(view) == NULL) { |
100 | return NULL; | 111 | return NULL; |
@@ -168,6 +179,14 @@ static void for_each_surface(struct sway_view *view, | |||
168 | user_data); | 179 | user_data); |
169 | } | 180 | } |
170 | 181 | ||
182 | static void for_each_popup(struct sway_view *view, | ||
183 | wlr_surface_iterator_func_t iterator, void *user_data) { | ||
184 | if (xdg_shell_view_from_view(view) == NULL) { | ||
185 | return; | ||
186 | } | ||
187 | wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); | ||
188 | } | ||
189 | |||
171 | static void _close(struct sway_view *view) { | 190 | static void _close(struct sway_view *view) { |
172 | if (xdg_shell_view_from_view(view) == NULL) { | 191 | if (xdg_shell_view_from_view(view) == NULL) { |
173 | return; | 192 | return; |
@@ -178,6 +197,18 @@ static void _close(struct sway_view *view) { | |||
178 | } | 197 | } |
179 | } | 198 | } |
180 | 199 | ||
200 | static void close_popups_iterator(struct wlr_surface *surface, | ||
201 | int sx, int sy, void *data) { | ||
202 | struct wlr_xdg_surface *xdg_surface = | ||
203 | wlr_xdg_surface_from_wlr_surface(surface); | ||
204 | wlr_xdg_surface_send_close(xdg_surface); | ||
205 | } | ||
206 | |||
207 | static void close_popups(struct sway_view *view) { | ||
208 | wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, | ||
209 | close_popups_iterator, NULL); | ||
210 | } | ||
211 | |||
181 | static void destroy(struct sway_view *view) { | 212 | static void destroy(struct sway_view *view) { |
182 | struct sway_xdg_shell_view *xdg_shell_view = | 213 | struct sway_xdg_shell_view *xdg_shell_view = |
183 | xdg_shell_view_from_view(view); | 214 | xdg_shell_view_from_view(view); |
@@ -188,6 +219,7 @@ static void destroy(struct sway_view *view) { | |||
188 | } | 219 | } |
189 | 220 | ||
190 | static const struct sway_view_impl view_impl = { | 221 | static const struct sway_view_impl view_impl = { |
222 | .get_constraints = get_constraints, | ||
191 | .get_string_prop = get_string_prop, | 223 | .get_string_prop = get_string_prop, |
192 | .configure = configure, | 224 | .configure = configure, |
193 | .set_activated = set_activated, | 225 | .set_activated = set_activated, |
@@ -195,7 +227,9 @@ static const struct sway_view_impl view_impl = { | |||
195 | .set_fullscreen = set_fullscreen, | 227 | .set_fullscreen = set_fullscreen, |
196 | .wants_floating = wants_floating, | 228 | .wants_floating = wants_floating, |
197 | .for_each_surface = for_each_surface, | 229 | .for_each_surface = for_each_surface, |
230 | .for_each_popup = for_each_popup, | ||
198 | .close = _close, | 231 | .close = _close, |
232 | .close_popups = close_popups, | ||
199 | .destroy = destroy, | 233 | .destroy = destroy, |
200 | }; | 234 | }; |
201 | 235 | ||
@@ -213,10 +247,24 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
213 | transaction_notify_view_ready(view, xdg_surface->configure_serial); | 247 | transaction_notify_view_ready(view, xdg_surface->configure_serial); |
214 | } | 248 | } |
215 | 249 | ||
216 | view_update_title(view, false); | ||
217 | view_damage_from(view); | 250 | view_damage_from(view); |
218 | } | 251 | } |
219 | 252 | ||
253 | static void handle_set_title(struct wl_listener *listener, void *data) { | ||
254 | struct sway_xdg_shell_view *xdg_shell_view = | ||
255 | wl_container_of(listener, xdg_shell_view, set_title); | ||
256 | struct sway_view *view = &xdg_shell_view->view; | ||
257 | view_update_title(view, false); | ||
258 | view_execute_criteria(view); | ||
259 | } | ||
260 | |||
261 | static void handle_set_app_id(struct wl_listener *listener, void *data) { | ||
262 | struct sway_xdg_shell_view *xdg_shell_view = | ||
263 | wl_container_of(listener, xdg_shell_view, set_app_id); | ||
264 | struct sway_view *view = &xdg_shell_view->view; | ||
265 | view_execute_criteria(view); | ||
266 | } | ||
267 | |||
220 | static void handle_new_popup(struct wl_listener *listener, void *data) { | 268 | static void handle_new_popup(struct wl_listener *listener, void *data) { |
221 | struct sway_xdg_shell_view *xdg_shell_view = | 269 | struct sway_xdg_shell_view *xdg_shell_view = |
222 | wl_container_of(listener, xdg_shell_view, new_popup); | 270 | wl_container_of(listener, xdg_shell_view, new_popup); |
@@ -241,13 +289,41 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
241 | return; | 289 | return; |
242 | } | 290 | } |
243 | 291 | ||
244 | view_set_fullscreen(view, e->fullscreen); | 292 | container_set_fullscreen(view->swayc, e->fullscreen); |
245 | 293 | ||
246 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 294 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
247 | arrange_windows(output); | 295 | arrange_windows(output); |
248 | transaction_commit_dirty(); | 296 | transaction_commit_dirty(); |
249 | } | 297 | } |
250 | 298 | ||
299 | static void handle_request_move(struct wl_listener *listener, void *data) { | ||
300 | struct sway_xdg_shell_view *xdg_shell_view = | ||
301 | wl_container_of(listener, xdg_shell_view, request_move); | ||
302 | struct sway_view *view = &xdg_shell_view->view; | ||
303 | if (!container_is_floating(view->swayc)) { | ||
304 | return; | ||
305 | } | ||
306 | struct wlr_xdg_toplevel_move_event *e = data; | ||
307 | struct sway_seat *seat = e->seat->seat->data; | ||
308 | if (e->serial == seat->last_button_serial) { | ||
309 | seat_begin_move(seat, view->swayc, seat->last_button); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | static void handle_request_resize(struct wl_listener *listener, void *data) { | ||
314 | struct sway_xdg_shell_view *xdg_shell_view = | ||
315 | wl_container_of(listener, xdg_shell_view, request_resize); | ||
316 | struct sway_view *view = &xdg_shell_view->view; | ||
317 | if (!container_is_floating(view->swayc)) { | ||
318 | return; | ||
319 | } | ||
320 | struct wlr_xdg_toplevel_resize_event *e = data; | ||
321 | struct sway_seat *seat = e->seat->seat->data; | ||
322 | if (e->serial == seat->last_button_serial) { | ||
323 | seat_begin_resize(seat, view->swayc, seat->last_button, e->edges); | ||
324 | } | ||
325 | } | ||
326 | |||
251 | static void handle_unmap(struct wl_listener *listener, void *data) { | 327 | static void handle_unmap(struct wl_listener *listener, void *data) { |
252 | struct sway_xdg_shell_view *xdg_shell_view = | 328 | struct sway_xdg_shell_view *xdg_shell_view = |
253 | wl_container_of(listener, xdg_shell_view, unmap); | 329 | wl_container_of(listener, xdg_shell_view, unmap); |
@@ -262,6 +338,10 @@ static void handle_unmap(struct wl_listener *listener, void *data) { | |||
262 | wl_list_remove(&xdg_shell_view->commit.link); | 338 | wl_list_remove(&xdg_shell_view->commit.link); |
263 | wl_list_remove(&xdg_shell_view->new_popup.link); | 339 | wl_list_remove(&xdg_shell_view->new_popup.link); |
264 | wl_list_remove(&xdg_shell_view->request_fullscreen.link); | 340 | wl_list_remove(&xdg_shell_view->request_fullscreen.link); |
341 | wl_list_remove(&xdg_shell_view->request_move.link); | ||
342 | wl_list_remove(&xdg_shell_view->request_resize.link); | ||
343 | wl_list_remove(&xdg_shell_view->set_title.link); | ||
344 | wl_list_remove(&xdg_shell_view->set_app_id.link); | ||
265 | } | 345 | } |
266 | 346 | ||
267 | static void handle_map(struct wl_listener *listener, void *data) { | 347 | static void handle_map(struct wl_listener *listener, void *data) { |
@@ -280,7 +360,7 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
280 | view_map(view, view->wlr_xdg_surface->surface); | 360 | view_map(view, view->wlr_xdg_surface->surface); |
281 | 361 | ||
282 | if (xdg_surface->toplevel->client_pending.fullscreen) { | 362 | if (xdg_surface->toplevel->client_pending.fullscreen) { |
283 | view_set_fullscreen(view, true); | 363 | container_set_fullscreen(view->swayc, true); |
284 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); | 364 | struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE); |
285 | arrange_windows(ws); | 365 | arrange_windows(ws); |
286 | } else { | 366 | } else { |
@@ -299,6 +379,22 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
299 | xdg_shell_view->request_fullscreen.notify = handle_request_fullscreen; | 379 | xdg_shell_view->request_fullscreen.notify = handle_request_fullscreen; |
300 | wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, | 380 | wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, |
301 | &xdg_shell_view->request_fullscreen); | 381 | &xdg_shell_view->request_fullscreen); |
382 | |||
383 | xdg_shell_view->request_move.notify = handle_request_move; | ||
384 | wl_signal_add(&xdg_surface->toplevel->events.request_move, | ||
385 | &xdg_shell_view->request_move); | ||
386 | |||
387 | xdg_shell_view->request_resize.notify = handle_request_resize; | ||
388 | wl_signal_add(&xdg_surface->toplevel->events.request_resize, | ||
389 | &xdg_shell_view->request_resize); | ||
390 | |||
391 | xdg_shell_view->set_title.notify = handle_set_title; | ||
392 | wl_signal_add(&xdg_surface->toplevel->events.set_title, | ||
393 | &xdg_shell_view->set_title); | ||
394 | |||
395 | xdg_shell_view->set_app_id.notify = handle_set_app_id; | ||
396 | wl_signal_add(&xdg_surface->toplevel->events.set_app_id, | ||
397 | &xdg_shell_view->set_app_id); | ||
302 | } | 398 | } |
303 | 399 | ||
304 | static void handle_destroy(struct wl_listener *listener, void *data) { | 400 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -344,9 +440,6 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { | |||
344 | view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); | 440 | view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); |
345 | xdg_shell_view->view.wlr_xdg_surface = xdg_surface; | 441 | xdg_shell_view->view.wlr_xdg_surface = xdg_surface; |
346 | 442 | ||
347 | // TODO: | ||
348 | // - Look up pid and open on appropriate workspace | ||
349 | |||
350 | xdg_shell_view->map.notify = handle_map; | 443 | xdg_shell_view->map.notify = handle_map; |
351 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); | 444 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); |
352 | 445 | ||