diff options
Diffstat (limited to 'sway/desktop/xdg_shell.c')
-rw-r--r-- | sway/desktop/xdg_shell.c | 252 |
1 files changed, 149 insertions, 103 deletions
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 8da922d5..7c417891 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #define _POSIX_C_SOURCE 199309L | ||
2 | #include <float.h> | 1 | #include <float.h> |
3 | #include <stdbool.h> | 2 | #include <stdbool.h> |
4 | #include <stdlib.h> | 3 | #include <stdlib.h> |
@@ -7,7 +6,7 @@ | |||
7 | #include <wlr/util/edges.h> | 6 | #include <wlr/util/edges.h> |
8 | #include "log.h" | 7 | #include "log.h" |
9 | #include "sway/decoration.h" | 8 | #include "sway/decoration.h" |
10 | #include "sway/desktop.h" | 9 | #include "sway/scene_descriptor.h" |
11 | #include "sway/desktop/transaction.h" | 10 | #include "sway/desktop/transaction.h" |
12 | #include "sway/input/cursor.h" | 11 | #include "sway/input/cursor.h" |
13 | #include "sway/input/input-manager.h" | 12 | #include "sway/input/input-manager.h" |
@@ -19,55 +18,39 @@ | |||
19 | #include "sway/tree/workspace.h" | 18 | #include "sway/tree/workspace.h" |
20 | #include "sway/xdg_decoration.h" | 19 | #include "sway/xdg_decoration.h" |
21 | 20 | ||
22 | static const struct sway_view_child_impl popup_impl; | ||
23 | |||
24 | static void popup_get_view_coords(struct sway_view_child *child, | ||
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 | |||
29 | wlr_xdg_popup_get_toplevel_coords(wlr_popup, | ||
30 | wlr_popup->current.geometry.x - wlr_popup->base->current.geometry.x, | ||
31 | wlr_popup->current.geometry.y - wlr_popup->base->current.geometry.y, | ||
32 | sx, sy); | ||
33 | } | ||
34 | |||
35 | static void popup_destroy(struct sway_view_child *child) { | ||
36 | if (!sway_assert(child->impl == &popup_impl, | ||
37 | "Expected an xdg_shell popup")) { | ||
38 | return; | ||
39 | } | ||
40 | struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; | ||
41 | wl_list_remove(&popup->new_popup.link); | ||
42 | wl_list_remove(&popup->destroy.link); | ||
43 | free(popup); | ||
44 | } | ||
45 | |||
46 | static const struct sway_view_child_impl popup_impl = { | ||
47 | .get_view_coords = popup_get_view_coords, | ||
48 | .destroy = popup_destroy, | ||
49 | }; | ||
50 | |||
51 | static struct sway_xdg_popup *popup_create( | 21 | static struct sway_xdg_popup *popup_create( |
52 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view); | 22 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view, |
23 | struct wlr_scene_tree *parent); | ||
53 | 24 | ||
54 | static void popup_handle_new_popup(struct wl_listener *listener, void *data) { | 25 | static void popup_handle_new_popup(struct wl_listener *listener, void *data) { |
55 | struct sway_xdg_popup *popup = | 26 | struct sway_xdg_popup *popup = |
56 | wl_container_of(listener, popup, new_popup); | 27 | wl_container_of(listener, popup, new_popup); |
57 | struct wlr_xdg_popup *wlr_popup = data; | 28 | struct wlr_xdg_popup *wlr_popup = data; |
58 | popup_create(wlr_popup, popup->child.view); | 29 | popup_create(wlr_popup, popup->view, popup->xdg_surface_tree); |
59 | } | 30 | } |
60 | 31 | ||
61 | static void popup_handle_destroy(struct wl_listener *listener, void *data) { | 32 | static void popup_handle_destroy(struct wl_listener *listener, void *data) { |
62 | struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); | 33 | struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); |
63 | view_child_destroy(&popup->child); | 34 | |
35 | wl_list_remove(&popup->new_popup.link); | ||
36 | wl_list_remove(&popup->destroy.link); | ||
37 | wl_list_remove(&popup->surface_commit.link); | ||
38 | wl_list_remove(&popup->reposition.link); | ||
39 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
40 | free(popup); | ||
64 | } | 41 | } |
65 | 42 | ||
66 | static void popup_unconstrain(struct sway_xdg_popup *popup) { | 43 | static void popup_unconstrain(struct sway_xdg_popup *popup) { |
67 | struct sway_view *view = popup->child.view; | 44 | struct sway_view *view = popup->view; |
68 | struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; | 45 | struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; |
69 | 46 | ||
70 | struct sway_output *output = view->container->pending.workspace->output; | 47 | struct sway_workspace *workspace = view->container->pending.workspace; |
48 | if (!workspace) { | ||
49 | // is null if in the scratchpad | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | struct sway_output *output = workspace->output; | ||
71 | 54 | ||
72 | // the output box expressed in the coordinate system of the toplevel parent | 55 | // the output box expressed in the coordinate system of the toplevel parent |
73 | // of the popup | 56 | // of the popup |
@@ -81,32 +64,72 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) { | |||
81 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); | 64 | wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); |
82 | } | 65 | } |
83 | 66 | ||
84 | static struct sway_xdg_popup *popup_create( | 67 | static void popup_handle_surface_commit(struct wl_listener *listener, void *data) { |
85 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { | 68 | struct sway_xdg_popup *popup = wl_container_of(listener, popup, surface_commit); |
69 | if (popup->wlr_xdg_popup->base->initial_commit) { | ||
70 | popup_unconstrain(popup); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static void popup_handle_reposition(struct wl_listener *listener, void *data) { | ||
75 | struct sway_xdg_popup *popup = wl_container_of(listener, popup, reposition); | ||
76 | popup_unconstrain(popup); | ||
77 | } | ||
78 | |||
79 | static struct sway_xdg_popup *popup_create(struct wlr_xdg_popup *wlr_popup, | ||
80 | struct sway_view *view, struct wlr_scene_tree *parent) { | ||
86 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; | 81 | struct wlr_xdg_surface *xdg_surface = wlr_popup->base; |
87 | 82 | ||
88 | struct sway_xdg_popup *popup = | 83 | struct sway_xdg_popup *popup = calloc(1, sizeof(struct sway_xdg_popup)); |
89 | calloc(1, sizeof(struct sway_xdg_popup)); | 84 | if (!popup) { |
90 | if (popup == NULL) { | 85 | return NULL; |
86 | } | ||
87 | |||
88 | popup->wlr_xdg_popup = wlr_popup; | ||
89 | popup->view = view; | ||
90 | |||
91 | popup->scene_tree = wlr_scene_tree_create(parent); | ||
92 | if (!popup->scene_tree) { | ||
93 | free(popup); | ||
91 | return NULL; | 94 | return NULL; |
92 | } | 95 | } |
93 | view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); | 96 | |
97 | popup->xdg_surface_tree = wlr_scene_xdg_surface_create( | ||
98 | popup->scene_tree, xdg_surface); | ||
99 | if (!popup->xdg_surface_tree) { | ||
100 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
101 | free(popup); | ||
102 | return NULL; | ||
103 | } | ||
104 | |||
105 | popup->desc.relative = &view->content_tree->node; | ||
106 | popup->desc.view = view; | ||
107 | |||
108 | if (!scene_descriptor_assign(&popup->scene_tree->node, | ||
109 | SWAY_SCENE_DESC_POPUP, &popup->desc)) { | ||
110 | sway_log(SWAY_ERROR, "Failed to allocate a popup scene descriptor"); | ||
111 | wlr_scene_node_destroy(&popup->scene_tree->node); | ||
112 | free(popup); | ||
113 | return NULL; | ||
114 | } | ||
115 | |||
94 | popup->wlr_xdg_popup = xdg_surface->popup; | 116 | popup->wlr_xdg_popup = xdg_surface->popup; |
117 | struct sway_xdg_shell_view *shell_view = | ||
118 | wl_container_of(view, shell_view, view); | ||
119 | xdg_surface->data = shell_view; | ||
95 | 120 | ||
121 | wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit); | ||
122 | popup->surface_commit.notify = popup_handle_surface_commit; | ||
96 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); | 123 | wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); |
97 | popup->new_popup.notify = popup_handle_new_popup; | 124 | popup->new_popup.notify = popup_handle_new_popup; |
98 | wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); | 125 | wl_signal_add(&wlr_popup->events.reposition, &popup->reposition); |
126 | popup->reposition.notify = popup_handle_reposition; | ||
127 | wl_signal_add(&wlr_popup->events.destroy, &popup->destroy); | ||
99 | popup->destroy.notify = popup_handle_destroy; | 128 | popup->destroy.notify = popup_handle_destroy; |
100 | 129 | ||
101 | wl_signal_add(&xdg_surface->events.map, &popup->child.surface_map); | ||
102 | wl_signal_add(&xdg_surface->events.unmap, &popup->child.surface_unmap); | ||
103 | |||
104 | popup_unconstrain(popup); | ||
105 | |||
106 | return popup; | 130 | return popup; |
107 | } | 131 | } |
108 | 132 | ||
109 | |||
110 | static struct sway_xdg_shell_view *xdg_shell_view_from_view( | 133 | static struct sway_xdg_shell_view *xdg_shell_view_from_view( |
111 | struct sway_view *view) { | 134 | struct sway_view *view) { |
112 | if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL, | 135 | if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL, |
@@ -163,12 +186,19 @@ static void set_tiled(struct sway_view *view, bool tiled) { | |||
163 | if (xdg_shell_view_from_view(view) == NULL) { | 186 | if (xdg_shell_view_from_view(view) == NULL) { |
164 | return; | 187 | return; |
165 | } | 188 | } |
166 | enum wlr_edges edges = WLR_EDGE_NONE; | 189 | if (wl_resource_get_version(view->wlr_xdg_toplevel->resource) >= |
167 | if (tiled) { | 190 | XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) { |
168 | edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | | 191 | enum wlr_edges edges = WLR_EDGE_NONE; |
169 | WLR_EDGE_BOTTOM; | 192 | if (tiled) { |
193 | edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | | ||
194 | WLR_EDGE_BOTTOM; | ||
195 | } | ||
196 | wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges); | ||
197 | } else { | ||
198 | // The version is too low for the tiled state; configure as maximized instead | ||
199 | // to stop the client from drawing decorations outside of the toplevel geometry. | ||
200 | wlr_xdg_toplevel_set_maximized(view->wlr_xdg_toplevel, tiled); | ||
170 | } | 201 | } |
171 | wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges); | ||
172 | } | 202 | } |
173 | 203 | ||
174 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { | 204 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { |
@@ -194,24 +224,6 @@ static bool wants_floating(struct sway_view *view) { | |||
194 | || toplevel->parent; | 224 | || toplevel->parent; |
195 | } | 225 | } |
196 | 226 | ||
197 | static void for_each_surface(struct sway_view *view, | ||
198 | wlr_surface_iterator_func_t iterator, void *user_data) { | ||
199 | if (xdg_shell_view_from_view(view) == NULL) { | ||
200 | return; | ||
201 | } | ||
202 | wlr_xdg_surface_for_each_surface(view->wlr_xdg_toplevel->base, iterator, | ||
203 | user_data); | ||
204 | } | ||
205 | |||
206 | static void for_each_popup_surface(struct sway_view *view, | ||
207 | wlr_surface_iterator_func_t iterator, void *user_data) { | ||
208 | if (xdg_shell_view_from_view(view) == NULL) { | ||
209 | return; | ||
210 | } | ||
211 | wlr_xdg_surface_for_each_popup_surface(view->wlr_xdg_toplevel->base, | ||
212 | iterator, user_data); | ||
213 | } | ||
214 | |||
215 | static bool is_transient_for(struct sway_view *child, | 227 | static bool is_transient_for(struct sway_view *child, |
216 | struct sway_view *ancestor) { | 228 | struct sway_view *ancestor) { |
217 | if (xdg_shell_view_from_view(child) == NULL) { | 229 | if (xdg_shell_view_from_view(child) == NULL) { |
@@ -259,8 +271,6 @@ static const struct sway_view_impl view_impl = { | |||
259 | .set_fullscreen = set_fullscreen, | 271 | .set_fullscreen = set_fullscreen, |
260 | .set_resizing = set_resizing, | 272 | .set_resizing = set_resizing, |
261 | .wants_floating = wants_floating, | 273 | .wants_floating = wants_floating, |
262 | .for_each_surface = for_each_surface, | ||
263 | .for_each_popup_surface = for_each_popup_surface, | ||
264 | .is_transient_for = is_transient_for, | 274 | .is_transient_for = is_transient_for, |
265 | .close = _close, | 275 | .close = _close, |
266 | .close_popups = close_popups, | 276 | .close_popups = close_popups, |
@@ -273,6 +283,20 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
273 | struct sway_view *view = &xdg_shell_view->view; | 283 | struct sway_view *view = &xdg_shell_view->view; |
274 | struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base; | 284 | struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base; |
275 | 285 | ||
286 | if (xdg_surface->initial_commit) { | ||
287 | if (view->xdg_decoration != NULL) { | ||
288 | set_xdg_decoration_mode(view->xdg_decoration); | ||
289 | } | ||
290 | // XXX: https://github.com/swaywm/sway/issues/2176 | ||
291 | wlr_xdg_surface_schedule_configure(xdg_surface); | ||
292 | // TODO: wlr_xdg_toplevel_set_bounds() | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | if (!xdg_surface->surface->mapped) { | ||
297 | return; | ||
298 | } | ||
299 | |||
276 | struct wlr_box new_geo; | 300 | struct wlr_box new_geo; |
277 | wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); | 301 | wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); |
278 | bool new_size = new_geo.width != view->geometry.width || | 302 | bool new_size = new_geo.width != view->geometry.width || |
@@ -284,23 +308,32 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
284 | // The client changed its surface size in this commit. For floating | 308 | // The client changed its surface size in this commit. For floating |
285 | // containers, we resize the container to match. For tiling containers, | 309 | // containers, we resize the container to match. For tiling containers, |
286 | // we only recenter the surface. | 310 | // we only recenter the surface. |
287 | desktop_damage_view(view); | ||
288 | memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); | 311 | memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box)); |
289 | if (container_is_floating(view->container)) { | 312 | if (container_is_floating(view->container)) { |
290 | view_update_size(view); | 313 | view_update_size(view); |
314 | // Only set the toplevel size the current container actually has a size. | ||
315 | if (view->container->current.width) { | ||
316 | wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel, view->geometry.width, | ||
317 | view->geometry.height); | ||
318 | } | ||
291 | transaction_commit_dirty_client(); | 319 | transaction_commit_dirty_client(); |
292 | } else { | ||
293 | view_center_surface(view); | ||
294 | } | 320 | } |
295 | desktop_damage_view(view); | 321 | |
322 | view_center_and_clip_surface(view); | ||
296 | } | 323 | } |
297 | 324 | ||
298 | if (view->container->node.instruction) { | 325 | if (view->container->node.instruction) { |
299 | transaction_notify_view_ready_by_serial(view, | 326 | bool successful = transaction_notify_view_ready_by_serial(view, |
300 | xdg_surface->current.configure_serial); | 327 | xdg_surface->current.configure_serial); |
301 | } | ||
302 | 328 | ||
303 | view_damage_from(view); | 329 | // If we saved the view and this commit isn't what we're looking for |
330 | // that means the user will never actually see the buffers submitted to | ||
331 | // us here. Just send frame done events to these surfaces so they can | ||
332 | // commit another time for us. | ||
333 | if (view->saved_surface_tree && !successful) { | ||
334 | view_send_frame_done(view); | ||
335 | } | ||
336 | } | ||
304 | } | 337 | } |
305 | 338 | ||
306 | static void handle_set_title(struct wl_listener *listener, void *data) { | 339 | static void handle_set_title(struct wl_listener *listener, void *data) { |
@@ -315,6 +348,7 @@ static void handle_set_app_id(struct wl_listener *listener, void *data) { | |||
315 | struct sway_xdg_shell_view *xdg_shell_view = | 348 | struct sway_xdg_shell_view *xdg_shell_view = |
316 | wl_container_of(listener, xdg_shell_view, set_app_id); | 349 | wl_container_of(listener, xdg_shell_view, set_app_id); |
317 | struct sway_view *view = &xdg_shell_view->view; | 350 | struct sway_view *view = &xdg_shell_view->view; |
351 | view_update_app_id(view); | ||
318 | view_execute_criteria(view); | 352 | view_execute_criteria(view); |
319 | } | 353 | } |
320 | 354 | ||
@@ -322,7 +356,16 @@ static void handle_new_popup(struct wl_listener *listener, void *data) { | |||
322 | struct sway_xdg_shell_view *xdg_shell_view = | 356 | struct sway_xdg_shell_view *xdg_shell_view = |
323 | wl_container_of(listener, xdg_shell_view, new_popup); | 357 | wl_container_of(listener, xdg_shell_view, new_popup); |
324 | struct wlr_xdg_popup *wlr_popup = data; | 358 | struct wlr_xdg_popup *wlr_popup = data; |
325 | 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); | ||
326 | } | 369 | } |
327 | 370 | ||
328 | static void handle_request_maximize(struct wl_listener *listener, void *data) { | 371 | static void handle_request_maximize(struct wl_listener *listener, void *data) { |
@@ -338,7 +381,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data) | |||
338 | struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel; | 381 | struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel; |
339 | struct sway_view *view = &xdg_shell_view->view; | 382 | struct sway_view *view = &xdg_shell_view->view; |
340 | 383 | ||
341 | if (!toplevel->base->mapped) { | 384 | if (!toplevel->base->surface->mapped) { |
342 | return; | 385 | return; |
343 | } | 386 | } |
344 | 387 | ||
@@ -403,7 +446,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) { | |||
403 | 446 | ||
404 | view_unmap(view); | 447 | view_unmap(view); |
405 | 448 | ||
406 | wl_list_remove(&xdg_shell_view->commit.link); | ||
407 | wl_list_remove(&xdg_shell_view->new_popup.link); | 449 | wl_list_remove(&xdg_shell_view->new_popup.link); |
408 | wl_list_remove(&xdg_shell_view->request_maximize.link); | 450 | wl_list_remove(&xdg_shell_view->request_maximize.link); |
409 | wl_list_remove(&xdg_shell_view->request_fullscreen.link); | 451 | wl_list_remove(&xdg_shell_view->request_fullscreen.link); |
@@ -446,10 +488,6 @@ static void handle_map(struct wl_listener *listener, void *data) { | |||
446 | 488 | ||
447 | transaction_commit_dirty(); | 489 | transaction_commit_dirty(); |
448 | 490 | ||
449 | xdg_shell_view->commit.notify = handle_commit; | ||
450 | wl_signal_add(&toplevel->base->surface->events.commit, | ||
451 | &xdg_shell_view->commit); | ||
452 | |||
453 | xdg_shell_view->new_popup.notify = handle_new_popup; | 491 | xdg_shell_view->new_popup.notify = handle_new_popup; |
454 | wl_signal_add(&toplevel->base->events.new_popup, | 492 | wl_signal_add(&toplevel->base->events.new_popup, |
455 | &xdg_shell_view->new_popup); | 493 | &xdg_shell_view->new_popup); |
@@ -489,6 +527,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
489 | wl_list_remove(&xdg_shell_view->destroy.link); | 527 | wl_list_remove(&xdg_shell_view->destroy.link); |
490 | wl_list_remove(&xdg_shell_view->map.link); | 528 | wl_list_remove(&xdg_shell_view->map.link); |
491 | wl_list_remove(&xdg_shell_view->unmap.link); | 529 | wl_list_remove(&xdg_shell_view->unmap.link); |
530 | wl_list_remove(&xdg_shell_view->commit.link); | ||
492 | view->wlr_xdg_toplevel = NULL; | 531 | view->wlr_xdg_toplevel = NULL; |
493 | if (view->xdg_decoration) { | 532 | if (view->xdg_decoration) { |
494 | view->xdg_decoration->view = NULL; | 533 | view->xdg_decoration->view = NULL; |
@@ -501,17 +540,12 @@ struct sway_view *view_from_wlr_xdg_surface( | |||
501 | return xdg_surface->data; | 540 | return xdg_surface->data; |
502 | } | 541 | } |
503 | 542 | ||
504 | void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { | 543 | void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) { |
505 | struct wlr_xdg_surface *xdg_surface = data; | 544 | struct wlr_xdg_toplevel *xdg_toplevel = data; |
506 | |||
507 | if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { | ||
508 | sway_log(SWAY_DEBUG, "New xdg_shell popup"); | ||
509 | return; | ||
510 | } | ||
511 | 545 | ||
512 | sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", | 546 | sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", |
513 | xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); | 547 | xdg_toplevel->title, xdg_toplevel->app_id); |
514 | wlr_xdg_surface_ping(xdg_surface); | 548 | wlr_xdg_surface_ping(xdg_toplevel->base); |
515 | 549 | ||
516 | struct sway_xdg_shell_view *xdg_shell_view = | 550 | struct sway_xdg_shell_view *xdg_shell_view = |
517 | calloc(1, sizeof(struct sway_xdg_shell_view)); | 551 | calloc(1, sizeof(struct sway_xdg_shell_view)); |
@@ -519,17 +553,29 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { | |||
519 | return; | 553 | return; |
520 | } | 554 | } |
521 | 555 | ||
522 | view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); | 556 | if (!view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl)) { |
523 | xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; | 557 | free(xdg_shell_view); |
558 | return; | ||
559 | } | ||
560 | xdg_shell_view->view.wlr_xdg_toplevel = xdg_toplevel; | ||
524 | 561 | ||
525 | xdg_shell_view->map.notify = handle_map; | 562 | xdg_shell_view->map.notify = handle_map; |
526 | wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); | 563 | wl_signal_add(&xdg_toplevel->base->surface->events.map, &xdg_shell_view->map); |
527 | 564 | ||
528 | xdg_shell_view->unmap.notify = handle_unmap; | 565 | xdg_shell_view->unmap.notify = handle_unmap; |
529 | wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); | 566 | wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &xdg_shell_view->unmap); |
567 | |||
568 | xdg_shell_view->commit.notify = handle_commit; | ||
569 | wl_signal_add(&xdg_toplevel->base->surface->events.commit, | ||
570 | &xdg_shell_view->commit); | ||
530 | 571 | ||
531 | xdg_shell_view->destroy.notify = handle_destroy; | 572 | xdg_shell_view->destroy.notify = handle_destroy; |
532 | wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); | 573 | wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy); |
574 | |||
575 | wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base); | ||
576 | |||
577 | xdg_toplevel->base->data = xdg_shell_view; | ||
533 | 578 | ||
534 | xdg_surface->data = xdg_shell_view; | 579 | wlr_xdg_toplevel_set_wm_capabilities(xdg_toplevel, |
580 | XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN); | ||
535 | } | 581 | } |