aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2023-12-06 14:28:59 -0500
committerLibravatar Kirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commitb38ed8b4792928dca3e1580e8160792ea41e25c4 (patch)
treeb080710c7a3f37de868ff4d5d96e6971f7105675
parenttransaction: ready signals will return success bools (diff)
downloadsway-b38ed8b4792928dca3e1580e8160792ea41e25c4.tar.gz
sway-b38ed8b4792928dca3e1580e8160792ea41e25c4.tar.zst
sway-b38ed8b4792928dca3e1580e8160792ea41e25c4.zip
scene_graph: Port xdg_shell
-rw-r--r--include/sway/scene_descriptor.h1
-rw-r--r--include/sway/tree/view.h46
-rw-r--r--sway/desktop/output.c8
-rw-r--r--sway/desktop/xdg_shell.c113
-rw-r--r--sway/input/cursor.c13
-rw-r--r--sway/tree/view.c272
6 files changed, 81 insertions, 372 deletions
diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h
index 970adaa5..43991f77 100644
--- a/include/sway/scene_descriptor.h
+++ b/include/sway/scene_descriptor.h
@@ -16,6 +16,7 @@ enum sway_scene_descriptor_type {
16 SWAY_SCENE_DESC_CONTAINER, 16 SWAY_SCENE_DESC_CONTAINER,
17 SWAY_SCENE_DESC_VIEW, 17 SWAY_SCENE_DESC_VIEW,
18 SWAY_SCENE_DESC_LAYER_SHELL, 18 SWAY_SCENE_DESC_LAYER_SHELL,
19 SWAY_SCENE_DESC_POPUP,
19 SWAY_SCENE_DESC_DRAG_ICON, 20 SWAY_SCENE_DESC_DRAG_ICON,
20}; 21};
21 22
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 4aaed9e3..467d912f 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -123,8 +123,6 @@ struct sway_view {
123 struct wl_signal unmap; 123 struct wl_signal unmap;
124 } events; 124 } events;
125 125
126 struct wl_listener surface_new_subsurface;
127
128 int max_render_time; // In milliseconds 126 int max_render_time; // In milliseconds
129 127
130 enum seat_config_shortcuts_inhibit shortcuts_inhibit; 128 enum seat_config_shortcuts_inhibit shortcuts_inhibit;
@@ -191,43 +189,12 @@ struct sway_xwayland_unmanaged {
191 struct wl_listener override_redirect; 189 struct wl_listener override_redirect;
192}; 190};
193#endif 191#endif
194struct sway_view_child;
195
196struct sway_view_child_impl {
197 void (*get_view_coords)(struct sway_view_child *child, int *sx, int *sy);
198 void (*destroy)(struct sway_view_child *child);
199};
200
201/**
202 * A view child is a surface in the view tree, such as a subsurface or a popup.
203 */
204struct sway_view_child {
205 const struct sway_view_child_impl *impl;
206 struct wl_list link;
207
208 struct sway_view *view;
209 struct sway_view_child *parent;
210 struct wl_list children; // sway_view_child::link
211 struct wlr_surface *surface;
212 bool mapped;
213
214 struct wl_listener surface_commit;
215 struct wl_listener surface_new_subsurface;
216 struct wl_listener surface_map;
217 struct wl_listener surface_unmap;
218 struct wl_listener surface_destroy;
219 struct wl_listener view_unmap;
220};
221
222struct sway_subsurface {
223 struct sway_view_child child;
224
225 struct wl_listener destroy;
226};
227 192
228struct sway_xdg_popup { 193struct sway_xdg_popup {
229 struct sway_view_child child; 194 struct sway_view *view;
230 195
196 struct wlr_scene_tree *scene_tree;
197 struct wlr_scene_tree *xdg_surface_tree;
231 struct wlr_xdg_popup *wlr_xdg_popup; 198 struct wlr_xdg_popup *wlr_xdg_popup;
232 199
233 struct wl_listener surface_commit; 200 struct wl_listener surface_commit;
@@ -339,13 +306,6 @@ void view_unmap(struct sway_view *view);
339void view_update_size(struct sway_view *view); 306void view_update_size(struct sway_view *view);
340void view_center_surface(struct sway_view *view); 307void view_center_surface(struct sway_view *view);
341 308
342void view_child_init(struct sway_view_child *child,
343 const struct sway_view_child_impl *impl, struct sway_view *view,
344 struct wlr_surface *surface);
345
346void view_child_destroy(struct sway_view_child *child);
347
348
349struct sway_view *view_from_wlr_xdg_surface( 309struct sway_view *view_from_wlr_xdg_surface(
350 struct wlr_xdg_surface *xdg_surface); 310 struct wlr_xdg_surface *xdg_surface);
351#if HAVE_XWAYLAND 311#if HAVE_XWAYLAND
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 942bc780..a5184484 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -289,8 +289,14 @@ static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
289 } 289 }
290 290
291 struct wlr_scene_node *current = &buffer->node; 291 struct wlr_scene_node *current = &buffer->node;
292
293 while (true) { 292 while (true) {
293 struct sway_view *view = scene_descriptor_try_get(current,
294 SWAY_SCENE_DESC_VIEW);
295 if (view) {
296 view_max_render_time = view->max_render_time;
297 break;
298 }
299
294 if (!current->parent) { 300 if (!current->parent) {
295 break; 301 break;
296 } 302 }
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 11c112be..fed820cf 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -7,7 +7,7 @@
7#include <wlr/util/edges.h> 7#include <wlr/util/edges.h>
8#include "log.h" 8#include "log.h"
9#include "sway/decoration.h" 9#include "sway/decoration.h"
10#include "sway/desktop.h" 10#include "sway/scene_descriptor.h"
11#include "sway/desktop/transaction.h" 11#include "sway/desktop/transaction.h"
12#include "sway/input/cursor.h" 12#include "sway/input/cursor.h"
13#include "sway/input/input-manager.h" 13#include "sway/input/input-manager.h"
@@ -19,41 +19,29 @@
19#include "sway/tree/workspace.h" 19#include "sway/tree/workspace.h"
20#include "sway/xdg_decoration.h" 20#include "sway/xdg_decoration.h"
21 21
22static const struct sway_view_child_impl popup_impl; 22static struct sway_xdg_popup *popup_create(
23 23 struct wlr_xdg_popup *wlr_popup, struct sway_view *view,
24static void popup_get_view_coords(struct sway_view_child *child, 24 struct wlr_scene_tree *parent);
25 int *sx, int *sy) {
26 struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
27 struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
28 25
29 wlr_xdg_popup_get_toplevel_coords(wlr_popup, 26static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
30 wlr_popup->current.geometry.x - wlr_popup->base->current.geometry.x, 27 struct sway_xdg_popup *popup =
31 wlr_popup->current.geometry.y - wlr_popup->base->current.geometry.y, 28 wl_container_of(listener, popup, new_popup);
32 sx, sy); 29 struct wlr_xdg_popup *wlr_popup = data;
30 popup_create(wlr_popup, popup->view, popup->xdg_surface_tree);
33} 31}
34 32
35static void popup_destroy(struct sway_view_child *child) { 33static void popup_handle_destroy(struct wl_listener *listener, void *data) {
36 if (!sway_assert(child->impl == &popup_impl, 34 struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
37 "Expected an xdg_shell popup")) { 35
38 return;
39 }
40 struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
41 wl_list_remove(&popup->surface_commit.link);
42 wl_list_remove(&popup->new_popup.link); 36 wl_list_remove(&popup->new_popup.link);
43 wl_list_remove(&popup->destroy.link); 37 wl_list_remove(&popup->destroy.link);
38 wl_list_remove(&popup->surface_commit.link);
39 wlr_scene_node_destroy(&popup->scene_tree->node);
44 free(popup); 40 free(popup);
45} 41}
46 42
47static const struct sway_view_child_impl popup_impl = {
48 .get_view_coords = popup_get_view_coords,
49 .destroy = popup_destroy,
50};
51
52static struct sway_xdg_popup *popup_create(
53 struct wlr_xdg_popup *wlr_popup, struct sway_view *view);
54
55static void popup_unconstrain(struct sway_xdg_popup *popup) { 43static void popup_unconstrain(struct sway_xdg_popup *popup) {
56 struct sway_view *view = popup->child.view; 44 struct sway_view *view = popup->view;
57 struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; 45 struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
58 46
59 struct sway_workspace *workspace = view->container->pending.workspace; 47 struct sway_workspace *workspace = view->container->pending.workspace;
@@ -83,29 +71,44 @@ static void popup_handle_surface_commit(struct wl_listener *listener, void *data
83 } 71 }
84} 72}
85 73
86static void popup_handle_new_popup(struct wl_listener *listener, void *data) { 74static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup,
87 struct sway_xdg_popup *popup = 75 struct sway_view *view, struct wlr_scene_tree *parent) {
88 wl_container_of(listener, popup, new_popup);
89 struct wlr_xdg_popup *wlr_popup = data;
90 popup_create(wlr_popup, popup->child.view);
91}
92
93static void popup_handle_destroy(struct wl_listener *listener, void *data) {
94 struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
95 view_child_destroy(&popup->child);
96}
97
98static struct sway_xdg_popup *popup_create(
99 struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {
100 struct wlr_xdg_surface *xdg_surface = wlr_popup->base; 76 struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
101 77
102 struct sway_xdg_popup *popup = 78 struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup));
103 calloc(1, sizeof(struct sway_xdg_popup)); 79 if (!popup) {
104 if (popup == NULL) {
105 return NULL; 80 return NULL;
106 } 81 }
107 view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); 82
108 popup->wlr_xdg_popup = wlr_popup; 83 popup->wlr_xdg_popup = wlr_popup;
84 popup->view = view;
85
86 popup->scene_tree = wlr_scene_tree_create(parent);
87 if (!popup->scene_tree) {
88 free(popup);
89 return NULL;
90 }
91
92 popup->xdg_surface_tree = wlr_scene_xdg_surface_create(
93 popup->scene_tree, xdg_surface);
94 if (!popup->xdg_surface_tree) {
95 wlr_scene_node_destroy(&popup->scene_tree->node);
96 free(popup);
97 return NULL;
98 }
99
100 if (!scene_descriptor_assign(&popup->scene_tree->node,
101 SWAY_SCENE_DESC_POPUP, popup)) {
102 sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor");
103 wlr_scene_node_destroy(&popup->scene_tree->node);
104 free(popup);
105 return NULL;
106 }
107
108 popup->wlr_xdg_popup = xdg_surface->popup;
109 struct sway_xdg_shell_view *shell_view =
110 wl_container_of(view, shell_view, view);
111 xdg_surface->data = shell_view;
109 112
110 wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit); 113 wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit);
111 popup->surface_commit.notify = popup_handle_surface_commit; 114 popup->surface_commit.notify = popup_handle_surface_commit;
@@ -114,9 +117,6 @@ static struct sway_xdg_popup *popup_create(
114 wl_signal_add(&wlr_popup->events.destroy, &popup->destroy); 117 wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
115 popup->destroy.notify = popup_handle_destroy; 118 popup->destroy.notify = popup_handle_destroy;
116 119
117 wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
118 wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
119
120 return popup; 120 return popup;
121} 121}
122 122
@@ -317,7 +317,6 @@ static void handle_commit(struct wl_listener *listener, void *data) {
317 // The client changed its surface size in this commit. For floating 317 // The client changed its surface size in this commit. For floating
318 // containers, we resize the container to match. For tiling containers, 318 // containers, we resize the container to match. For tiling containers,
319 // we only recenter the surface. 319 // we only recenter the surface.
320 desktop_damage_view(view);
321 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); 320 memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
322 if (container_is_floating(view->container)) { 321 if (container_is_floating(view->container)) {
323 view_update_size(view); 322 view_update_size(view);
@@ -330,15 +329,12 @@ static void handle_commit(struct wl_listener *listener, void *data) {
330 } else { 329 } else {
331 view_center_surface(view); 330 view_center_surface(view);
332 } 331 }
333 desktop_damage_view(view);
334 } 332 }
335 333
336 if (view->container->node.instruction) { 334 if (view->container->node.instruction) {
337 transaction_notify_view_ready_by_serial(view, 335 transaction_notify_view_ready_by_serial(view,
338 xdg_surface->current.configure_serial); 336 xdg_surface->current.configure_serial);
339 } 337 }
340
341 view_damage_from(view);
342} 338}
343 339
344static void handle_set_title(struct wl_listener *listener, void *data) { 340static void handle_set_title(struct wl_listener *listener, void *data) {
@@ -360,7 +356,16 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
360 struct sway_xdg_shell_view *xdg_shell_view = 356 struct sway_xdg_shell_view *xdg_shell_view =
361 wl_container_of(listener, xdg_shell_view, new_popup); 357 wl_container_of(listener, xdg_shell_view, new_popup);
362 struct wlr_xdg_popup *wlr_popup = data; 358 struct wlr_xdg_popup *wlr_popup = data;
363 popup_create(wlr_popup, &xdg_shell_view->view); 359
360 struct sway_xdg_popup *popup = popup_create(wlr_popup,
361 &xdg_shell_view->view, root->layers.popup);
362 if (!popup) {
363 return;
364 }
365
366 int lx, ly;
367 wlr_scene_node_coords(&popup->view->content_tree->node, &lx, &ly);
368 wlr_scene_node_set_position(&popup->scene_tree->node, lx, ly);
364} 369}
365 370
366static void handle_request_maximize(struct wl_listener *listener, void *data) { 371static void handle_request_maximize(struct wl_listener *listener, void *data) {
@@ -567,5 +572,7 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
567 xdg_shell_view->destroy.notify = handle_destroy; 572 xdg_shell_view->destroy.notify = handle_destroy;
568 wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy); 573 wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
569 574
575 wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
576
570 xdg_toplevel->base->data = xdg_shell_view; 577 xdg_toplevel->base->data = xdg_shell_view;
571} 578}
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 30df76f4..fd8f50d4 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -80,6 +80,7 @@ struct sway_node *node_at_coords(
80 while (true) { 80 while (true) {
81 struct sway_container *con = scene_descriptor_try_get(current, 81 struct sway_container *con = scene_descriptor_try_get(current,
82 SWAY_SCENE_DESC_CONTAINER); 82 SWAY_SCENE_DESC_CONTAINER);
83
83 if (!con) { 84 if (!con) {
84 struct sway_view *view = scene_descriptor_try_get(current, 85 struct sway_view *view = scene_descriptor_try_get(current,
85 SWAY_SCENE_DESC_VIEW); 86 SWAY_SCENE_DESC_VIEW);
@@ -88,12 +89,18 @@ struct sway_node *node_at_coords(
88 } 89 }
89 } 90 }
90 91
91 if (con) { 92 if (!con) {
92 if (!con->view || con->view->surface) { 93 struct sway_xdg_popup *popup =
93 return &con->node; 94 scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
95 if (popup) {
96 con = popup->view->container;
94 } 97 }
95 } 98 }
96 99
100 if (con && (!con->view || con->view->surface)) {
101 return &con->node;
102 }
103
97 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) { 104 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) {
98 // We don't want to feed through the current workspace on 105 // We don't want to feed through the current workspace on
99 // layer shells 106 // layer shells
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 7af2fd3f..ee25faf1 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -488,24 +488,6 @@ void view_for_each_popup_surface(struct sway_view *view,
488 view->impl->for_each_popup_surface(view, iterator, user_data); 488 view->impl->for_each_popup_surface(view, iterator, user_data);
489 } 489 }
490} 490}
491
492static void view_subsurface_create(struct sway_view *view,
493 struct wlr_subsurface *subsurface);
494
495static void view_init_subsurfaces(struct sway_view *view,
496 struct wlr_surface *surface);
497
498static void view_child_init_subsurfaces(struct sway_view_child *view_child,
499 struct wlr_surface *surface);
500
501static void view_handle_surface_new_subsurface(struct wl_listener *listener,
502 void *data) {
503 struct sway_view *view =
504 wl_container_of(listener, view, surface_new_subsurface);
505 struct wlr_subsurface *subsurface = data;
506 view_subsurface_create(view, subsurface);
507}
508
509static bool view_has_executed_criteria(struct sway_view *view, 491static bool view_has_executed_criteria(struct sway_view *view,
510 struct criteria *criteria) { 492 struct criteria *criteria) {
511 for (int i = 0; i < view->executed_criteria->length; ++i) { 493 for (int i = 0; i < view->executed_criteria->length; ++i) {
@@ -826,11 +808,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
826 } 808 }
827 ipc_event_window(view->container, "new"); 809 ipc_event_window(view->container, "new");
828 810
829 view_init_subsurfaces(view, wlr_surface);
830 wl_signal_add(&wlr_surface->events.new_subsurface,
831 &view->surface_new_subsurface);
832 view->surface_new_subsurface.notify = view_handle_surface_new_subsurface;
833
834 if (decoration) { 811 if (decoration) {
835 view_update_csd_from_client(view, decoration); 812 view_update_csd_from_client(view, decoration);
836 } 813 }
@@ -897,8 +874,6 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
897void view_unmap(struct sway_view *view) { 874void view_unmap(struct sway_view *view) {
898 wl_signal_emit_mutable(&view->events.unmap, view); 875 wl_signal_emit_mutable(&view->events.unmap, view);
899 876
900 wl_list_remove(&view->surface_new_subsurface.link);
901
902 view->executed_criteria->length = 0; 877 view->executed_criteria->length = 0;
903 878
904 if (view->urgent_timer) { 879 if (view->urgent_timer) {
@@ -962,253 +937,6 @@ void view_center_surface(struct sway_view *view) {
962 (con->current.content_height - view->geometry.height) / 2); 937 (con->current.content_height - view->geometry.height) / 2);
963} 938}
964 939
965static const struct sway_view_child_impl subsurface_impl;
966
967static void subsurface_get_view_coords(struct sway_view_child *child,
968 int *sx, int *sy) {
969 struct wlr_surface *surface = child->surface;
970 if (child->parent && child->parent->impl &&
971 child->parent->impl->get_view_coords) {
972 child->parent->impl->get_view_coords(child->parent, sx, sy);
973 } else {
974 *sx = *sy = 0;
975 }
976 struct wlr_subsurface *subsurface =
977 wlr_subsurface_try_from_wlr_surface(surface);
978 *sx += subsurface->current.x;
979 *sy += subsurface->current.y;
980}
981
982static void subsurface_destroy(struct sway_view_child *child) {
983 if (!sway_assert(child->impl == &subsurface_impl,
984 "Expected a subsurface")) {
985 return;
986 }
987 struct sway_subsurface *subsurface = (struct sway_subsurface *)child;
988 wl_list_remove(&subsurface->destroy.link);
989 free(subsurface);
990}
991
992static const struct sway_view_child_impl subsurface_impl = {
993 .get_view_coords = subsurface_get_view_coords,
994 .destroy = subsurface_destroy,
995};
996
997static void subsurface_handle_destroy(struct wl_listener *listener,
998 void *data) {
999 struct sway_subsurface *subsurface =
1000 wl_container_of(listener, subsurface, destroy);
1001 struct sway_view_child *child = &subsurface->child;
1002 view_child_destroy(child);
1003}
1004
1005static void view_child_damage(struct sway_view_child *child, bool whole);
1006
1007static void view_subsurface_create(struct sway_view *view,
1008 struct wlr_subsurface *wlr_subsurface) {
1009 struct sway_subsurface *subsurface =
1010 calloc(1, sizeof(struct sway_subsurface));
1011 if (subsurface == NULL) {
1012 sway_log(SWAY_ERROR, "Allocation failed");
1013 return;
1014 }
1015 view_child_init(&subsurface->child, &subsurface_impl, view,
1016 wlr_subsurface->surface);
1017
1018 wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
1019 subsurface->destroy.notify = subsurface_handle_destroy;
1020
1021 subsurface->child.mapped = true;
1022
1023 view_child_damage(&subsurface->child, true);
1024}
1025
1026static void view_child_subsurface_create(struct sway_view_child *child,
1027 struct wlr_subsurface *wlr_subsurface) {
1028 struct sway_subsurface *subsurface =
1029 calloc(1, sizeof(struct sway_subsurface));
1030 if (subsurface == NULL) {
1031 sway_log(SWAY_ERROR, "Allocation failed");
1032 return;
1033 }
1034 subsurface->child.parent = child;
1035 wl_list_insert(&child->children, &subsurface->child.link);
1036 view_child_init(&subsurface->child, &subsurface_impl, child->view,
1037 wlr_subsurface->surface);
1038
1039 wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
1040 subsurface->destroy.notify = subsurface_handle_destroy;
1041
1042 subsurface->child.mapped = true;
1043
1044 view_child_damage(&subsurface->child, true);
1045}
1046
1047static bool view_child_is_mapped(struct sway_view_child *child) {
1048 while (child) {
1049 if (!child->mapped) {
1050 return false;
1051 }
1052 child = child->parent;
1053 }
1054 return true;
1055}
1056
1057static void view_child_damage(struct sway_view_child *child, bool whole) {
1058 if (!child || !view_child_is_mapped(child) || !child->view || !child->view->container) {
1059 return;
1060 }
1061 int sx, sy;
1062 child->impl->get_view_coords(child, &sx, &sy);
1063 desktop_damage_surface(child->surface,
1064 child->view->container->pending.content_x -
1065 child->view->geometry.x + sx,
1066 child->view->container->pending.content_y -
1067 child->view->geometry.y + sy, whole);
1068}
1069
1070static void view_child_handle_surface_commit(struct wl_listener *listener,
1071 void *data) {
1072 struct sway_view_child *child =
1073 wl_container_of(listener, child, surface_commit);
1074 view_child_damage(child, false);
1075}
1076
1077static void view_child_handle_surface_new_subsurface(
1078 struct wl_listener *listener, void *data) {
1079 struct sway_view_child *child =
1080 wl_container_of(listener, child, surface_new_subsurface);
1081 struct wlr_subsurface *subsurface = data;
1082 view_child_subsurface_create(child, subsurface);
1083}
1084
1085static void view_child_handle_surface_destroy(struct wl_listener *listener,
1086 void *data) {
1087 struct sway_view_child *child =
1088 wl_container_of(listener, child, surface_destroy);
1089 view_child_destroy(child);
1090}
1091
1092static void view_init_subsurfaces(struct sway_view *view,
1093 struct wlr_surface *surface) {
1094 struct wlr_subsurface *subsurface;
1095 wl_list_for_each(subsurface, &surface->current.subsurfaces_below,
1096 current.link) {
1097 view_subsurface_create(view, subsurface);
1098 }
1099 wl_list_for_each(subsurface, &surface->current.subsurfaces_above,
1100 current.link) {
1101 view_subsurface_create(view, subsurface);
1102 }
1103}
1104
1105static void view_child_init_subsurfaces(struct sway_view_child *view_child,
1106 struct wlr_surface *surface) {
1107 struct wlr_subsurface *subsurface;
1108 wl_list_for_each(subsurface, &surface->current.subsurfaces_below,
1109 current.link) {
1110 view_child_subsurface_create(view_child, subsurface);
1111 }
1112 wl_list_for_each(subsurface, &surface->current.subsurfaces_above,
1113 current.link) {
1114 view_child_subsurface_create(view_child, subsurface);
1115 }
1116}
1117
1118static void view_child_handle_surface_map(struct wl_listener *listener,
1119 void *data) {
1120 struct sway_view_child *child =
1121 wl_container_of(listener, child, surface_map);
1122 child->mapped = true;
1123 view_child_damage(child, true);
1124}
1125
1126static void view_child_handle_surface_unmap(struct wl_listener *listener,
1127 void *data) {
1128 struct sway_view_child *child =
1129 wl_container_of(listener, child, surface_unmap);
1130 view_child_damage(child, true);
1131 child->mapped = false;
1132}
1133
1134static void view_child_handle_view_unmap(struct wl_listener *listener,
1135 void *data) {
1136 struct sway_view_child *child =
1137 wl_container_of(listener, child, view_unmap);
1138 view_child_damage(child, true);
1139 child->mapped = false;
1140}
1141
1142void view_child_init(struct sway_view_child *child,
1143 const struct sway_view_child_impl *impl, struct sway_view *view,
1144 struct wlr_surface *surface) {
1145 child->impl = impl;
1146 child->view = view;
1147 child->surface = surface;
1148 wl_list_init(&child->children);
1149
1150 wl_signal_add(&surface->events.commit, &child->surface_commit);
1151 child->surface_commit.notify = view_child_handle_surface_commit;
1152 wl_signal_add(&surface->events.new_subsurface,
1153 &child->surface_new_subsurface);
1154 child->surface_new_subsurface.notify =
1155 view_child_handle_surface_new_subsurface;
1156 wl_signal_add(&surface->events.destroy, &child->surface_destroy);
1157 child->surface_destroy.notify = view_child_handle_surface_destroy;
1158
1159 // Not all child views have a map/unmap event
1160 child->surface_map.notify = view_child_handle_surface_map;
1161 wl_list_init(&child->surface_map.link);
1162 child->surface_unmap.notify = view_child_handle_surface_unmap;
1163 wl_list_init(&child->surface_unmap.link);
1164
1165 wl_signal_add(&view->events.unmap, &child->view_unmap);
1166 child->view_unmap.notify = view_child_handle_view_unmap;
1167
1168 struct sway_container *container = child->view->container;
1169 if (container != NULL) {
1170 struct sway_workspace *workspace = container->pending.workspace;
1171 if (workspace) {
1172 surface_enter_output(child->surface, workspace->output);
1173 }
1174 }
1175
1176 view_child_init_subsurfaces(child, surface);
1177}
1178
1179void view_child_destroy(struct sway_view_child *child) {
1180 if (view_child_is_mapped(child) && child->view->container != NULL) {
1181 view_child_damage(child, true);
1182 }
1183
1184 if (child->parent != NULL) {
1185 wl_list_remove(&child->link);
1186 child->parent = NULL;
1187 }
1188
1189 struct sway_view_child *subchild, *tmpchild;
1190 wl_list_for_each_safe(subchild, tmpchild, &child->children, link) {
1191 wl_list_remove(&subchild->link);
1192 subchild->parent = NULL;
1193 // The subchild lost its parent link, so it cannot see that the parent
1194 // is unmapped. Unmap it directly.
1195 subchild->mapped = false;
1196 }
1197
1198 wl_list_remove(&child->surface_commit.link);
1199 wl_list_remove(&child->surface_destroy.link);
1200 wl_list_remove(&child->surface_map.link);
1201 wl_list_remove(&child->surface_unmap.link);
1202 wl_list_remove(&child->view_unmap.link);
1203 wl_list_remove(&child->surface_new_subsurface.link);
1204
1205 if (child->impl && child->impl->destroy) {
1206 child->impl->destroy(child);
1207 } else {
1208 free(child);
1209 }
1210}
1211
1212struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) { 940struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
1213 struct wlr_xdg_surface *xdg_surface; 941 struct wlr_xdg_surface *xdg_surface;
1214 if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) { 942 if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) {