diff options
author | Tobias Langendorf <junglerobba@jngl.one> | 2020-08-29 17:14:55 +0200 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2020-10-10 09:53:41 +0200 |
commit | 657587964e5d8e444ac64829a0aab309c25ff50f (patch) | |
tree | b0991a49d72f845a5783d5c642ccc72326b312c4 /sway/desktop | |
parent | commands/move: fix single-split escaping on move (diff) | |
download | sway-657587964e5d8e444ac64829a0aab309c25ff50f.tar.gz sway-657587964e5d8e444ac64829a0aab309c25ff50f.tar.zst sway-657587964e5d8e444ac64829a0aab309c25ff50f.zip |
xwayland: support views that change override-redirect status
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/xwayland.c | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 3b42013b..e35473bf 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -118,12 +118,36 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { | |||
118 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { | 118 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { |
119 | struct sway_xwayland_unmanaged *surface = | 119 | struct sway_xwayland_unmanaged *surface = |
120 | wl_container_of(listener, surface, destroy); | 120 | wl_container_of(listener, surface, destroy); |
121 | wl_list_remove(&surface->request_configure.link); | ||
121 | wl_list_remove(&surface->map.link); | 122 | wl_list_remove(&surface->map.link); |
122 | wl_list_remove(&surface->unmap.link); | 123 | wl_list_remove(&surface->unmap.link); |
123 | wl_list_remove(&surface->destroy.link); | 124 | wl_list_remove(&surface->destroy.link); |
125 | wl_list_remove(&surface->override_redirect.link); | ||
124 | free(surface); | 126 | free(surface); |
125 | } | 127 | } |
126 | 128 | ||
129 | static void handle_map(struct wl_listener *listener, void *data); | ||
130 | |||
131 | struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); | ||
132 | |||
133 | static void unmanaged_handle_override_redirect(struct wl_listener *listener, void *data) { | ||
134 | struct sway_xwayland_unmanaged *surface = | ||
135 | wl_container_of(listener, surface, override_redirect); | ||
136 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; | ||
137 | |||
138 | bool mapped = xsurface->mapped; | ||
139 | if (mapped) { | ||
140 | unmanaged_handle_unmap(&surface->unmap, NULL); | ||
141 | } | ||
142 | |||
143 | unmanaged_handle_destroy(&surface->destroy, NULL); | ||
144 | xsurface->data = NULL; | ||
145 | struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface); | ||
146 | if (mapped) { | ||
147 | handle_map(&xwayland_view->map, xsurface); | ||
148 | } | ||
149 | } | ||
150 | |||
127 | static struct sway_xwayland_unmanaged *create_unmanaged( | 151 | static struct sway_xwayland_unmanaged *create_unmanaged( |
128 | struct wlr_xwayland_surface *xsurface) { | 152 | struct wlr_xwayland_surface *xsurface) { |
129 | struct sway_xwayland_unmanaged *surface = | 153 | struct sway_xwayland_unmanaged *surface = |
@@ -144,6 +168,8 @@ static struct sway_xwayland_unmanaged *create_unmanaged( | |||
144 | surface->unmap.notify = unmanaged_handle_unmap; | 168 | surface->unmap.notify = unmanaged_handle_unmap; |
145 | wl_signal_add(&xsurface->events.destroy, &surface->destroy); | 169 | wl_signal_add(&xsurface->events.destroy, &surface->destroy); |
146 | surface->destroy.notify = unmanaged_handle_destroy; | 170 | surface->destroy.notify = unmanaged_handle_destroy; |
171 | wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); | ||
172 | surface->override_redirect.notify = unmanaged_handle_override_redirect; | ||
147 | 173 | ||
148 | return surface; | 174 | return surface; |
149 | } | 175 | } |
@@ -418,6 +444,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
418 | wl_list_remove(&xwayland_view->set_decorations.link); | 444 | wl_list_remove(&xwayland_view->set_decorations.link); |
419 | wl_list_remove(&xwayland_view->map.link); | 445 | wl_list_remove(&xwayland_view->map.link); |
420 | wl_list_remove(&xwayland_view->unmap.link); | 446 | wl_list_remove(&xwayland_view->unmap.link); |
447 | wl_list_remove(&xwayland_view->override_redirect.link); | ||
421 | view_begin_destroy(&xwayland_view->view); | 448 | view_begin_destroy(&xwayland_view->view); |
422 | } | 449 | } |
423 | 450 | ||
@@ -441,16 +468,6 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
441 | struct wlr_xwayland_surface *xsurface = data; | 468 | struct wlr_xwayland_surface *xsurface = data; |
442 | struct sway_view *view = &xwayland_view->view; | 469 | struct sway_view *view = &xwayland_view->view; |
443 | 470 | ||
444 | if (xsurface->override_redirect) { | ||
445 | // This window used not to have the override redirect flag and has it | ||
446 | // now. Switch to unmanaged. | ||
447 | handle_destroy(&xwayland_view->destroy, view); | ||
448 | xsurface->data = NULL; | ||
449 | struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); | ||
450 | unmanaged_handle_map(&unmanaged->map, xsurface); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | view->natural_width = xsurface->width; | 471 | view->natural_width = xsurface->width; |
455 | view->natural_height = xsurface->height; | 472 | view->natural_height = xsurface->height; |
456 | 473 | ||
@@ -465,6 +482,25 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
465 | transaction_commit_dirty(); | 482 | transaction_commit_dirty(); |
466 | } | 483 | } |
467 | 484 | ||
485 | static void handle_override_redirect(struct wl_listener *listener, void *data) { | ||
486 | struct sway_xwayland_view *xwayland_view = | ||
487 | wl_container_of(listener, xwayland_view, override_redirect); | ||
488 | struct wlr_xwayland_surface *xsurface = data; | ||
489 | struct sway_view *view = &xwayland_view->view; | ||
490 | |||
491 | bool mapped = xsurface->mapped; | ||
492 | if (mapped) { | ||
493 | handle_unmap(&xwayland_view->unmap, NULL); | ||
494 | } | ||
495 | |||
496 | handle_destroy(&xwayland_view->destroy, view); | ||
497 | xsurface->data = NULL; | ||
498 | struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); | ||
499 | if (mapped) { | ||
500 | unmanaged_handle_map(&unmanaged->map, xsurface); | ||
501 | } | ||
502 | } | ||
503 | |||
468 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 504 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
469 | struct sway_xwayland_view *xwayland_view = | 505 | struct sway_xwayland_view *xwayland_view = |
470 | wl_container_of(listener, xwayland_view, request_configure); | 506 | wl_container_of(listener, xwayland_view, request_configure); |
@@ -637,22 +673,14 @@ struct sway_view *view_from_wlr_xwayland_surface( | |||
637 | return xsurface->data; | 673 | return xsurface->data; |
638 | } | 674 | } |
639 | 675 | ||
640 | void handle_xwayland_surface(struct wl_listener *listener, void *data) { | 676 | struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface) { |
641 | struct wlr_xwayland_surface *xsurface = data; | ||
642 | |||
643 | if (xsurface->override_redirect) { | ||
644 | sway_log(SWAY_DEBUG, "New xwayland unmanaged surface"); | ||
645 | create_unmanaged(xsurface); | ||
646 | return; | ||
647 | } | ||
648 | |||
649 | sway_log(SWAY_DEBUG, "New xwayland surface title='%s' class='%s'", | 677 | sway_log(SWAY_DEBUG, "New xwayland surface title='%s' class='%s'", |
650 | xsurface->title, xsurface->class); | 678 | xsurface->title, xsurface->class); |
651 | 679 | ||
652 | struct sway_xwayland_view *xwayland_view = | 680 | struct sway_xwayland_view *xwayland_view = |
653 | calloc(1, sizeof(struct sway_xwayland_view)); | 681 | calloc(1, sizeof(struct sway_xwayland_view)); |
654 | if (!sway_assert(xwayland_view, "Failed to allocate view")) { | 682 | if (!sway_assert(xwayland_view, "Failed to allocate view")) { |
655 | return; | 683 | return NULL; |
656 | } | 684 | } |
657 | 685 | ||
658 | view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); | 686 | view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl); |
@@ -711,7 +739,25 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
711 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); | 739 | wl_signal_add(&xsurface->events.map, &xwayland_view->map); |
712 | xwayland_view->map.notify = handle_map; | 740 | xwayland_view->map.notify = handle_map; |
713 | 741 | ||
742 | wl_signal_add(&xsurface->events.set_override_redirect, | ||
743 | &xwayland_view->override_redirect); | ||
744 | xwayland_view->override_redirect.notify = handle_override_redirect; | ||
745 | |||
714 | xsurface->data = xwayland_view; | 746 | xsurface->data = xwayland_view; |
747 | |||
748 | return xwayland_view; | ||
749 | } | ||
750 | |||
751 | void handle_xwayland_surface(struct wl_listener *listener, void *data) { | ||
752 | struct wlr_xwayland_surface *xsurface = data; | ||
753 | |||
754 | if (xsurface->override_redirect) { | ||
755 | sway_log(SWAY_DEBUG, "New xwayland unmanaged surface"); | ||
756 | create_unmanaged(xsurface); | ||
757 | return; | ||
758 | } | ||
759 | |||
760 | create_xwayland_view(xsurface); | ||
715 | } | 761 | } |
716 | 762 | ||
717 | void handle_xwayland_ready(struct wl_listener *listener, void *data) { | 763 | void handle_xwayland_ready(struct wl_listener *listener, void *data) { |