blob: cb083237fd1ccb218f7fcf2b0c783565d567d3fa [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{
74 bool to_add = (parent == NULL && state != XWAYLAND);
75
76 assert(state != NONE);
77
Quentin Glidic6384edf2016-08-16 11:42:47 +020078 if (to_add && surface->added) {
79 surface->state = state;
Quentin Glidic248dd102016-08-12 10:41:34 +020080 return;
Quentin Glidic6384edf2016-08-16 11:42:47 +020081 }
Quentin Glidic248dd102016-08-12 10:41:34 +020082
83 if (surface->state != state) {
84 if (surface->state == XWAYLAND) {
Quentin Glidicf01ecee2016-08-16 10:52:46 +020085 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidicf6636a82016-08-16 10:55:02 +020086 weston_view_destroy(surface->view);
Quentin Glidic248dd102016-08-12 10:41:34 +020087 surface->view = NULL;
88 }
89
90 if (to_add) {
91 weston_desktop_surface_unset_relative_to(surface->surface);
92 weston_desktop_api_surface_added(surface->desktop,
93 surface->surface);
94 } else if (surface->added) {
95 weston_desktop_api_surface_removed(surface->desktop,
96 surface->surface);
97 }
98
99 if (state == XWAYLAND) {
100 surface->view =
101 weston_desktop_surface_create_view(surface->surface);
102 weston_layer_entry_insert(&surface->xwayland->layer.view_list,
103 &surface->view->layer_link);
104 weston_view_set_position(surface->view, x, y);
105 }
106
107 surface->state = state;
108 surface->added = to_add;
109 }
110
111 if (parent != NULL)
112 weston_desktop_surface_set_relative_to(surface->surface, parent,
113 x, y, false);
114}
115
116static void
117weston_desktop_xwayland_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +0200118 void *user_data,
Quentin Glidic248dd102016-08-12 10:41:34 +0200119 int32_t sx, int32_t sy)
120{
Quentin Glidic955cec02016-08-12 10:41:35 +0200121 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200122
123 if (surface->has_next_geometry) {
124 surface->has_next_geometry = false;
125 weston_desktop_surface_set_geometry(surface->surface,
126 surface->next_geometry);
127 }
128
129 if (surface->added)
130 weston_desktop_api_committed(surface->desktop, surface->surface,
131 sx, sy);
132}
133
134static void
135weston_desktop_xwayland_surface_set_size(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200136 void *user_data,
137 int32_t width, int32_t height)
Quentin Glidic248dd102016-08-12 10:41:34 +0200138{
Quentin Glidic955cec02016-08-12 10:41:35 +0200139 struct weston_desktop_xwayland_surface *surface = user_data;
140 struct weston_surface *wsurface =
141 weston_desktop_surface_get_surface(surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200142
Quentin Glidic955cec02016-08-12 10:41:35 +0200143 surface->client_interface->send_configure(wsurface, width, height);
Quentin Glidic248dd102016-08-12 10:41:34 +0200144}
145
146static void
147weston_desktop_xwayland_surface_destroy(struct weston_desktop_surface *dsurface,
148 void *user_data)
149{
Quentin Glidic955cec02016-08-12 10:41:35 +0200150 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200151
152 wl_list_remove(&surface->resource_destroy_listener.link);
153
154 weston_desktop_surface_unset_relative_to(surface->surface);
Quentin Glidicf6636a82016-08-16 10:55:02 +0200155 if (surface->added) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200156 weston_desktop_api_surface_removed(surface->desktop,
157 surface->surface);
Quentin Glidicf6636a82016-08-16 10:55:02 +0200158 } else if (surface->state == XWAYLAND) {
Quentin Glidicf01ecee2016-08-16 10:52:46 +0200159 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidicf6636a82016-08-16 10:55:02 +0200160 weston_view_destroy(surface->view);
161 }
Quentin Glidic248dd102016-08-12 10:41:34 +0200162
163 free(surface);
164}
165
166static bool
167weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200168 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200169{
Quentin Glidic955cec02016-08-12 10:41:35 +0200170 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200171
172 return surface->state == MAXIMIZED;
173}
174
175static bool
176weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200177 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200178{
Quentin Glidic955cec02016-08-12 10:41:35 +0200179 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200180
181 return surface->state == FULLSCREEN;
182}
183
184static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
185 .committed = weston_desktop_xwayland_surface_committed,
186 .set_size = weston_desktop_xwayland_surface_set_size,
187
188 .get_maximized = weston_desktop_xwayland_surface_get_maximized,
189 .get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
190
191 .destroy = weston_desktop_xwayland_surface_destroy,
192};
193
194static void
195weston_destop_xwayland_resource_destroyed(struct wl_listener *listener,
196 void *data)
197{
Quentin Glidic955cec02016-08-12 10:41:35 +0200198 struct weston_desktop_xwayland_surface *surface =
Quentin Glidic248dd102016-08-12 10:41:34 +0200199 wl_container_of(listener, surface, resource_destroy_listener);
200
201 weston_desktop_surface_destroy(surface->surface);
202}
203
Quentin Glidic955cec02016-08-12 10:41:35 +0200204static struct weston_desktop_xwayland_surface *
205create_surface(struct weston_desktop_xwayland *xwayland,
206 struct weston_surface *wsurface,
207 const struct weston_xwayland_client_interface *client_interface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200208{
Quentin Glidic955cec02016-08-12 10:41:35 +0200209 struct weston_desktop_xwayland_surface *surface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200210
Quentin Glidic955cec02016-08-12 10:41:35 +0200211 surface = zalloc(sizeof(struct weston_desktop_xwayland_surface));
Quentin Glidic248dd102016-08-12 10:41:34 +0200212 if (surface == NULL)
213 return NULL;
214
215 surface->xwayland = xwayland;
216 surface->desktop = xwayland->desktop;
Quentin Glidic955cec02016-08-12 10:41:35 +0200217 surface->client_interface = client_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200218
219 surface->surface =
220 weston_desktop_surface_create(surface->desktop,
221 xwayland->client, wsurface,
222 &weston_desktop_xwayland_surface_internal_implementation,
223 surface);
224 if (surface->surface == NULL) {
225 free(surface);
226 return NULL;
227 }
228
229 surface->resource_destroy_listener.notify =
230 weston_destop_xwayland_resource_destroyed;
231 wl_resource_add_destroy_listener(wsurface->resource,
232 &surface->resource_destroy_listener);
233
234 return surface;
235}
236
237static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200238set_toplevel(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200239{
240 weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
241 0, 0);
242}
243
244static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200245set_parent(struct weston_desktop_xwayland_surface *surface,
246 struct weston_surface *wparent)
Quentin Glidic248dd102016-08-12 10:41:34 +0200247{
248 struct weston_desktop_surface *parent;
249
250 if (!weston_surface_is_desktop_surface(wparent))
251 return;
252
253 parent = weston_surface_get_desktop_surface(wparent);
Quentin Glidic955cec02016-08-12 10:41:35 +0200254 weston_desktop_api_set_parent(surface->desktop, surface->surface, parent);
Quentin Glidic248dd102016-08-12 10:41:34 +0200255}
256
257static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200258set_transient(struct weston_desktop_xwayland_surface *surface,
259 struct weston_surface *wparent, int x, int y)
260{
261 struct weston_desktop_surface *parent;
262
263 if (!weston_surface_is_desktop_surface(wparent))
264 return;
265
266 parent = weston_surface_get_desktop_surface(wparent);
267 weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent,
268 x, y);
269}
270
271static void
272set_fullscreen(struct weston_desktop_xwayland_surface *surface,
273 struct weston_output *output)
Quentin Glidic248dd102016-08-12 10:41:34 +0200274{
275 weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
276 0, 0);
277 weston_desktop_api_fullscreen_requested(surface->desktop,
278 surface->surface, true, output);
279}
280
281static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200282set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y)
Quentin Glidic248dd102016-08-12 10:41:34 +0200283{
284 weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL,
285 x, y);
286}
287
288static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200289move(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200290 struct weston_pointer *pointer)
291{
292 if (surface->state == TOPLEVEL ||
293 surface->state == MAXIMIZED ||
294 surface->state == FULLSCREEN)
295 weston_desktop_api_move(surface->desktop, surface->surface,
296 pointer->seat, pointer->grab_serial);
297 return 0;
298}
299
300static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200301resize(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200302 struct weston_pointer *pointer, uint32_t edges)
303{
304 if (surface->state == TOPLEVEL ||
305 surface->state == MAXIMIZED ||
306 surface->state == FULLSCREEN)
307 weston_desktop_api_resize(surface->desktop, surface->surface,
308 pointer->seat, pointer->grab_serial,
309 edges);
310 return 0;
311}
312
313static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200314set_title(struct weston_desktop_xwayland_surface *surface, const char *title)
Quentin Glidic248dd102016-08-12 10:41:34 +0200315{
316 weston_desktop_surface_set_title(surface->surface, title);
317}
318
319static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200320set_window_geometry(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200321 int32_t x, int32_t y, int32_t width, int32_t height)
322{
323 surface->has_next_geometry = true;
324 surface->next_geometry.x = x;
325 surface->next_geometry.y = y;
326 surface->next_geometry.width = width;
327 surface->next_geometry.height = height;
328}
329
330static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200331set_maximized(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200332{
333 weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
334 0, 0);
335 weston_desktop_api_maximized_requested(surface->desktop,
336 surface->surface, true);
337}
338
339static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200340set_pid(struct weston_desktop_xwayland_surface *surface, pid_t pid)
Quentin Glidic248dd102016-08-12 10:41:34 +0200341{
Quentin Glidic955cec02016-08-12 10:41:35 +0200342 weston_desktop_surface_set_pid(surface->surface, pid);
Quentin Glidic248dd102016-08-12 10:41:34 +0200343}
344
Quentin Glidic955cec02016-08-12 10:41:35 +0200345static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_interface = {
346 .create_surface = create_surface,
347 .set_toplevel = set_toplevel,
348 .set_parent = set_parent,
349 .set_transient = set_transient,
350 .set_fullscreen = set_fullscreen,
351 .set_xwayland = set_xwayland,
352 .move = move,
353 .resize = resize,
354 .set_title = set_title,
355 .set_window_geometry = set_window_geometry,
356 .set_maximized = set_maximized,
357 .set_pid = set_pid,
358};
359
Quentin Glidic248dd102016-08-12 10:41:34 +0200360void
361weston_desktop_xwayland_init(struct weston_desktop *desktop)
362{
363 struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
364 struct weston_desktop_xwayland *xwayland;
365
366 xwayland = zalloc(sizeof(struct weston_desktop_xwayland));
367 if (xwayland == NULL)
368 return;
369
370 xwayland->desktop = desktop;
371 xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
372
373 weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link);
374
Quentin Glidic955cec02016-08-12 10:41:35 +0200375 compositor->xwayland = xwayland;
376 compositor->xwayland_interface = &weston_desktop_xwayland_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200377}