diff options
Diffstat (limited to 'sway/desktop/xdg_shell.c')
-rw-r--r-- | sway/desktop/xdg_shell.c | 113 |
1 files changed, 60 insertions, 53 deletions
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 | ||
22 | static const struct sway_view_child_impl popup_impl; | 22 | static struct sway_xdg_popup *popup_create( |
23 | 23 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view, | |
24 | static 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, | 26 | static 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 | ||
35 | static void popup_destroy(struct sway_view_child *child) { | 33 | static 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 | ||
47 | static const struct sway_view_child_impl popup_impl = { | ||
48 | .get_view_coords = popup_get_view_coords, | ||
49 | .destroy = popup_destroy, | ||
50 | }; | ||
51 | |||
52 | static struct sway_xdg_popup *popup_create( | ||
53 | struct wlr_xdg_popup *wlr_popup, struct sway_view *view); | ||
54 | |||
55 | static void popup_unconstrain(struct sway_xdg_popup *popup) { | 43 | static 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 | ||
86 | static void popup_handle_new_popup(struct wl_listener *listener, void *data) { | 74 | static 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 | |||
93 | static 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 | |||
98 | static 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 | ||
344 | static void handle_set_title(struct wl_listener *listener, void *data) { | 340 | static 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 | ||
366 | static void handle_request_maximize(struct wl_listener *listener, void *data) { | 371 | static 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 | } |