diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-10-07 20:40:05 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-10-08 22:49:59 +1000 |
commit | 832ebc896655cb5ca7689559d4e42b426d764e71 (patch) | |
tree | 1a3bc3ff7fb13d7ed5e86ad67a05739d4c4a1de3 /sway/desktop | |
parent | Merge pull request #2791 from RyanDwyer/status-command-optional (diff) | |
download | sway-832ebc896655cb5ca7689559d4e42b426d764e71.tar.gz sway-832ebc896655cb5ca7689559d4e42b426d764e71.tar.zst sway-832ebc896655cb5ca7689559d4e42b426d764e71.zip |
Implement popup_during_fullscreen
This introduces a new view_impl function: is_transient_for. Similar to
container_has_ancestor but works using the surface parents rather than
the tree.
This patch modifies view_is_visible, container_at and so on to allow
transient views to function normally when they're in front of a
fullscreen view.
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/output.c | 11 | ||||
-rw-r--r-- | sway/desktop/render.c | 11 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 29 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 28 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 29 |
5 files changed, 108 insertions, 0 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index cfb5a710..0bcdcac1 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -329,6 +329,17 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
329 | workspace->current.fullscreen, &data); | 329 | workspace->current.fullscreen, &data); |
330 | container_for_each_child(workspace->current.fullscreen, | 330 | container_for_each_child(workspace->current.fullscreen, |
331 | send_frame_done_container_iterator, &data); | 331 | send_frame_done_container_iterator, &data); |
332 | if (config->popup_during_fullscreen == POPUP_SMART && | ||
333 | workspace->current.fullscreen->view) { | ||
334 | for (int i = 0; i < workspace->current.floating->length; ++i) { | ||
335 | struct sway_container *floater = | ||
336 | workspace->current.floating->items[i]; | ||
337 | if (floater->view && view_is_transient_for(floater->view, | ||
338 | workspace->current.fullscreen->view)) { | ||
339 | send_frame_done_container_iterator(floater, &data); | ||
340 | } | ||
341 | } | ||
342 | } | ||
332 | #ifdef HAVE_XWAYLAND | 343 | #ifdef HAVE_XWAYLAND |
333 | send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); | 344 | send_frame_done_unmanaged(output, &root->xwayland_unmanaged, when); |
334 | #endif | 345 | #endif |
diff --git a/sway/desktop/render.c b/sway/desktop/render.c index c8b08a58..c2a0d29f 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c | |||
@@ -961,6 +961,17 @@ void output_render(struct sway_output *output, struct timespec *when, | |||
961 | render_container(output, damage, fullscreen_con, | 961 | render_container(output, damage, fullscreen_con, |
962 | fullscreen_con->current.focused); | 962 | fullscreen_con->current.focused); |
963 | } | 963 | } |
964 | |||
965 | if (config->popup_during_fullscreen == POPUP_SMART && | ||
966 | fullscreen_con->view) { | ||
967 | for (int i = 0; i < workspace->floating->length; ++i) { | ||
968 | struct sway_container *floater = workspace->floating->items[i]; | ||
969 | if (floater->view && view_is_transient_for( | ||
970 | floater->view, fullscreen_con->view)) { | ||
971 | render_floating_container(output, damage, floater); | ||
972 | } | ||
973 | } | ||
974 | } | ||
964 | #ifdef HAVE_XWAYLAND | 975 | #ifdef HAVE_XWAYLAND |
965 | render_unmanaged(output, damage, &root->xwayland_unmanaged); | 976 | render_unmanaged(output, damage, &root->xwayland_unmanaged); |
966 | #endif | 977 | #endif |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index a8b527a7..54831679 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -192,6 +192,21 @@ static void for_each_popup(struct sway_view *view, | |||
192 | wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); | 192 | wlr_xdg_surface_for_each_popup(view->wlr_xdg_surface, iterator, user_data); |
193 | } | 193 | } |
194 | 194 | ||
195 | static bool is_transient_for(struct sway_view *child, | ||
196 | struct sway_view *ancestor) { | ||
197 | if (xdg_shell_view_from_view(child) == NULL) { | ||
198 | return false; | ||
199 | } | ||
200 | struct wlr_xdg_surface *surface = child->wlr_xdg_surface; | ||
201 | while (surface) { | ||
202 | if (surface->toplevel->parent == ancestor->wlr_xdg_surface) { | ||
203 | return true; | ||
204 | } | ||
205 | surface = surface->toplevel->parent; | ||
206 | } | ||
207 | return false; | ||
208 | } | ||
209 | |||
195 | static void _close(struct sway_view *view) { | 210 | static void _close(struct sway_view *view) { |
196 | if (xdg_shell_view_from_view(view) == NULL) { | 211 | if (xdg_shell_view_from_view(view) == NULL) { |
197 | return; | 212 | return; |
@@ -233,6 +248,7 @@ static const struct sway_view_impl view_impl = { | |||
233 | .wants_floating = wants_floating, | 248 | .wants_floating = wants_floating, |
234 | .for_each_surface = for_each_surface, | 249 | .for_each_surface = for_each_surface, |
235 | .for_each_popup = for_each_popup, | 250 | .for_each_popup = for_each_popup, |
251 | .is_transient_for = is_transient_for, | ||
236 | .close = _close, | 252 | .close = _close, |
237 | .close_popups = close_popups, | 253 | .close_popups = close_popups, |
238 | .destroy = destroy, | 254 | .destroy = destroy, |
@@ -385,6 +401,18 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
385 | view_update_csd_from_client(view, csd); | 401 | view_update_csd_from_client(view, csd); |
386 | } | 402 | } |
387 | 403 | ||
404 | if (config->popup_during_fullscreen == POPUP_LEAVE && | ||
405 | view->container->workspace && | ||
406 | view->container->workspace->fullscreen && | ||
407 | xdg_surface->toplevel->parent) { | ||
408 | struct wlr_xdg_surface *psurface = xdg_surface->toplevel->parent; | ||
409 | struct sway_xdg_shell_view *parent = psurface->data; | ||
410 | struct sway_view *sway_view = &parent->view; | ||
411 | if (sway_view->container && sway_view->container->is_fullscreen) { | ||
412 | container_set_fullscreen(sway_view->container, false); | ||
413 | } | ||
414 | } | ||
415 | |||
388 | if (xdg_surface->toplevel->client_pending.fullscreen) { | 416 | if (xdg_surface->toplevel->client_pending.fullscreen) { |
389 | container_set_fullscreen(view->container, true); | 417 | container_set_fullscreen(view->container, true); |
390 | arrange_workspace(view->container->workspace); | 418 | arrange_workspace(view->container->workspace); |
@@ -395,6 +423,7 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
395 | arrange_workspace(view->container->workspace); | 423 | arrange_workspace(view->container->workspace); |
396 | } | 424 | } |
397 | } | 425 | } |
426 | |||
398 | transaction_commit_dirty(); | 427 | transaction_commit_dirty(); |
399 | 428 | ||
400 | xdg_shell_view->commit.notify = handle_commit; | 429 | xdg_shell_view->commit.notify = handle_commit; |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index a7838c0f..dacfca02 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -189,6 +189,21 @@ static void for_each_popup(struct sway_view *view, | |||
189 | user_data); | 189 | user_data); |
190 | } | 190 | } |
191 | 191 | ||
192 | static bool is_transient_for(struct sway_view *child, | ||
193 | struct sway_view *ancestor) { | ||
194 | if (xdg_shell_v6_view_from_view(child) == NULL) { | ||
195 | return false; | ||
196 | } | ||
197 | struct wlr_xdg_surface_v6 *surface = child->wlr_xdg_surface_v6; | ||
198 | while (surface) { | ||
199 | if (surface->toplevel->parent == ancestor->wlr_xdg_surface_v6) { | ||
200 | return true; | ||
201 | } | ||
202 | surface = surface->toplevel->parent; | ||
203 | } | ||
204 | return false; | ||
205 | } | ||
206 | |||
192 | static void _close(struct sway_view *view) { | 207 | static void _close(struct sway_view *view) { |
193 | if (xdg_shell_v6_view_from_view(view) == NULL) { | 208 | if (xdg_shell_v6_view_from_view(view) == NULL) { |
194 | return; | 209 | return; |
@@ -230,6 +245,7 @@ static const struct sway_view_impl view_impl = { | |||
230 | .wants_floating = wants_floating, | 245 | .wants_floating = wants_floating, |
231 | .for_each_surface = for_each_surface, | 246 | .for_each_surface = for_each_surface, |
232 | .for_each_popup = for_each_popup, | 247 | .for_each_popup = for_each_popup, |
248 | .is_transient_for = is_transient_for, | ||
233 | .close = _close, | 249 | .close = _close, |
234 | .close_popups = close_popups, | 250 | .close_popups = close_popups, |
235 | .destroy = destroy, | 251 | .destroy = destroy, |
@@ -380,6 +396,18 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
380 | WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; | 396 | WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; |
381 | view_update_csd_from_client(view, csd); | 397 | view_update_csd_from_client(view, csd); |
382 | 398 | ||
399 | if (config->popup_during_fullscreen == POPUP_LEAVE && | ||
400 | view->container->workspace && | ||
401 | view->container->workspace->fullscreen && | ||
402 | xdg_surface->toplevel->parent) { | ||
403 | struct wlr_xdg_surface_v6 *psurface = xdg_surface->toplevel->parent; | ||
404 | struct sway_xdg_shell_v6_view *parent = psurface->data; | ||
405 | struct sway_view *sway_view = &parent->view; | ||
406 | if (sway_view->container && sway_view->container->is_fullscreen) { | ||
407 | container_set_fullscreen(sway_view->container, false); | ||
408 | } | ||
409 | } | ||
410 | |||
383 | if (xdg_surface->toplevel->client_pending.fullscreen) { | 411 | if (xdg_surface->toplevel->client_pending.fullscreen) { |
384 | container_set_fullscreen(view->container, true); | 412 | container_set_fullscreen(view->container, true); |
385 | arrange_workspace(view->container->workspace); | 413 | arrange_workspace(view->container->workspace); |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 4c710f7e..80489f93 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "sway/tree/arrange.h" | 15 | #include "sway/tree/arrange.h" |
16 | #include "sway/tree/container.h" | 16 | #include "sway/tree/container.h" |
17 | #include "sway/tree/view.h" | 17 | #include "sway/tree/view.h" |
18 | #include "sway/tree/workspace.h" | ||
18 | 19 | ||
19 | static const char *atom_map[ATOM_LAST] = { | 20 | static const char *atom_map[ATOM_LAST] = { |
20 | "_NET_WM_WINDOW_TYPE_NORMAL", | 21 | "_NET_WM_WINDOW_TYPE_NORMAL", |
@@ -253,6 +254,21 @@ static void handle_set_decorations(struct wl_listener *listener, void *data) { | |||
253 | view_update_csd_from_client(view, csd); | 254 | view_update_csd_from_client(view, csd); |
254 | } | 255 | } |
255 | 256 | ||
257 | static bool is_transient_for(struct sway_view *child, | ||
258 | struct sway_view *ancestor) { | ||
259 | if (xwayland_view_from_view(child) == NULL) { | ||
260 | return false; | ||
261 | } | ||
262 | struct wlr_xwayland_surface *surface = child->wlr_xwayland_surface; | ||
263 | while (surface) { | ||
264 | if (surface->parent == ancestor->wlr_xwayland_surface) { | ||
265 | return true; | ||
266 | } | ||
267 | surface = surface->parent; | ||
268 | } | ||
269 | return false; | ||
270 | } | ||
271 | |||
256 | static void _close(struct sway_view *view) { | 272 | static void _close(struct sway_view *view) { |
257 | if (xwayland_view_from_view(view) == NULL) { | 273 | if (xwayland_view_from_view(view) == NULL) { |
258 | return; | 274 | return; |
@@ -276,6 +292,7 @@ static const struct sway_view_impl view_impl = { | |||
276 | .set_tiled = set_tiled, | 292 | .set_tiled = set_tiled, |
277 | .set_fullscreen = set_fullscreen, | 293 | .set_fullscreen = set_fullscreen, |
278 | .wants_floating = wants_floating, | 294 | .wants_floating = wants_floating, |
295 | .is_transient_for = is_transient_for, | ||
279 | .close = _close, | 296 | .close = _close, |
280 | .destroy = destroy, | 297 | .destroy = destroy, |
281 | }; | 298 | }; |
@@ -390,6 +407,18 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
390 | // Put it back into the tree | 407 | // Put it back into the tree |
391 | view_map(view, xsurface->surface); | 408 | view_map(view, xsurface->surface); |
392 | 409 | ||
410 | if (config->popup_during_fullscreen == POPUP_LEAVE && | ||
411 | view->container->workspace && | ||
412 | view->container->workspace->fullscreen && | ||
413 | xsurface->parent) { | ||
414 | struct wlr_xwayland_surface *psurface = xsurface->parent; | ||
415 | struct sway_xwayland_view *parent = psurface->data; | ||
416 | struct sway_view *sway_view = &parent->view; | ||
417 | if (sway_view->container && sway_view->container->is_fullscreen) { | ||
418 | container_set_fullscreen(sway_view->container, false); | ||
419 | } | ||
420 | } | ||
421 | |||
393 | if (xsurface->fullscreen) { | 422 | if (xsurface->fullscreen) { |
394 | container_set_fullscreen(view->container, true); | 423 | container_set_fullscreen(view->container, true); |
395 | arrange_workspace(view->container->workspace); | 424 | arrange_workspace(view->container->workspace); |