diff options
Diffstat (limited to 'sway/desktop/xwayland.c')
-rw-r--r-- | sway/desktop/xwayland.c | 136 |
1 files changed, 66 insertions, 70 deletions
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 17f827d9..bfef68cf 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -14,6 +14,33 @@ | |||
14 | #include "sway/input/input-manager.h" | 14 | #include "sway/input/input-manager.h" |
15 | #include "log.h" | 15 | #include "log.h" |
16 | 16 | ||
17 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { | ||
18 | struct sway_xwayland_unmanaged *sway_surface = | ||
19 | wl_container_of(listener, sway_surface, destroy); | ||
20 | wl_list_remove(&sway_surface->destroy.link); | ||
21 | wl_list_remove(&sway_surface->link); | ||
22 | free(sway_surface); | ||
23 | } | ||
24 | |||
25 | static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { | ||
26 | struct sway_xwayland_unmanaged *sway_surface = | ||
27 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | ||
28 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | sway_surface->wlr_xwayland_surface = xsurface; | ||
33 | |||
34 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); | ||
35 | sway_surface->destroy.notify = unmanaged_handle_destroy; | ||
36 | |||
37 | wl_list_insert(&root_container.sway_root->xwayland_unmanaged, | ||
38 | &sway_surface->link); | ||
39 | |||
40 | // TODO: damage tracking | ||
41 | } | ||
42 | |||
43 | |||
17 | static bool assert_xwayland(struct sway_view *view) { | 44 | static bool assert_xwayland(struct sway_view *view) { |
18 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, | 45 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, |
19 | "Expected xwayland view!"); | 46 | "Expected xwayland view!"); |
@@ -33,22 +60,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
33 | } | 60 | } |
34 | } | 61 | } |
35 | 62 | ||
36 | static void set_size(struct sway_view *view, int width, int height) { | 63 | static void configure(struct sway_view *view, double ox, double oy, int width, |
64 | int height) { | ||
37 | if (!assert_xwayland(view)) { | 65 | if (!assert_xwayland(view)) { |
38 | return; | 66 | return; |
39 | } | 67 | } |
40 | view->sway_xwayland_surface->pending_width = width; | ||
41 | view->sway_xwayland_surface->pending_height = height; | ||
42 | |||
43 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 68 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
44 | wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y, | ||
45 | width, height); | ||
46 | } | ||
47 | 69 | ||
48 | static void set_position(struct sway_view *view, double ox, double oy) { | ||
49 | if (!assert_xwayland(view)) { | ||
50 | return; | ||
51 | } | ||
52 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 70 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
53 | if (!sway_assert(output, "view must be within tree to set position")) { | 71 | if (!sway_assert(output, "view must be within tree to set position")) { |
54 | return; | 72 | return; |
@@ -64,13 +82,12 @@ static void set_position(struct sway_view *view, double ox, double oy) { | |||
64 | return; | 82 | return; |
65 | } | 83 | } |
66 | 84 | ||
67 | view->swayc->x = ox; | 85 | view_update_position(view, ox, oy); |
68 | view->swayc->y = oy; | ||
69 | 86 | ||
70 | wlr_xwayland_surface_configure(view->wlr_xwayland_surface, | 87 | view->sway_xwayland_surface->pending_width = width; |
71 | ox + loutput->x, oy + loutput->y, | 88 | view->sway_xwayland_surface->pending_height = height; |
72 | view->wlr_xwayland_surface->width, | 89 | wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, |
73 | view->wlr_xwayland_surface->height); | 90 | width, height); |
74 | } | 91 | } |
75 | 92 | ||
76 | static void set_activated(struct sway_view *view, bool activated) { | 93 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -81,77 +98,58 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
81 | wlr_xwayland_surface_activate(surface, activated); | 98 | wlr_xwayland_surface_activate(surface, activated); |
82 | } | 99 | } |
83 | 100 | ||
84 | static void close_view(struct sway_view *view) { | 101 | static void _close(struct sway_view *view) { |
85 | if (!assert_xwayland(view)) { | 102 | if (!assert_xwayland(view)) { |
86 | return; | 103 | return; |
87 | } | 104 | } |
88 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); | 105 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); |
89 | } | 106 | } |
90 | 107 | ||
108 | static const struct sway_view_impl view_impl = { | ||
109 | .get_prop = get_prop, | ||
110 | .configure = configure, | ||
111 | .set_activated = set_activated, | ||
112 | .close = _close, | ||
113 | }; | ||
114 | |||
91 | static void handle_commit(struct wl_listener *listener, void *data) { | 115 | static void handle_commit(struct wl_listener *listener, void *data) { |
92 | struct sway_xwayland_surface *sway_surface = | 116 | struct sway_xwayland_surface *sway_surface = |
93 | wl_container_of(listener, sway_surface, commit); | 117 | wl_container_of(listener, sway_surface, commit); |
94 | struct sway_view *view = sway_surface->view; | 118 | struct sway_view *view = sway_surface->view; |
95 | // NOTE: We intentionally discard the view's desired width here | 119 | // NOTE: We intentionally discard the view's desired width here |
96 | // TODO: Let floating views do whatever | 120 | // TODO: Let floating views do whatever |
97 | view->width = sway_surface->pending_width; | 121 | view_update_size(view, sway_surface->pending_width, |
98 | view->height = sway_surface->pending_height; | 122 | sway_surface->pending_height); |
99 | view_damage_from(view); | 123 | view_damage_from(view); |
100 | } | 124 | } |
101 | 125 | ||
102 | static void handle_destroy(struct wl_listener *listener, void *data) { | 126 | static void handle_destroy(struct wl_listener *listener, void *data) { |
103 | struct sway_xwayland_surface *sway_surface = | 127 | struct sway_xwayland_surface *sway_surface = |
104 | wl_container_of(listener, sway_surface, destroy); | 128 | wl_container_of(listener, sway_surface, destroy); |
105 | |||
106 | wl_list_remove(&sway_surface->commit.link); | 129 | wl_list_remove(&sway_surface->commit.link); |
107 | wl_list_remove(&sway_surface->destroy.link); | 130 | wl_list_remove(&sway_surface->destroy.link); |
108 | wl_list_remove(&sway_surface->request_configure.link); | 131 | wl_list_remove(&sway_surface->request_configure.link); |
109 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 132 | wl_list_remove(&sway_surface->map.link); |
110 | container_view_destroy(sway_surface->view->swayc); | 133 | wl_list_remove(&sway_surface->unmap.link); |
111 | sway_surface->view->swayc = NULL; | 134 | view_destroy(sway_surface->view); |
112 | sway_surface->view->surface = NULL; | 135 | free(sway_surface); |
113 | } | 136 | } |
114 | 137 | ||
115 | static void handle_unmap(struct wl_listener *listener, void *data) { | 138 | static void handle_unmap(struct wl_listener *listener, void *data) { |
116 | struct sway_xwayland_surface *sway_surface = | 139 | struct sway_xwayland_surface *sway_surface = |
117 | wl_container_of(listener, sway_surface, unmap); | 140 | wl_container_of(listener, sway_surface, unmap); |
118 | view_damage_whole(sway_surface->view); | 141 | view_unmap(sway_surface->view); |
119 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
120 | wl_list_init(&sway_surface->view->unmanaged_view_link); | ||
121 | container_view_destroy(sway_surface->view->swayc); | ||
122 | sway_surface->view->swayc = NULL; | ||
123 | sway_surface->view->surface = NULL; | ||
124 | } | 142 | } |
125 | 143 | ||
126 | static void handle_map(struct wl_listener *listener, void *data) { | 144 | static void handle_map(struct wl_listener *listener, void *data) { |
127 | struct sway_xwayland_surface *sway_surface = | 145 | struct sway_xwayland_surface *sway_surface = |
128 | wl_container_of(listener, sway_surface, map); | 146 | wl_container_of(listener, sway_surface, map); |
129 | struct wlr_xwayland_surface *xsurface = data; | 147 | struct wlr_xwayland_surface *xsurface = data; |
130 | 148 | struct sway_view *view = sway_surface->view; | |
131 | sway_surface->view->surface = xsurface->surface; | ||
132 | 149 | ||
133 | // put it back into the tree | 150 | // put it back into the tree |
134 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | 151 | wlr_xwayland_surface_set_maximized(xsurface, true); |
135 | xsurface->override_redirect) { | 152 | view_map(view, xsurface->surface); |
136 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
137 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
138 | &sway_surface->view->unmanaged_view_link); | ||
139 | } else { | ||
140 | struct sway_view *view = sway_surface->view; | ||
141 | container_view_destroy(view->swayc); | ||
142 | |||
143 | wlr_xwayland_surface_set_maximized(xsurface, true); | ||
144 | |||
145 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
146 | struct sway_container *focus = seat_get_focus_inactive(seat, | ||
147 | &root_container); | ||
148 | struct sway_container *cont = container_view_create(focus, view); | ||
149 | view->swayc = cont; | ||
150 | arrange_windows(cont->parent, -1, -1); | ||
151 | input_manager_set_focus(input_manager, cont); | ||
152 | } | ||
153 | |||
154 | view_damage_whole(sway_surface->view); | ||
155 | } | 153 | } |
156 | 154 | ||
157 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 155 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
@@ -171,34 +169,32 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
171 | listener, server, xwayland_surface); | 169 | listener, server, xwayland_surface); |
172 | struct wlr_xwayland_surface *xsurface = data; | 170 | struct wlr_xwayland_surface *xsurface = data; |
173 | 171 | ||
172 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | ||
173 | xsurface->override_redirect) { | ||
174 | wlr_log(L_DEBUG, "New xwayland unmanaged surface"); | ||
175 | create_unmanaged(xsurface); | ||
176 | return; | ||
177 | } | ||
178 | |||
174 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", | 179 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", |
175 | xsurface->title, xsurface->class); | 180 | xsurface->title, xsurface->class); |
176 | 181 | ||
177 | struct sway_xwayland_surface *sway_surface = | 182 | struct sway_xwayland_surface *sway_surface = |
178 | calloc(1, sizeof(struct sway_xwayland_surface)); | 183 | calloc(1, sizeof(struct sway_xwayland_surface)); |
179 | if (!sway_assert(sway_surface, "Failed to allocate surface!")) { | 184 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { |
180 | return; | 185 | return; |
181 | } | 186 | } |
182 | 187 | ||
183 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 188 | struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); |
184 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 189 | if (!sway_assert(view, "Failed to allocate view")) { |
185 | return; | 190 | return; |
186 | } | 191 | } |
187 | sway_view->type = SWAY_XWAYLAND_VIEW; | 192 | view->wlr_xwayland_surface = xsurface; |
188 | sway_view->iface.get_prop = get_prop; | 193 | view->sway_xwayland_surface = sway_surface; |
189 | sway_view->iface.set_size = set_size; | 194 | sway_surface->view = view; |
190 | sway_view->iface.set_position = set_position; | ||
191 | sway_view->iface.set_activated = set_activated; | ||
192 | sway_view->iface.close = close_view; | ||
193 | sway_view->wlr_xwayland_surface = xsurface; | ||
194 | sway_view->sway_xwayland_surface = sway_surface; | ||
195 | sway_surface->view = sway_view; | ||
196 | |||
197 | wl_list_init(&sway_view->unmanaged_view_link); | ||
198 | 195 | ||
199 | // TODO: | 196 | // TODO: |
200 | // - Look up pid and open on appropriate workspace | 197 | // - Look up pid and open on appropriate workspace |
201 | // - Set new view to maximized so it behaves nicely | ||
202 | // - Criteria | 198 | // - Criteria |
203 | 199 | ||
204 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); | 200 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); |