blob: 6b90c14a5e8495f04942101c6353a20a27b8e883 [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
Giulio Camuffof15320f2016-12-08 09:21:08 +0100244 weston_desktop_surface_set_pid(surface->surface, 0);
245
Quentin Glidic248dd102016-08-12 10:41:34 +0200246 return surface;
247}
248
249static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200250set_toplevel(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200251{
252 weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
253 0, 0);
254}
255
256static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200257set_parent(struct weston_desktop_xwayland_surface *surface,
258 struct weston_surface *wparent)
Quentin Glidic248dd102016-08-12 10:41:34 +0200259{
260 struct weston_desktop_surface *parent;
261
262 if (!weston_surface_is_desktop_surface(wparent))
263 return;
264
265 parent = weston_surface_get_desktop_surface(wparent);
Quentin Glidic955cec02016-08-12 10:41:35 +0200266 weston_desktop_api_set_parent(surface->desktop, surface->surface, parent);
Quentin Glidic248dd102016-08-12 10:41:34 +0200267}
268
269static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200270set_transient(struct weston_desktop_xwayland_surface *surface,
271 struct weston_surface *wparent, int x, int y)
272{
273 struct weston_desktop_surface *parent;
274
275 if (!weston_surface_is_desktop_surface(wparent))
276 return;
277
278 parent = weston_surface_get_desktop_surface(wparent);
279 weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent,
280 x, y);
281}
282
283static void
284set_fullscreen(struct weston_desktop_xwayland_surface *surface,
285 struct weston_output *output)
Quentin Glidic248dd102016-08-12 10:41:34 +0200286{
287 weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
288 0, 0);
289 weston_desktop_api_fullscreen_requested(surface->desktop,
290 surface->surface, true, output);
291}
292
293static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200294set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y)
Quentin Glidic248dd102016-08-12 10:41:34 +0200295{
296 weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL,
297 x, y);
298}
299
300static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200301move(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200302 struct weston_pointer *pointer)
303{
304 if (surface->state == TOPLEVEL ||
305 surface->state == MAXIMIZED ||
306 surface->state == FULLSCREEN)
307 weston_desktop_api_move(surface->desktop, surface->surface,
308 pointer->seat, pointer->grab_serial);
309 return 0;
310}
311
312static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200313resize(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200314 struct weston_pointer *pointer, uint32_t edges)
315{
316 if (surface->state == TOPLEVEL ||
317 surface->state == MAXIMIZED ||
318 surface->state == FULLSCREEN)
319 weston_desktop_api_resize(surface->desktop, surface->surface,
320 pointer->seat, pointer->grab_serial,
321 edges);
322 return 0;
323}
324
325static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200326set_title(struct weston_desktop_xwayland_surface *surface, const char *title)
Quentin Glidic248dd102016-08-12 10:41:34 +0200327{
328 weston_desktop_surface_set_title(surface->surface, title);
329}
330
331static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200332set_window_geometry(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200333 int32_t x, int32_t y, int32_t width, int32_t height)
334{
335 surface->has_next_geometry = true;
336 surface->next_geometry.x = x;
337 surface->next_geometry.y = y;
338 surface->next_geometry.width = width;
339 surface->next_geometry.height = height;
340}
341
342static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200343set_maximized(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200344{
345 weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
346 0, 0);
347 weston_desktop_api_maximized_requested(surface->desktop,
348 surface->surface, true);
349}
350
351static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200352set_pid(struct weston_desktop_xwayland_surface *surface, pid_t pid)
Quentin Glidic248dd102016-08-12 10:41:34 +0200353{
Quentin Glidic955cec02016-08-12 10:41:35 +0200354 weston_desktop_surface_set_pid(surface->surface, pid);
Quentin Glidic248dd102016-08-12 10:41:34 +0200355}
356
Quentin Glidic955cec02016-08-12 10:41:35 +0200357static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_interface = {
358 .create_surface = create_surface,
359 .set_toplevel = set_toplevel,
360 .set_parent = set_parent,
361 .set_transient = set_transient,
362 .set_fullscreen = set_fullscreen,
363 .set_xwayland = set_xwayland,
364 .move = move,
365 .resize = resize,
366 .set_title = set_title,
367 .set_window_geometry = set_window_geometry,
368 .set_maximized = set_maximized,
369 .set_pid = set_pid,
370};
371
Quentin Glidic248dd102016-08-12 10:41:34 +0200372void
373weston_desktop_xwayland_init(struct weston_desktop *desktop)
374{
375 struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
376 struct weston_desktop_xwayland *xwayland;
377
378 xwayland = zalloc(sizeof(struct weston_desktop_xwayland));
379 if (xwayland == NULL)
380 return;
381
382 xwayland->desktop = desktop;
383 xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
384
385 weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link);
386
Quentin Glidic955cec02016-08-12 10:41:35 +0200387 compositor->xwayland = xwayland;
388 compositor->xwayland_interface = &weston_desktop_xwayland_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200389}