blob: 7362a72600ed7a25b51d4f1921cbd593f2398acb [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
78 if (to_add && surface->added)
79 return;
80
81 if (surface->state != state) {
82 if (surface->state == XWAYLAND) {
83 weston_desktop_surface_destroy_view(surface->view);
84 surface->view = NULL;
85 }
86
87 if (to_add) {
88 weston_desktop_surface_unset_relative_to(surface->surface);
89 weston_desktop_api_surface_added(surface->desktop,
90 surface->surface);
91 } else if (surface->added) {
92 weston_desktop_api_surface_removed(surface->desktop,
93 surface->surface);
94 }
95
96 if (state == XWAYLAND) {
97 surface->view =
98 weston_desktop_surface_create_view(surface->surface);
99 weston_layer_entry_insert(&surface->xwayland->layer.view_list,
100 &surface->view->layer_link);
101 weston_view_set_position(surface->view, x, y);
102 }
103
104 surface->state = state;
105 surface->added = to_add;
106 }
107
108 if (parent != NULL)
109 weston_desktop_surface_set_relative_to(surface->surface, parent,
110 x, y, false);
111}
112
113static void
114weston_desktop_xwayland_surface_committed(struct weston_desktop_surface *dsurface,
115 void *user_data, bool new_buffer,
116 int32_t sx, int32_t sy)
117{
Quentin Glidic955cec02016-08-12 10:41:35 +0200118 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200119
120 if (surface->has_next_geometry) {
121 surface->has_next_geometry = false;
122 weston_desktop_surface_set_geometry(surface->surface,
123 surface->next_geometry);
124 }
125
126 if (surface->added)
127 weston_desktop_api_committed(surface->desktop, surface->surface,
128 sx, sy);
129}
130
131static void
132weston_desktop_xwayland_surface_set_size(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200133 void *user_data,
134 int32_t width, int32_t height)
Quentin Glidic248dd102016-08-12 10:41:34 +0200135{
Quentin Glidic955cec02016-08-12 10:41:35 +0200136 struct weston_desktop_xwayland_surface *surface = user_data;
137 struct weston_surface *wsurface =
138 weston_desktop_surface_get_surface(surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200139
Quentin Glidic955cec02016-08-12 10:41:35 +0200140 surface->client_interface->send_configure(wsurface, width, height);
Quentin Glidic248dd102016-08-12 10:41:34 +0200141}
142
143static void
144weston_desktop_xwayland_surface_destroy(struct weston_desktop_surface *dsurface,
145 void *user_data)
146{
Quentin Glidic955cec02016-08-12 10:41:35 +0200147 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200148
149 wl_list_remove(&surface->resource_destroy_listener.link);
150
151 weston_desktop_surface_unset_relative_to(surface->surface);
152 if (surface->added)
153 weston_desktop_api_surface_removed(surface->desktop,
154 surface->surface);
155 else if (surface->state == XWAYLAND)
156 weston_desktop_surface_destroy_view(surface->view);
157
158 free(surface);
159}
160
161static bool
162weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200163 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200164{
Quentin Glidic955cec02016-08-12 10:41:35 +0200165 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200166
167 return surface->state == MAXIMIZED;
168}
169
170static bool
171weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200172 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200173{
Quentin Glidic955cec02016-08-12 10:41:35 +0200174 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200175
176 return surface->state == FULLSCREEN;
177}
178
179static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
180 .committed = weston_desktop_xwayland_surface_committed,
181 .set_size = weston_desktop_xwayland_surface_set_size,
182
183 .get_maximized = weston_desktop_xwayland_surface_get_maximized,
184 .get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
185
186 .destroy = weston_desktop_xwayland_surface_destroy,
187};
188
189static void
190weston_destop_xwayland_resource_destroyed(struct wl_listener *listener,
191 void *data)
192{
Quentin Glidic955cec02016-08-12 10:41:35 +0200193 struct weston_desktop_xwayland_surface *surface =
Quentin Glidic248dd102016-08-12 10:41:34 +0200194 wl_container_of(listener, surface, resource_destroy_listener);
195
196 weston_desktop_surface_destroy(surface->surface);
197}
198
Quentin Glidic955cec02016-08-12 10:41:35 +0200199static struct weston_desktop_xwayland_surface *
200create_surface(struct weston_desktop_xwayland *xwayland,
201 struct weston_surface *wsurface,
202 const struct weston_xwayland_client_interface *client_interface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200203{
Quentin Glidic955cec02016-08-12 10:41:35 +0200204 struct weston_desktop_xwayland_surface *surface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200205
Quentin Glidic955cec02016-08-12 10:41:35 +0200206 surface = zalloc(sizeof(struct weston_desktop_xwayland_surface));
Quentin Glidic248dd102016-08-12 10:41:34 +0200207 if (surface == NULL)
208 return NULL;
209
210 surface->xwayland = xwayland;
211 surface->desktop = xwayland->desktop;
Quentin Glidic955cec02016-08-12 10:41:35 +0200212 surface->client_interface = client_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200213
214 surface->surface =
215 weston_desktop_surface_create(surface->desktop,
216 xwayland->client, wsurface,
217 &weston_desktop_xwayland_surface_internal_implementation,
218 surface);
219 if (surface->surface == NULL) {
220 free(surface);
221 return NULL;
222 }
223
224 surface->resource_destroy_listener.notify =
225 weston_destop_xwayland_resource_destroyed;
226 wl_resource_add_destroy_listener(wsurface->resource,
227 &surface->resource_destroy_listener);
228
229 return surface;
230}
231
232static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200233set_toplevel(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200234{
235 weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
236 0, 0);
237}
238
239static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200240set_parent(struct weston_desktop_xwayland_surface *surface,
241 struct weston_surface *wparent)
Quentin Glidic248dd102016-08-12 10:41:34 +0200242{
243 struct weston_desktop_surface *parent;
244
245 if (!weston_surface_is_desktop_surface(wparent))
246 return;
247
248 parent = weston_surface_get_desktop_surface(wparent);
Quentin Glidic955cec02016-08-12 10:41:35 +0200249 weston_desktop_api_set_parent(surface->desktop, surface->surface, parent);
Quentin Glidic248dd102016-08-12 10:41:34 +0200250}
251
252static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200253set_transient(struct weston_desktop_xwayland_surface *surface,
254 struct weston_surface *wparent, int x, int y)
255{
256 struct weston_desktop_surface *parent;
257
258 if (!weston_surface_is_desktop_surface(wparent))
259 return;
260
261 parent = weston_surface_get_desktop_surface(wparent);
262 weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent,
263 x, y);
264}
265
266static void
267set_fullscreen(struct weston_desktop_xwayland_surface *surface,
268 struct weston_output *output)
Quentin Glidic248dd102016-08-12 10:41:34 +0200269{
270 weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
271 0, 0);
272 weston_desktop_api_fullscreen_requested(surface->desktop,
273 surface->surface, true, output);
274}
275
276static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200277set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y)
Quentin Glidic248dd102016-08-12 10:41:34 +0200278{
279 weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL,
280 x, y);
281}
282
283static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200284move(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200285 struct weston_pointer *pointer)
286{
287 if (surface->state == TOPLEVEL ||
288 surface->state == MAXIMIZED ||
289 surface->state == FULLSCREEN)
290 weston_desktop_api_move(surface->desktop, surface->surface,
291 pointer->seat, pointer->grab_serial);
292 return 0;
293}
294
295static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200296resize(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200297 struct weston_pointer *pointer, uint32_t edges)
298{
299 if (surface->state == TOPLEVEL ||
300 surface->state == MAXIMIZED ||
301 surface->state == FULLSCREEN)
302 weston_desktop_api_resize(surface->desktop, surface->surface,
303 pointer->seat, pointer->grab_serial,
304 edges);
305 return 0;
306}
307
308static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200309set_title(struct weston_desktop_xwayland_surface *surface, const char *title)
Quentin Glidic248dd102016-08-12 10:41:34 +0200310{
311 weston_desktop_surface_set_title(surface->surface, title);
312}
313
314static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200315set_window_geometry(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200316 int32_t x, int32_t y, int32_t width, int32_t height)
317{
318 surface->has_next_geometry = true;
319 surface->next_geometry.x = x;
320 surface->next_geometry.y = y;
321 surface->next_geometry.width = width;
322 surface->next_geometry.height = height;
323}
324
325static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200326set_maximized(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200327{
328 weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
329 0, 0);
330 weston_desktop_api_maximized_requested(surface->desktop,
331 surface->surface, true);
332}
333
334static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200335set_pid(struct weston_desktop_xwayland_surface *surface, pid_t pid)
Quentin Glidic248dd102016-08-12 10:41:34 +0200336{
Quentin Glidic955cec02016-08-12 10:41:35 +0200337 weston_desktop_surface_set_pid(surface->surface, pid);
Quentin Glidic248dd102016-08-12 10:41:34 +0200338}
339
Quentin Glidic955cec02016-08-12 10:41:35 +0200340static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_interface = {
341 .create_surface = create_surface,
342 .set_toplevel = set_toplevel,
343 .set_parent = set_parent,
344 .set_transient = set_transient,
345 .set_fullscreen = set_fullscreen,
346 .set_xwayland = set_xwayland,
347 .move = move,
348 .resize = resize,
349 .set_title = set_title,
350 .set_window_geometry = set_window_geometry,
351 .set_maximized = set_maximized,
352 .set_pid = set_pid,
353};
354
Quentin Glidic248dd102016-08-12 10:41:34 +0200355void
356weston_desktop_xwayland_init(struct weston_desktop *desktop)
357{
358 struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
359 struct weston_desktop_xwayland *xwayland;
360
361 xwayland = zalloc(sizeof(struct weston_desktop_xwayland));
362 if (xwayland == NULL)
363 return;
364
365 xwayland->desktop = desktop;
366 xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
367
368 weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link);
369
Quentin Glidic955cec02016-08-12 10:41:35 +0200370 compositor->xwayland = xwayland;
371 compositor->xwayland_interface = &weston_desktop_xwayland_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200372}