blob: baacf7b987c3f453096c2a6138574eac84fc7e59 [file] [log] [blame]
Quentin Glidic248dd102016-08-12 10:41:34 +02001/*
2 * Copyright © 2010-2012 Intel Corporation
3 * Copyright © 2011-2012 Collabora, Ltd.
4 * Copyright © 2013 Raspberry Pi Foundation
5 * Copyright © 2016 Quentin "Sardem FF7" Glidic
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26
27#include "config.h"
28
29#include <assert.h>
30
31#include <wayland-server.h>
32
33#include "compositor.h"
34#include "zalloc.h"
35
36#include "libweston-desktop.h"
37#include "internal.h"
Quentin Glidic955cec02016-08-12 10:41:35 +020038#include "xwayland/xwayland-internal-interface.h"
Quentin Glidic248dd102016-08-12 10:41:34 +020039
40enum weston_desktop_xwayland_surface_state {
41 NONE,
42 TOPLEVEL,
43 MAXIMIZED,
44 FULLSCREEN,
45 TRANSIENT,
46 XWAYLAND,
47};
48
49struct weston_desktop_xwayland {
50 struct weston_desktop *desktop;
51 struct weston_desktop_client *client;
52 struct weston_layer layer;
53};
54
Quentin Glidic955cec02016-08-12 10:41:35 +020055struct weston_desktop_xwayland_surface {
Quentin Glidic248dd102016-08-12 10:41:34 +020056 struct weston_desktop_xwayland *xwayland;
57 struct weston_desktop *desktop;
58 struct weston_desktop_surface *surface;
59 struct wl_listener resource_destroy_listener;
60 struct weston_view *view;
Quentin Glidic955cec02016-08-12 10:41:35 +020061 const struct weston_xwayland_client_interface *client_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +020062 struct weston_geometry next_geometry;
63 bool has_next_geometry;
64 bool added;
65 enum weston_desktop_xwayland_surface_state state;
66};
67
68static void
Quentin Glidic955cec02016-08-12 10:41:35 +020069weston_desktop_xwayland_surface_change_state(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +020070 enum weston_desktop_xwayland_surface_state state,
71 struct weston_desktop_surface *parent,
72 int32_t x, int32_t y)
73{
Pekka Paalanene3a582f2016-11-15 14:24:21 +020074 struct weston_surface *wsurface;
Quentin Glidic248dd102016-08-12 10:41:34 +020075 bool to_add = (parent == NULL && state != XWAYLAND);
76
77 assert(state != NONE);
Pekka Paalanena838b782016-11-15 11:43:36 +020078 assert(!parent || state == TRANSIENT);
Quentin Glidic248dd102016-08-12 10:41:34 +020079
Quentin Glidic6384edf2016-08-16 11:42:47 +020080 if (to_add && surface->added) {
81 surface->state = state;
Quentin Glidic248dd102016-08-12 10:41:34 +020082 return;
Quentin Glidic6384edf2016-08-16 11:42:47 +020083 }
Quentin Glidic248dd102016-08-12 10:41:34 +020084
Pekka Paalanene3a582f2016-11-15 14:24:21 +020085 wsurface = weston_desktop_surface_get_surface(surface->surface);
86
Quentin Glidic248dd102016-08-12 10:41:34 +020087 if (surface->state != state) {
88 if (surface->state == XWAYLAND) {
Pekka Paalanenbbc749a2016-11-15 12:22:09 +020089 assert(!surface->added);
90
Quentin Glidicf01ecee2016-08-16 10:52:46 +020091 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidicf6636a82016-08-16 10:55:02 +020092 weston_view_destroy(surface->view);
Quentin Glidic248dd102016-08-12 10:41:34 +020093 surface->view = NULL;
Pekka Paalanene3a582f2016-11-15 14:24:21 +020094 weston_surface_unmap(wsurface);
Quentin Glidic248dd102016-08-12 10:41:34 +020095 }
96
97 if (to_add) {
98 weston_desktop_surface_unset_relative_to(surface->surface);
99 weston_desktop_api_surface_added(surface->desktop,
100 surface->surface);
Pekka Paalanen33268202016-11-15 11:48:42 +0200101 surface->added = true;
Quentin Glidic248dd102016-08-12 10:41:34 +0200102 } else if (surface->added) {
103 weston_desktop_api_surface_removed(surface->desktop,
104 surface->surface);
Pekka Paalanen33268202016-11-15 11:48:42 +0200105 surface->added = false;
Quentin Glidic248dd102016-08-12 10:41:34 +0200106 }
107
108 if (state == XWAYLAND) {
Pekka Paalanenbbc749a2016-11-15 12:22:09 +0200109 assert(!surface->added);
110
Quentin Glidic248dd102016-08-12 10:41:34 +0200111 surface->view =
112 weston_desktop_surface_create_view(surface->surface);
113 weston_layer_entry_insert(&surface->xwayland->layer.view_list,
114 &surface->view->layer_link);
115 weston_view_set_position(surface->view, x, y);
Pekka Paalanene3a582f2016-11-15 14:24:21 +0200116 surface->view->is_mapped = true;
117 wsurface->is_mapped = true;
Quentin Glidic248dd102016-08-12 10:41:34 +0200118 }
119
120 surface->state = state;
Quentin Glidic248dd102016-08-12 10:41:34 +0200121 }
122
123 if (parent != NULL)
124 weston_desktop_surface_set_relative_to(surface->surface, parent,
125 x, y, false);
126}
127
128static void
129weston_desktop_xwayland_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +0200130 void *user_data,
Quentin Glidic248dd102016-08-12 10:41:34 +0200131 int32_t sx, int32_t sy)
132{
Quentin Glidic955cec02016-08-12 10:41:35 +0200133 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200134
135 if (surface->has_next_geometry) {
136 surface->has_next_geometry = false;
137 weston_desktop_surface_set_geometry(surface->surface,
138 surface->next_geometry);
139 }
140
141 if (surface->added)
142 weston_desktop_api_committed(surface->desktop, surface->surface,
143 sx, sy);
144}
145
146static void
147weston_desktop_xwayland_surface_set_size(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200148 void *user_data,
149 int32_t width, int32_t height)
Quentin Glidic248dd102016-08-12 10:41:34 +0200150{
Quentin Glidic955cec02016-08-12 10:41:35 +0200151 struct weston_desktop_xwayland_surface *surface = user_data;
152 struct weston_surface *wsurface =
153 weston_desktop_surface_get_surface(surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200154
Quentin Glidic955cec02016-08-12 10:41:35 +0200155 surface->client_interface->send_configure(wsurface, width, height);
Quentin Glidic248dd102016-08-12 10:41:34 +0200156}
157
158static void
159weston_desktop_xwayland_surface_destroy(struct weston_desktop_surface *dsurface,
160 void *user_data)
161{
Quentin Glidic955cec02016-08-12 10:41:35 +0200162 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200163
164 wl_list_remove(&surface->resource_destroy_listener.link);
165
166 weston_desktop_surface_unset_relative_to(surface->surface);
Quentin Glidic1714f012016-08-18 16:45:30 +0200167 if (surface->added)
Quentin Glidic248dd102016-08-12 10:41:34 +0200168 weston_desktop_api_surface_removed(surface->desktop,
169 surface->surface);
Quentin Glidic1714f012016-08-18 16:45:30 +0200170 else if (surface->state == XWAYLAND)
Quentin Glidicf01ecee2016-08-16 10:52:46 +0200171 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidic248dd102016-08-12 10:41:34 +0200172
173 free(surface);
174}
175
176static bool
177weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200178 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200179{
Quentin Glidic955cec02016-08-12 10:41:35 +0200180 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200181
182 return surface->state == MAXIMIZED;
183}
184
185static bool
186weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200187 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200188{
Quentin Glidic955cec02016-08-12 10:41:35 +0200189 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200190
191 return surface->state == FULLSCREEN;
192}
193
194static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
195 .committed = weston_desktop_xwayland_surface_committed,
196 .set_size = weston_desktop_xwayland_surface_set_size,
197
198 .get_maximized = weston_desktop_xwayland_surface_get_maximized,
199 .get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
200
201 .destroy = weston_desktop_xwayland_surface_destroy,
202};
203
204static void
205weston_destop_xwayland_resource_destroyed(struct wl_listener *listener,
206 void *data)
207{
Quentin Glidic955cec02016-08-12 10:41:35 +0200208 struct weston_desktop_xwayland_surface *surface =
Quentin Glidic248dd102016-08-12 10:41:34 +0200209 wl_container_of(listener, surface, resource_destroy_listener);
210
211 weston_desktop_surface_destroy(surface->surface);
212}
213
Quentin Glidic955cec02016-08-12 10:41:35 +0200214static struct weston_desktop_xwayland_surface *
215create_surface(struct weston_desktop_xwayland *xwayland,
216 struct weston_surface *wsurface,
217 const struct weston_xwayland_client_interface *client_interface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200218{
Quentin Glidic955cec02016-08-12 10:41:35 +0200219 struct weston_desktop_xwayland_surface *surface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200220
Quentin Glidic955cec02016-08-12 10:41:35 +0200221 surface = zalloc(sizeof(struct weston_desktop_xwayland_surface));
Quentin Glidic248dd102016-08-12 10:41:34 +0200222 if (surface == NULL)
223 return NULL;
224
225 surface->xwayland = xwayland;
226 surface->desktop = xwayland->desktop;
Quentin Glidic955cec02016-08-12 10:41:35 +0200227 surface->client_interface = client_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200228
229 surface->surface =
230 weston_desktop_surface_create(surface->desktop,
231 xwayland->client, wsurface,
232 &weston_desktop_xwayland_surface_internal_implementation,
233 surface);
234 if (surface->surface == NULL) {
235 free(surface);
236 return NULL;
237 }
238
239 surface->resource_destroy_listener.notify =
240 weston_destop_xwayland_resource_destroyed;
241 wl_resource_add_destroy_listener(wsurface->resource,
242 &surface->resource_destroy_listener);
243
244 return surface;
245}
246
247static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200248set_toplevel(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200249{
250 weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
251 0, 0);
252}
253
254static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200255set_parent(struct weston_desktop_xwayland_surface *surface,
256 struct weston_surface *wparent)
Quentin Glidic248dd102016-08-12 10:41:34 +0200257{
258 struct weston_desktop_surface *parent;
259
260 if (!weston_surface_is_desktop_surface(wparent))
261 return;
262
263 parent = weston_surface_get_desktop_surface(wparent);
Quentin Glidic955cec02016-08-12 10:41:35 +0200264 weston_desktop_api_set_parent(surface->desktop, surface->surface, parent);
Quentin Glidic248dd102016-08-12 10:41:34 +0200265}
266
267static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200268set_transient(struct weston_desktop_xwayland_surface *surface,
269 struct weston_surface *wparent, int x, int y)
270{
271 struct weston_desktop_surface *parent;
272
273 if (!weston_surface_is_desktop_surface(wparent))
274 return;
275
276 parent = weston_surface_get_desktop_surface(wparent);
277 weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent,
278 x, y);
279}
280
281static void
282set_fullscreen(struct weston_desktop_xwayland_surface *surface,
283 struct weston_output *output)
Quentin Glidic248dd102016-08-12 10:41:34 +0200284{
285 weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
286 0, 0);
287 weston_desktop_api_fullscreen_requested(surface->desktop,
288 surface->surface, true, output);
289}
290
291static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200292set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y)
Quentin Glidic248dd102016-08-12 10:41:34 +0200293{
294 weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL,
295 x, y);
296}
297
298static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200299move(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200300 struct weston_pointer *pointer)
301{
302 if (surface->state == TOPLEVEL ||
303 surface->state == MAXIMIZED ||
304 surface->state == FULLSCREEN)
305 weston_desktop_api_move(surface->desktop, surface->surface,
306 pointer->seat, pointer->grab_serial);
307 return 0;
308}
309
310static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200311resize(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200312 struct weston_pointer *pointer, uint32_t edges)
313{
314 if (surface->state == TOPLEVEL ||
315 surface->state == MAXIMIZED ||
316 surface->state == FULLSCREEN)
317 weston_desktop_api_resize(surface->desktop, surface->surface,
318 pointer->seat, pointer->grab_serial,
319 edges);
320 return 0;
321}
322
323static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200324set_title(struct weston_desktop_xwayland_surface *surface, const char *title)
Quentin Glidic248dd102016-08-12 10:41:34 +0200325{
326 weston_desktop_surface_set_title(surface->surface, title);
327}
328
329static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200330set_window_geometry(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200331 int32_t x, int32_t y, int32_t width, int32_t height)
332{
333 surface->has_next_geometry = true;
334 surface->next_geometry.x = x;
335 surface->next_geometry.y = y;
336 surface->next_geometry.width = width;
337 surface->next_geometry.height = height;
338}
339
340static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200341set_maximized(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200342{
343 weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
344 0, 0);
345 weston_desktop_api_maximized_requested(surface->desktop,
346 surface->surface, true);
347}
348
349static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200350set_pid(struct weston_desktop_xwayland_surface *surface, pid_t pid)
Quentin Glidic248dd102016-08-12 10:41:34 +0200351{
Quentin Glidic955cec02016-08-12 10:41:35 +0200352 weston_desktop_surface_set_pid(surface->surface, pid);
Quentin Glidic248dd102016-08-12 10:41:34 +0200353}
354
Quentin Glidic955cec02016-08-12 10:41:35 +0200355static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_interface = {
356 .create_surface = create_surface,
357 .set_toplevel = set_toplevel,
358 .set_parent = set_parent,
359 .set_transient = set_transient,
360 .set_fullscreen = set_fullscreen,
361 .set_xwayland = set_xwayland,
362 .move = move,
363 .resize = resize,
364 .set_title = set_title,
365 .set_window_geometry = set_window_geometry,
366 .set_maximized = set_maximized,
367 .set_pid = set_pid,
368};
369
Quentin Glidic248dd102016-08-12 10:41:34 +0200370void
371weston_desktop_xwayland_init(struct weston_desktop *desktop)
372{
373 struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
374 struct weston_desktop_xwayland *xwayland;
375
376 xwayland = zalloc(sizeof(struct weston_desktop_xwayland));
377 if (xwayland == NULL)
378 return;
379
380 xwayland->desktop = desktop;
381 xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
382
383 weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link);
384
Quentin Glidic955cec02016-08-12 10:41:35 +0200385 compositor->xwayland = xwayland;
386 compositor->xwayland_interface = &weston_desktop_xwayland_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200387}