diff options
-rw-r--r-- | include/sway/desktop.h | 7 | ||||
-rw-r--r-- | include/sway/output.h | 6 | ||||
-rw-r--r-- | include/sway/tree/container.h | 8 | ||||
-rw-r--r-- | include/sway/tree/view.h | 50 | ||||
-rw-r--r-- | sway/desktop/desktop.c | 20 | ||||
-rw-r--r-- | sway/desktop/output.c | 25 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 1 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 73 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 132 | ||||
-rw-r--r-- | sway/input/cursor.c | 14 | ||||
-rw-r--r-- | sway/meson.build | 1 | ||||
-rw-r--r-- | sway/tree/container.c | 11 | ||||
-rw-r--r-- | sway/tree/view.c | 112 |
13 files changed, 409 insertions, 51 deletions
diff --git a/include/sway/desktop.h b/include/sway/desktop.h new file mode 100644 index 00000000..96bdc94c --- /dev/null +++ b/include/sway/desktop.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #include <wlr/types/wlr_surface.h> | ||
2 | |||
3 | void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, | ||
4 | double ly); | ||
5 | |||
6 | void desktop_damage_from_surface(struct wlr_surface *surface, double lx, | ||
7 | double ly); | ||
diff --git a/include/sway/output.h b/include/sway/output.h index 98d0f83f..4bffa2b7 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -34,9 +34,15 @@ struct sway_output { | |||
34 | 34 | ||
35 | void output_damage_whole(struct sway_output *output); | 35 | void output_damage_whole(struct sway_output *output); |
36 | 36 | ||
37 | void output_damage_whole_surface(struct sway_output *output, | ||
38 | double ox, double oy, struct wlr_surface *surface); | ||
39 | |||
37 | void output_damage_whole_view(struct sway_output *output, | 40 | void output_damage_whole_view(struct sway_output *output, |
38 | struct sway_view *view); | 41 | struct sway_view *view); |
39 | 42 | ||
43 | void output_damage_whole_container(struct sway_output *output, | ||
44 | struct sway_container *con); | ||
45 | |||
40 | struct sway_container *output_by_name(const char *name); | 46 | struct sway_container *output_by_name(const char *name); |
41 | 47 | ||
42 | #endif | 48 | #endif |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 3a3a9429..7acb607b 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -97,8 +97,7 @@ struct sway_container *container_create(enum sway_container_type type); | |||
97 | 97 | ||
98 | const char *container_type_to_str(enum sway_container_type type); | 98 | const char *container_type_to_str(enum sway_container_type type); |
99 | 99 | ||
100 | struct sway_container *output_create( | 100 | struct sway_container *output_create(struct sway_output *sway_output); |
101 | struct sway_output *sway_output); | ||
102 | 101 | ||
103 | /** | 102 | /** |
104 | * Create a new container container. A container container can be a a child of | 103 | * Create a new container container. A container container can be a a child of |
@@ -116,7 +115,8 @@ struct sway_container *output_create(struct sway_output *sway_output); | |||
116 | * Create a new workspace container. Workspaces are children of an output | 115 | * Create a new workspace container. Workspaces are children of an output |
117 | * container and are ordered alphabetically by name. | 116 | * container and are ordered alphabetically by name. |
118 | */ | 117 | */ |
119 | struct sway_container *workspace_create(struct sway_container *output, const char *name); | 118 | struct sway_container *workspace_create(struct sway_container *output, |
119 | const char *name); | ||
120 | 120 | ||
121 | /* | 121 | /* |
122 | * Create a new view container. A view can be a child of a workspace container | 122 | * Create a new view container. A view can be a child of a workspace container |
@@ -182,4 +182,6 @@ bool container_has_child(struct sway_container *con, | |||
182 | 182 | ||
183 | void container_create_notify(struct sway_container *container); | 183 | void container_create_notify(struct sway_container *container); |
184 | 184 | ||
185 | void container_damage_whole(struct sway_container *container); | ||
186 | |||
185 | #endif | 187 | #endif |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index d4dace4a..03d27ceb 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -45,6 +45,12 @@ struct sway_view { | |||
45 | struct wlr_xwayland_surface *wlr_xwayland_surface; | 45 | struct wlr_xwayland_surface *wlr_xwayland_surface; |
46 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; | 46 | struct wlr_wl_shell_surface *wlr_wl_shell_surface; |
47 | }; | 47 | }; |
48 | |||
49 | struct { | ||
50 | struct wl_signal unmap; | ||
51 | } events; | ||
52 | |||
53 | struct wl_listener surface_new_subsurface; | ||
48 | }; | 54 | }; |
49 | 55 | ||
50 | struct sway_xdg_shell_v6_view { | 56 | struct sway_xdg_shell_v6_view { |
@@ -54,6 +60,7 @@ struct sway_xdg_shell_v6_view { | |||
54 | struct wl_listener request_move; | 60 | struct wl_listener request_move; |
55 | struct wl_listener request_resize; | 61 | struct wl_listener request_resize; |
56 | struct wl_listener request_maximize; | 62 | struct wl_listener request_maximize; |
63 | struct wl_listener new_popup; | ||
57 | struct wl_listener map; | 64 | struct wl_listener map; |
58 | struct wl_listener unmap; | 65 | struct wl_listener unmap; |
59 | struct wl_listener destroy; | 66 | struct wl_listener destroy; |
@@ -80,6 +87,12 @@ struct sway_xwayland_unmanaged { | |||
80 | struct wlr_xwayland_surface *wlr_xwayland_surface; | 87 | struct wlr_xwayland_surface *wlr_xwayland_surface; |
81 | struct wl_list link; | 88 | struct wl_list link; |
82 | 89 | ||
90 | int lx, ly; | ||
91 | |||
92 | struct wl_listener request_configure; | ||
93 | struct wl_listener commit; | ||
94 | struct wl_listener map; | ||
95 | struct wl_listener unmap; | ||
83 | struct wl_listener destroy; | 96 | struct wl_listener destroy; |
84 | }; | 97 | }; |
85 | 98 | ||
@@ -95,6 +108,37 @@ struct sway_wl_shell_view { | |||
95 | int pending_width, pending_height; | 108 | int pending_width, pending_height; |
96 | }; | 109 | }; |
97 | 110 | ||
111 | struct sway_view_child; | ||
112 | |||
113 | struct sway_view_child_impl { | ||
114 | void (*destroy)(struct sway_view_child *child); | ||
115 | }; | ||
116 | |||
117 | /** | ||
118 | * A view child is a surface in the view tree, such as a subsurface or a popup. | ||
119 | */ | ||
120 | struct sway_view_child { | ||
121 | const struct sway_view_child_impl *impl; | ||
122 | |||
123 | struct sway_view *view; | ||
124 | struct wlr_surface *surface; | ||
125 | |||
126 | struct wl_listener surface_commit; | ||
127 | struct wl_listener surface_new_subsurface; | ||
128 | struct wl_listener surface_destroy; | ||
129 | struct wl_listener view_unmap; | ||
130 | }; | ||
131 | |||
132 | struct sway_xdg_popup_v6 { | ||
133 | struct sway_view_child child; | ||
134 | |||
135 | struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; | ||
136 | |||
137 | struct wl_listener new_popup; | ||
138 | struct wl_listener unmap; | ||
139 | struct wl_listener destroy; | ||
140 | }; | ||
141 | |||
98 | const char *view_get_title(struct sway_view *view); | 142 | const char *view_get_title(struct sway_view *view); |
99 | 143 | ||
100 | const char *view_get_app_id(struct sway_view *view); | 144 | const char *view_get_app_id(struct sway_view *view); |
@@ -129,4 +173,10 @@ void view_update_position(struct sway_view *view, double ox, double oy); | |||
129 | 173 | ||
130 | void view_update_size(struct sway_view *view, int width, int height); | 174 | void view_update_size(struct sway_view *view, int width, int height); |
131 | 175 | ||
176 | void view_child_init(struct sway_view_child *child, | ||
177 | const struct sway_view_child_impl *impl, struct sway_view *view, | ||
178 | struct wlr_surface *surface); | ||
179 | |||
180 | void view_child_destroy(struct sway_view_child *child); | ||
181 | |||
132 | #endif | 182 | #endif |
diff --git a/sway/desktop/desktop.c b/sway/desktop/desktop.c new file mode 100644 index 00000000..3a13191f --- /dev/null +++ b/sway/desktop/desktop.c | |||
@@ -0,0 +1,20 @@ | |||
1 | #include "sway/tree/container.h" | ||
2 | #include "sway/desktop.h" | ||
3 | #include "sway/output.h" | ||
4 | |||
5 | void desktop_damage_whole_surface(struct wlr_surface *surface, double lx, | ||
6 | double ly) { | ||
7 | for (int i = 0; i < root_container.children->length; ++i) { | ||
8 | struct sway_container *cont = root_container.children->items[i]; | ||
9 | if (cont->type == C_OUTPUT) { | ||
10 | output_damage_whole_surface(cont->sway_output, | ||
11 | lx - cont->x, ly - cont->y, surface); | ||
12 | } | ||
13 | } | ||
14 | } | ||
15 | |||
16 | void desktop_damage_from_surface(struct wlr_surface *surface, double lx, | ||
17 | double ly) { | ||
18 | // TODO | ||
19 | desktop_damage_whole_surface(surface, lx, ly); | ||
20 | } | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 0e8a9485..aa18f1b8 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -267,17 +267,14 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
267 | 267 | ||
268 | // render unmanaged views on top | 268 | // render unmanaged views on top |
269 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; | 269 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
270 | struct sway_xwayland_unmanaged *sway_surface; | 270 | struct sway_xwayland_unmanaged *unmanaged_surface; |
271 | wl_list_for_each(sway_surface, unmanaged, link) { | 271 | wl_list_for_each(unmanaged_surface, unmanaged, link) { |
272 | struct wlr_xwayland_surface *xsurface = | 272 | struct wlr_xwayland_surface *xsurface = |
273 | sway_surface->wlr_xwayland_surface; | 273 | unmanaged_surface->wlr_xwayland_surface; |
274 | if (xsurface->surface == NULL) { | ||
275 | continue; | ||
276 | } | ||
277 | 274 | ||
278 | const struct wlr_box view_box = { | 275 | const struct wlr_box view_box = { |
279 | .x = xsurface->x, | 276 | .x = unmanaged_surface->lx, |
280 | .y = xsurface->y, | 277 | .y = unmanaged_surface->ly, |
281 | .width = xsurface->width, | 278 | .width = xsurface->width, |
282 | .height = xsurface->height, | 279 | .height = xsurface->height, |
283 | }; | 280 | }; |
@@ -335,12 +332,24 @@ void output_damage_whole(struct sway_output *output) { | |||
335 | wlr_output_damage_add_whole(output->damage); | 332 | wlr_output_damage_add_whole(output->damage); |
336 | } | 333 | } |
337 | 334 | ||
335 | void output_damage_whole_surface(struct sway_output *output, | ||
336 | double ox, double oy, struct wlr_surface *surface) { | ||
337 | // TODO | ||
338 | output_damage_whole(output); | ||
339 | } | ||
340 | |||
338 | void output_damage_whole_view(struct sway_output *output, | 341 | void output_damage_whole_view(struct sway_output *output, |
339 | struct sway_view *view) { | 342 | struct sway_view *view) { |
340 | // TODO | 343 | // TODO |
341 | output_damage_whole(output); | 344 | output_damage_whole(output); |
342 | } | 345 | } |
343 | 346 | ||
347 | void output_damage_whole_container(struct sway_output *output, | ||
348 | struct sway_container *con) { | ||
349 | // TODO | ||
350 | output_damage_whole(output); | ||
351 | } | ||
352 | |||
344 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 353 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |
345 | struct sway_output *output = | 354 | struct sway_output *output = |
346 | wl_container_of(listener, output, damage_destroy); | 355 | wl_container_of(listener, output, damage_destroy); |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index 5955fa9d..fff31da8 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -68,6 +68,7 @@ static const struct sway_view_impl view_impl = { | |||
68 | .get_prop = get_prop, | 68 | .get_prop = get_prop, |
69 | .configure = configure, | 69 | .configure = configure, |
70 | .close = _close, | 70 | .close = _close, |
71 | .destroy = destroy, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | static void handle_commit(struct wl_listener *listener, void *data) { | 74 | static void handle_commit(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 7b9d5fb7..c66cc39a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -11,6 +11,66 @@ | |||
11 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
12 | #include "log.h" | 12 | #include "log.h" |
13 | 13 | ||
14 | static const struct sway_view_child_impl popup_impl; | ||
15 | |||
16 | static void popup_destroy(struct sway_view_child *child) { | ||
17 | if (!sway_assert(child->impl == &popup_impl, | ||
18 | "Expected an xdg_shell_v6 popup")) { | ||
19 | return; | ||
20 | } | ||
21 | struct sway_xdg_popup_v6 *popup = (struct sway_xdg_popup_v6 *)child; | ||
22 | wl_list_remove(&popup->new_popup.link); | ||
23 | wl_list_remove(&popup->unmap.link); | ||
24 | wl_list_remove(&popup->destroy.link); | ||
25 | free(popup); | ||
26 | } | ||
27 | |||
28 | static const struct sway_view_child_impl popup_impl = { | ||
29 | .destroy = popup_destroy, | ||
30 | }; | ||
31 | |||
32 | static struct sway_xdg_popup_v6 *popup_create( | ||
33 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view); | ||
34 | |||
35 | static void popup_handle_new_popup(struct wl_listener *listener, void *data) { | ||
36 | struct sway_xdg_popup_v6 *popup = | ||
37 | wl_container_of(listener, popup, new_popup); | ||
38 | struct wlr_xdg_popup_v6 *wlr_popup = data; | ||
39 | popup_create(wlr_popup, popup->child.view); | ||
40 | } | ||
41 | |||
42 | static void popup_handle_unmap(struct wl_listener *listener, void *data) { | ||
43 | struct sway_xdg_popup_v6 *popup = wl_container_of(listener, popup, unmap); | ||
44 | view_child_destroy(&popup->child); | ||
45 | } | ||
46 | |||
47 | static void popup_handle_destroy(struct wl_listener *listener, void *data) { | ||
48 | struct sway_xdg_popup_v6 *popup = wl_container_of(listener, popup, destroy); | ||
49 | view_child_destroy(&popup->child); | ||
50 | } | ||
51 | |||
52 | static struct sway_xdg_popup_v6 *popup_create( | ||
53 | struct wlr_xdg_popup_v6 *wlr_popup, struct sway_view *view) { | ||
54 | struct wlr_xdg_surface_v6 *xdg_surface = wlr_popup->base; | ||
55 | |||
56 | struct sway_xdg_popup_v6 *popup = | ||
57 | calloc(1, sizeof(struct sway_xdg_popup_v6)); | ||
58 | if (popup == NULL) { | ||
59 | return NULL; | ||
60 | } | ||
61 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | ||
62 | |||
63 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | ||
64 | popup->new_popup.notify = popup_handle_new_popup; | ||
65 | wl_signal_add(&xdg_surface->events.unmap, &popup->unmap); | ||
66 | popup->unmap.notify = popup_handle_unmap; | ||
67 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | ||
68 | popup->destroy.notify = popup_handle_destroy; | ||
69 | |||
70 | return popup; | ||
71 | } | ||
72 | |||
73 | |||
14 | static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view( | 74 | static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view( |
15 | struct sway_view *view) { | 75 | struct sway_view *view) { |
16 | if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, | 76 | if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, |
@@ -76,6 +136,7 @@ static void destroy(struct sway_view *view) { | |||
76 | } | 136 | } |
77 | wl_list_remove(&xdg_shell_v6_view->commit.link); | 137 | wl_list_remove(&xdg_shell_v6_view->commit.link); |
78 | wl_list_remove(&xdg_shell_v6_view->destroy.link); | 138 | wl_list_remove(&xdg_shell_v6_view->destroy.link); |
139 | wl_list_remove(&xdg_shell_v6_view->new_popup.link); | ||
79 | wl_list_remove(&xdg_shell_v6_view->map.link); | 140 | wl_list_remove(&xdg_shell_v6_view->map.link); |
80 | wl_list_remove(&xdg_shell_v6_view->unmap.link); | 141 | wl_list_remove(&xdg_shell_v6_view->unmap.link); |
81 | free(xdg_shell_v6_view); | 142 | free(xdg_shell_v6_view); |
@@ -86,6 +147,7 @@ static const struct sway_view_impl view_impl = { | |||
86 | .configure = configure, | 147 | .configure = configure, |
87 | .set_activated = set_activated, | 148 | .set_activated = set_activated, |
88 | .close = _close, | 149 | .close = _close, |
150 | .destroy = destroy, | ||
89 | }; | 151 | }; |
90 | 152 | ||
91 | static void handle_commit(struct wl_listener *listener, void *data) { | 153 | static void handle_commit(struct wl_listener *listener, void *data) { |
@@ -100,6 +162,13 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
100 | view_damage_from(view); | 162 | view_damage_from(view); |
101 | } | 163 | } |
102 | 164 | ||
165 | static void handle_new_popup(struct wl_listener *listener, void *data) { | ||
166 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = | ||
167 | wl_container_of(listener, xdg_shell_v6_view, new_popup); | ||
168 | struct wlr_xdg_popup_v6 *wlr_popup = data; | ||
169 | popup_create(wlr_popup, &xdg_shell_v6_view->view); | ||
170 | } | ||
171 | |||
103 | static void handle_unmap(struct wl_listener *listener, void *data) { | 172 | static void handle_unmap(struct wl_listener *listener, void *data) { |
104 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = | 173 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = |
105 | wl_container_of(listener, xdg_shell_v6_view, unmap); | 174 | wl_container_of(listener, xdg_shell_v6_view, unmap); |
@@ -151,6 +220,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
151 | wl_signal_add(&xdg_surface->surface->events.commit, | 220 | wl_signal_add(&xdg_surface->surface->events.commit, |
152 | &xdg_shell_v6_view->commit); | 221 | &xdg_shell_v6_view->commit); |
153 | 222 | ||
223 | xdg_shell_v6_view->new_popup.notify = handle_new_popup; | ||
224 | wl_signal_add(&xdg_surface->events.new_popup, | ||
225 | &xdg_shell_v6_view->new_popup); | ||
226 | |||
154 | xdg_shell_v6_view->map.notify = handle_map; | 227 | xdg_shell_v6_view->map.notify = handle_map; |
155 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); | 228 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map); |
156 | 229 | ||
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 384f4236..e3da1da7 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -2,42 +2,110 @@ | |||
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <wayland-server.h> | 4 | #include <wayland-server.h> |
5 | #include <wlr/xwayland.h> | ||
6 | #include <wlr/types/wlr_output_layout.h> | 5 | #include <wlr/types/wlr_output_layout.h> |
7 | #include <wlr/types/wlr_output.h> | 6 | #include <wlr/types/wlr_output.h> |
7 | #include <wlr/xwayland.h> | ||
8 | #include "log.h" | ||
9 | #include "sway/desktop.h" | ||
10 | #include "sway/input/input-manager.h" | ||
11 | #include "sway/input/seat.h" | ||
12 | #include "sway/output.h" | ||
13 | #include "sway/server.h" | ||
8 | #include "sway/tree/container.h" | 14 | #include "sway/tree/container.h" |
9 | #include "sway/tree/layout.h" | 15 | #include "sway/tree/layout.h" |
10 | #include "sway/server.h" | ||
11 | #include "sway/tree/view.h" | 16 | #include "sway/tree/view.h" |
12 | #include "sway/output.h" | ||
13 | #include "sway/input/seat.h" | ||
14 | #include "sway/input/input-manager.h" | ||
15 | #include "log.h" | ||
16 | 17 | ||
17 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { | 18 | static void unmanaged_handle_request_configure(struct wl_listener *listener, |
18 | struct sway_xwayland_unmanaged *sway_surface = | 19 | void *data) { |
19 | wl_container_of(listener, sway_surface, destroy); | 20 | struct sway_xwayland_unmanaged *surface = |
20 | wl_list_remove(&sway_surface->destroy.link); | 21 | wl_container_of(listener, surface, request_configure); |
21 | wl_list_remove(&sway_surface->link); | 22 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; |
22 | free(sway_surface); | 23 | struct wlr_xwayland_surface_configure_event *ev = data; |
24 | wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, | ||
25 | ev->width, ev->height); | ||
23 | } | 26 | } |
24 | 27 | ||
25 | static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { | 28 | static void unmanaged_handle_commit(struct wl_listener *listener, void *data) { |
26 | struct sway_xwayland_unmanaged *sway_surface = | 29 | struct sway_xwayland_unmanaged *surface = |
27 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | 30 | wl_container_of(listener, surface, commit); |
28 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { | 31 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; |
29 | return; | 32 | |
33 | if (xsurface->x != surface->lx || xsurface->y != surface->ly) { | ||
34 | // Surface has moved | ||
35 | desktop_damage_whole_surface(xsurface->surface, | ||
36 | surface->lx, surface->ly); | ||
37 | surface->lx = xsurface->x; | ||
38 | surface->ly = xsurface->y; | ||
39 | desktop_damage_whole_surface(xsurface->surface, | ||
40 | surface->lx, surface->ly); | ||
41 | } else { | ||
42 | desktop_damage_from_surface(xsurface->surface, | ||
43 | xsurface->x, xsurface->y); | ||
30 | } | 44 | } |
45 | } | ||
31 | 46 | ||
32 | sway_surface->wlr_xwayland_surface = xsurface; | 47 | static void unmanaged_handle_map(struct wl_listener *listener, void *data) { |
33 | 48 | struct sway_xwayland_unmanaged *surface = | |
34 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); | 49 | wl_container_of(listener, surface, map); |
35 | sway_surface->destroy.notify = unmanaged_handle_destroy; | 50 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; |
36 | 51 | ||
37 | wl_list_insert(&root_container.sway_root->xwayland_unmanaged, | 52 | wl_list_insert(&root_container.sway_root->xwayland_unmanaged, |
38 | &sway_surface->link); | 53 | &surface->link); |
54 | |||
55 | wl_signal_add(&xsurface->surface->events.commit, &surface->commit); | ||
56 | surface->commit.notify = unmanaged_handle_commit; | ||
57 | |||
58 | surface->lx = xsurface->x; | ||
59 | surface->ly = xsurface->y; | ||
60 | desktop_damage_whole_surface(xsurface->surface, surface->lx, surface->ly); | ||
61 | } | ||
62 | |||
63 | static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) { | ||
64 | struct sway_xwayland_unmanaged *surface = | ||
65 | wl_container_of(listener, surface, unmap); | ||
66 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; | ||
67 | desktop_damage_whole_surface(xsurface->surface, xsurface->x, xsurface->y); | ||
68 | wl_list_remove(&surface->link); | ||
69 | wl_list_remove(&surface->commit.link); | ||
70 | } | ||
39 | 71 | ||
40 | // TODO: damage tracking | 72 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { |
73 | struct sway_xwayland_unmanaged *surface = | ||
74 | wl_container_of(listener, surface, destroy); | ||
75 | struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; | ||
76 | if (xsurface->mapped) { | ||
77 | unmanaged_handle_unmap(&surface->unmap, xsurface); | ||
78 | } | ||
79 | wl_list_remove(&surface->map.link); | ||
80 | wl_list_remove(&surface->unmap.link); | ||
81 | wl_list_remove(&surface->destroy.link); | ||
82 | free(surface); | ||
83 | } | ||
84 | |||
85 | static struct sway_xwayland_unmanaged *create_unmanaged( | ||
86 | struct wlr_xwayland_surface *xsurface) { | ||
87 | struct sway_xwayland_unmanaged *surface = | ||
88 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | ||
89 | if (surface == NULL) { | ||
90 | wlr_log(L_ERROR, "Allocation failed"); | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | surface->wlr_xwayland_surface = xsurface; | ||
95 | |||
96 | wl_signal_add(&xsurface->events.request_configure, | ||
97 | &surface->request_configure); | ||
98 | surface->request_configure.notify = unmanaged_handle_request_configure; | ||
99 | wl_signal_add(&xsurface->events.map, &surface->map); | ||
100 | surface->map.notify = unmanaged_handle_map; | ||
101 | wl_signal_add(&xsurface->events.unmap, &surface->unmap); | ||
102 | surface->unmap.notify = unmanaged_handle_unmap; | ||
103 | wl_signal_add(&xsurface->events.destroy, &surface->destroy); | ||
104 | surface->destroy.notify = unmanaged_handle_destroy; | ||
105 | |||
106 | unmanaged_handle_map(&surface->map, xsurface); | ||
107 | |||
108 | return surface; | ||
41 | } | 109 | } |
42 | 110 | ||
43 | 111 | ||
@@ -127,6 +195,7 @@ static const struct sway_view_impl view_impl = { | |||
127 | .configure = configure, | 195 | .configure = configure, |
128 | .set_activated = set_activated, | 196 | .set_activated = set_activated, |
129 | .close = _close, | 197 | .close = _close, |
198 | .destroy = destroy, | ||
130 | }; | 199 | }; |
131 | 200 | ||
132 | static void handle_commit(struct wl_listener *listener, void *data) { | 201 | static void handle_commit(struct wl_listener *listener, void *data) { |
@@ -140,12 +209,6 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
140 | view_damage_from(view); | 209 | view_damage_from(view); |
141 | } | 210 | } |
142 | 211 | ||
143 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
144 | struct sway_xwayland_view *xwayland_view = | ||
145 | wl_container_of(listener, xwayland_view, destroy); | ||
146 | view_destroy(&xwayland_view->view); | ||
147 | } | ||
148 | |||
149 | static void handle_unmap(struct wl_listener *listener, void *data) { | 212 | static void handle_unmap(struct wl_listener *listener, void *data) { |
150 | struct sway_xwayland_view *xwayland_view = | 213 | struct sway_xwayland_view *xwayland_view = |
151 | wl_container_of(listener, xwayland_view, unmap); | 214 | wl_container_of(listener, xwayland_view, unmap); |
@@ -169,6 +232,17 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
169 | view_map(view, xsurface->surface); | 232 | view_map(view, xsurface->surface); |
170 | } | 233 | } |
171 | 234 | ||
235 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
236 | struct sway_xwayland_view *xwayland_view = | ||
237 | wl_container_of(listener, xwayland_view, destroy); | ||
238 | struct sway_view *view = &xwayland_view->view; | ||
239 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
240 | if (xsurface->mapped) { | ||
241 | handle_unmap(&xwayland_view->unmap, xsurface); | ||
242 | } | ||
243 | view_destroy(&xwayland_view->view); | ||
244 | } | ||
245 | |||
172 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 246 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
173 | struct sway_xwayland_view *xwayland_view = | 247 | struct sway_xwayland_view *xwayland_view = |
174 | wl_container_of(listener, xwayland_view, request_configure); | 248 | wl_container_of(listener, xwayland_view, request_configure); |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 195ddce9..b83bc9fe 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -48,17 +48,13 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, | |||
48 | struct wlr_surface **surface, double *sx, double *sy) { | 48 | struct wlr_surface **surface, double *sx, double *sy) { |
49 | // check for unmanaged views first | 49 | // check for unmanaged views first |
50 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; | 50 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
51 | struct sway_xwayland_unmanaged *sway_surface; | 51 | struct sway_xwayland_unmanaged *unmanaged_surface; |
52 | wl_list_for_each_reverse(sway_surface, unmanaged, link) { | 52 | wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { |
53 | struct wlr_xwayland_surface *xsurface = | 53 | struct wlr_xwayland_surface *xsurface = |
54 | sway_surface->wlr_xwayland_surface; | 54 | unmanaged_surface->wlr_xwayland_surface; |
55 | if (xsurface->surface == NULL) { | ||
56 | continue; | ||
57 | } | ||
58 | |||
59 | struct wlr_box box = { | 55 | struct wlr_box box = { |
60 | .x = xsurface->x, | 56 | .x = unmanaged_surface->lx, |
61 | .y = xsurface->y, | 57 | .y = unmanaged_surface->ly, |
62 | .width = xsurface->width, | 58 | .width = xsurface->width, |
63 | .height = xsurface->height, | 59 | .height = xsurface->height, |
64 | }; | 60 | }; |
diff --git a/sway/meson.build b/sway/meson.build index ec7b4c42..29aaa7b7 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -8,6 +8,7 @@ sway_sources = files( | |||
8 | 'ipc-server.c', | 8 | 'ipc-server.c', |
9 | 'security.c', | 9 | 'security.c', |
10 | 10 | ||
11 | 'desktop/desktop.c', | ||
11 | 'desktop/output.c', | 12 | 'desktop/output.c', |
12 | 'desktop/layer_shell.c', | 13 | 'desktop/layer_shell.c', |
13 | 'desktop/wl_shell.c', | 14 | 'desktop/wl_shell.c', |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 3e8c1c75..41321dc8 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -514,9 +514,16 @@ static bool find_child_func(struct sway_container *con, void *data) { | |||
514 | 514 | ||
515 | bool container_has_child(struct sway_container *con, | 515 | bool container_has_child(struct sway_container *con, |
516 | struct sway_container *child) { | 516 | struct sway_container *child) { |
517 | if (con == NULL || con->type == C_VIEW || | 517 | if (con == NULL || con->type == C_VIEW || con->children->length == 0) { |
518 | con->children->length == 0) { | ||
519 | return false; | 518 | return false; |
520 | } | 519 | } |
521 | return container_find(con, find_child_func, child); | 520 | return container_find(con, find_child_func, child); |
522 | } | 521 | } |
522 | |||
523 | void container_damage_whole(struct sway_container *con) { | ||
524 | struct sway_container *output = con; | ||
525 | if (output->type != C_OUTPUT) { | ||
526 | output = container_parent(output, C_OUTPUT); | ||
527 | } | ||
528 | output_damage_whole_container(output->sway_output, con); | ||
529 | } | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 3927c195..d3e3186c 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -11,6 +11,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
11 | const struct sway_view_impl *impl) { | 11 | const struct sway_view_impl *impl) { |
12 | view->type = type; | 12 | view->type = type; |
13 | view->impl = impl; | 13 | view->impl = impl; |
14 | wl_signal_init(&view->events.unmap); | ||
14 | } | 15 | } |
15 | 16 | ||
16 | void view_destroy(struct sway_view *view) { | 17 | void view_destroy(struct sway_view *view) { |
@@ -123,6 +124,20 @@ static void view_update_outputs(struct sway_view *view, | |||
123 | } | 124 | } |
124 | } | 125 | } |
125 | 126 | ||
127 | static void view_subsurface_create(struct sway_view *view, | ||
128 | struct wlr_subsurface *subsurface); | ||
129 | |||
130 | static void view_init_subsurfaces(struct sway_view *view, | ||
131 | struct wlr_surface *surface); | ||
132 | |||
133 | static void view_handle_surface_new_subsurface(struct wl_listener *listener, | ||
134 | void *data) { | ||
135 | struct sway_view *view = | ||
136 | wl_container_of(listener, view, surface_new_subsurface); | ||
137 | struct wlr_subsurface *subsurface = data; | ||
138 | view_subsurface_create(view, subsurface); | ||
139 | } | ||
140 | |||
126 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | 141 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
127 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { | 142 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
128 | return; | 143 | return; |
@@ -136,6 +151,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
136 | view->surface = wlr_surface; | 151 | view->surface = wlr_surface; |
137 | view->swayc = cont; | 152 | view->swayc = cont; |
138 | 153 | ||
154 | view_init_subsurfaces(view, wlr_surface); | ||
155 | wl_signal_add(&wlr_surface->events.new_subsurface, | ||
156 | &view->surface_new_subsurface); | ||
157 | view->surface_new_subsurface.notify = view_handle_surface_new_subsurface; | ||
158 | |||
139 | arrange_windows(cont->parent, -1, -1); | 159 | arrange_windows(cont->parent, -1, -1); |
140 | input_manager_set_focus(input_manager, cont); | 160 | input_manager_set_focus(input_manager, cont); |
141 | 161 | ||
@@ -148,10 +168,14 @@ void view_unmap(struct sway_view *view) { | |||
148 | return; | 168 | return; |
149 | } | 169 | } |
150 | 170 | ||
171 | wl_signal_emit(&view->events.unmap, view); | ||
172 | |||
151 | view_damage_whole(view); | 173 | view_damage_whole(view); |
152 | 174 | ||
153 | struct sway_container *parent = container_destroy(view->swayc); | 175 | struct sway_container *parent = container_destroy(view->swayc); |
154 | 176 | ||
177 | wl_list_remove(&view->surface_new_subsurface.link); | ||
178 | |||
155 | view->swayc = NULL; | 179 | view->swayc = NULL; |
156 | view->surface = NULL; | 180 | view->surface = NULL; |
157 | 181 | ||
@@ -185,3 +209,91 @@ void view_update_size(struct sway_view *view, int width, int height) { | |||
185 | view_update_outputs(view, &box); | 209 | view_update_outputs(view, &box); |
186 | view_damage_whole(view); | 210 | view_damage_whole(view); |
187 | } | 211 | } |
212 | |||
213 | |||
214 | static void view_subsurface_create(struct sway_view *view, | ||
215 | struct wlr_subsurface *subsurface) { | ||
216 | struct sway_view_child *child = calloc(1, sizeof(struct sway_view_child)); | ||
217 | if (child == NULL) { | ||
218 | wlr_log(L_ERROR, "Allocation failed"); | ||
219 | return; | ||
220 | } | ||
221 | view_child_init(child, NULL, view, subsurface->surface); | ||
222 | } | ||
223 | |||
224 | static void view_child_handle_surface_commit(struct wl_listener *listener, | ||
225 | void *data) { | ||
226 | struct sway_view_child *child = | ||
227 | wl_container_of(listener, child, surface_commit); | ||
228 | // TODO: only accumulate damage from the child | ||
229 | view_damage_from(child->view); | ||
230 | } | ||
231 | |||
232 | static void view_child_handle_surface_new_subsurface( | ||
233 | struct wl_listener *listener, void *data) { | ||
234 | struct sway_view_child *child = | ||
235 | wl_container_of(listener, child, surface_new_subsurface); | ||
236 | struct wlr_subsurface *subsurface = data; | ||
237 | view_subsurface_create(child->view, subsurface); | ||
238 | } | ||
239 | |||
240 | static void view_child_handle_surface_destroy(struct wl_listener *listener, | ||
241 | void *data) { | ||
242 | struct sway_view_child *child = | ||
243 | wl_container_of(listener, child, surface_destroy); | ||
244 | view_child_destroy(child); | ||
245 | } | ||
246 | |||
247 | static void view_child_handle_view_unmap(struct wl_listener *listener, | ||
248 | void *data) { | ||
249 | struct sway_view_child *child = | ||
250 | wl_container_of(listener, child, view_unmap); | ||
251 | view_child_destroy(child); | ||
252 | } | ||
253 | |||
254 | static void view_init_subsurfaces(struct sway_view *view, | ||
255 | struct wlr_surface *surface) { | ||
256 | struct wlr_subsurface *subsurface; | ||
257 | wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { | ||
258 | view_subsurface_create(view, subsurface); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void view_child_init(struct sway_view_child *child, | ||
263 | const struct sway_view_child_impl *impl, struct sway_view *view, | ||
264 | struct wlr_surface *surface) { | ||
265 | child->impl = impl; | ||
266 | child->view = view; | ||
267 | child->surface = surface; | ||
268 | |||
269 | wl_signal_add(&surface->events.commit, &child->surface_commit); | ||
270 | child->surface_commit.notify = view_child_handle_surface_commit; | ||
271 | wl_signal_add(&surface->events.new_subsurface, | ||
272 | &child->surface_new_subsurface); | ||
273 | child->surface_new_subsurface.notify = | ||
274 | view_child_handle_surface_new_subsurface; | ||
275 | wl_signal_add(&surface->events.destroy, &child->surface_destroy); | ||
276 | child->surface_destroy.notify = view_child_handle_surface_destroy; | ||
277 | wl_signal_add(&view->events.unmap, &child->view_unmap); | ||
278 | child->view_unmap.notify = view_child_handle_view_unmap; | ||
279 | |||
280 | view_init_subsurfaces(child->view, surface); | ||
281 | |||
282 | // TODO: only damage the whole child | ||
283 | view_damage_whole(child->view); | ||
284 | } | ||
285 | |||
286 | void view_child_destroy(struct sway_view_child *child) { | ||
287 | // TODO: only damage the whole child | ||
288 | view_damage_whole(child->view); | ||
289 | |||
290 | wl_list_remove(&child->surface_commit.link); | ||
291 | wl_list_remove(&child->surface_destroy.link); | ||
292 | wl_list_remove(&child->view_unmap.link); | ||
293 | |||
294 | if (child->impl && child->impl->destroy) { | ||
295 | child->impl->destroy(child); | ||
296 | } else { | ||
297 | free(child); | ||
298 | } | ||
299 | } | ||