blob: 62a3389951c50408c71c2ad9a7e428dc32a130f4 [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);
Pekka Paalanena838b782016-11-15 11:43:36 +020077 assert(!parent || state == TRANSIENT);
Quentin Glidic248dd102016-08-12 10:41:34 +020078
Quentin Glidic6384edf2016-08-16 11:42:47 +020079 if (to_add && surface->added) {
80 surface->state = state;
Quentin Glidic248dd102016-08-12 10:41:34 +020081 return;
Quentin Glidic6384edf2016-08-16 11:42:47 +020082 }
Quentin Glidic248dd102016-08-12 10:41:34 +020083
84 if (surface->state != state) {
85 if (surface->state == XWAYLAND) {
Quentin Glidicf01ecee2016-08-16 10:52:46 +020086 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidicf6636a82016-08-16 10:55:02 +020087 weston_view_destroy(surface->view);
Quentin Glidic248dd102016-08-12 10:41:34 +020088 surface->view = NULL;
89 }
90
91 if (to_add) {
92 weston_desktop_surface_unset_relative_to(surface->surface);
93 weston_desktop_api_surface_added(surface->desktop,
94 surface->surface);
95 } else if (surface->added) {
96 weston_desktop_api_surface_removed(surface->desktop,
97 surface->surface);
98 }
99
100 if (state == XWAYLAND) {
101 surface->view =
102 weston_desktop_surface_create_view(surface->surface);
103 weston_layer_entry_insert(&surface->xwayland->layer.view_list,
104 &surface->view->layer_link);
105 weston_view_set_position(surface->view, x, y);
106 }
107
108 surface->state = state;
109 surface->added = to_add;
110 }
111
112 if (parent != NULL)
113 weston_desktop_surface_set_relative_to(surface->surface, parent,
114 x, y, false);
115}
116
117static void
118weston_desktop_xwayland_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +0200119 void *user_data,
Quentin Glidic248dd102016-08-12 10:41:34 +0200120 int32_t sx, int32_t sy)
121{
Quentin Glidic955cec02016-08-12 10:41:35 +0200122 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200123
124 if (surface->has_next_geometry) {
125 surface->has_next_geometry = false;
126 weston_desktop_surface_set_geometry(surface->surface,
127 surface->next_geometry);
128 }
129
130 if (surface->added)
131 weston_desktop_api_committed(surface->desktop, surface->surface,
132 sx, sy);
133}
134
135static void
136weston_desktop_xwayland_surface_set_size(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200137 void *user_data,
138 int32_t width, int32_t height)
Quentin Glidic248dd102016-08-12 10:41:34 +0200139{
Quentin Glidic955cec02016-08-12 10:41:35 +0200140 struct weston_desktop_xwayland_surface *surface = user_data;
141 struct weston_surface *wsurface =
142 weston_desktop_surface_get_surface(surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200143
Quentin Glidic955cec02016-08-12 10:41:35 +0200144 surface->client_interface->send_configure(wsurface, width, height);
Quentin Glidic248dd102016-08-12 10:41:34 +0200145}
146
147static void
148weston_desktop_xwayland_surface_destroy(struct weston_desktop_surface *dsurface,
149 void *user_data)
150{
Quentin Glidic955cec02016-08-12 10:41:35 +0200151 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200152
153 wl_list_remove(&surface->resource_destroy_listener.link);
154
155 weston_desktop_surface_unset_relative_to(surface->surface);
Quentin Glidic1714f012016-08-18 16:45:30 +0200156 if (surface->added)
Quentin Glidic248dd102016-08-12 10:41:34 +0200157 weston_desktop_api_surface_removed(surface->desktop,
158 surface->surface);
Quentin Glidic1714f012016-08-18 16:45:30 +0200159 else if (surface->state == XWAYLAND)
Quentin Glidicf01ecee2016-08-16 10:52:46 +0200160 weston_desktop_surface_unlink_view(surface->view);
Quentin Glidic248dd102016-08-12 10:41:34 +0200161
162 free(surface);
163}
164
165static bool
166weston_desktop_xwayland_surface_get_maximized(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200167 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200168{
Quentin Glidic955cec02016-08-12 10:41:35 +0200169 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200170
171 return surface->state == MAXIMIZED;
172}
173
174static bool
175weston_desktop_xwayland_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
Quentin Glidic955cec02016-08-12 10:41:35 +0200176 void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200177{
Quentin Glidic955cec02016-08-12 10:41:35 +0200178 struct weston_desktop_xwayland_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200179
180 return surface->state == FULLSCREEN;
181}
182
183static const struct weston_desktop_surface_implementation weston_desktop_xwayland_surface_internal_implementation = {
184 .committed = weston_desktop_xwayland_surface_committed,
185 .set_size = weston_desktop_xwayland_surface_set_size,
186
187 .get_maximized = weston_desktop_xwayland_surface_get_maximized,
188 .get_fullscreen = weston_desktop_xwayland_surface_get_fullscreen,
189
190 .destroy = weston_desktop_xwayland_surface_destroy,
191};
192
193static void
194weston_destop_xwayland_resource_destroyed(struct wl_listener *listener,
195 void *data)
196{
Quentin Glidic955cec02016-08-12 10:41:35 +0200197 struct weston_desktop_xwayland_surface *surface =
Quentin Glidic248dd102016-08-12 10:41:34 +0200198 wl_container_of(listener, surface, resource_destroy_listener);
199
200 weston_desktop_surface_destroy(surface->surface);
201}
202
Quentin Glidic955cec02016-08-12 10:41:35 +0200203static struct weston_desktop_xwayland_surface *
204create_surface(struct weston_desktop_xwayland *xwayland,
205 struct weston_surface *wsurface,
206 const struct weston_xwayland_client_interface *client_interface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200207{
Quentin Glidic955cec02016-08-12 10:41:35 +0200208 struct weston_desktop_xwayland_surface *surface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200209
Quentin Glidic955cec02016-08-12 10:41:35 +0200210 surface = zalloc(sizeof(struct weston_desktop_xwayland_surface));
Quentin Glidic248dd102016-08-12 10:41:34 +0200211 if (surface == NULL)
212 return NULL;
213
214 surface->xwayland = xwayland;
215 surface->desktop = xwayland->desktop;
Quentin Glidic955cec02016-08-12 10:41:35 +0200216 surface->client_interface = client_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200217
218 surface->surface =
219 weston_desktop_surface_create(surface->desktop,
220 xwayland->client, wsurface,
221 &weston_desktop_xwayland_surface_internal_implementation,
222 surface);
223 if (surface->surface == NULL) {
224 free(surface);
225 return NULL;
226 }
227
228 surface->resource_destroy_listener.notify =
229 weston_destop_xwayland_resource_destroyed;
230 wl_resource_add_destroy_listener(wsurface->resource,
231 &surface->resource_destroy_listener);
232
233 return surface;
234}
235
236static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200237set_toplevel(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200238{
239 weston_desktop_xwayland_surface_change_state(surface, TOPLEVEL, NULL,
240 0, 0);
241}
242
243static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200244set_parent(struct weston_desktop_xwayland_surface *surface,
245 struct weston_surface *wparent)
Quentin Glidic248dd102016-08-12 10:41:34 +0200246{
247 struct weston_desktop_surface *parent;
248
249 if (!weston_surface_is_desktop_surface(wparent))
250 return;
251
252 parent = weston_surface_get_desktop_surface(wparent);
Quentin Glidic955cec02016-08-12 10:41:35 +0200253 weston_desktop_api_set_parent(surface->desktop, surface->surface, parent);
Quentin Glidic248dd102016-08-12 10:41:34 +0200254}
255
256static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200257set_transient(struct weston_desktop_xwayland_surface *surface,
258 struct weston_surface *wparent, int x, int y)
259{
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);
266 weston_desktop_xwayland_surface_change_state(surface, TRANSIENT, parent,
267 x, y);
268}
269
270static void
271set_fullscreen(struct weston_desktop_xwayland_surface *surface,
272 struct weston_output *output)
Quentin Glidic248dd102016-08-12 10:41:34 +0200273{
274 weston_desktop_xwayland_surface_change_state(surface, FULLSCREEN, NULL,
275 0, 0);
276 weston_desktop_api_fullscreen_requested(surface->desktop,
277 surface->surface, true, output);
278}
279
280static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200281set_xwayland(struct weston_desktop_xwayland_surface *surface, int x, int y)
Quentin Glidic248dd102016-08-12 10:41:34 +0200282{
283 weston_desktop_xwayland_surface_change_state(surface, XWAYLAND, NULL,
284 x, y);
285}
286
287static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200288move(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200289 struct weston_pointer *pointer)
290{
291 if (surface->state == TOPLEVEL ||
292 surface->state == MAXIMIZED ||
293 surface->state == FULLSCREEN)
294 weston_desktop_api_move(surface->desktop, surface->surface,
295 pointer->seat, pointer->grab_serial);
296 return 0;
297}
298
299static int
Quentin Glidic955cec02016-08-12 10:41:35 +0200300resize(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200301 struct weston_pointer *pointer, uint32_t edges)
302{
303 if (surface->state == TOPLEVEL ||
304 surface->state == MAXIMIZED ||
305 surface->state == FULLSCREEN)
306 weston_desktop_api_resize(surface->desktop, surface->surface,
307 pointer->seat, pointer->grab_serial,
308 edges);
309 return 0;
310}
311
312static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200313set_title(struct weston_desktop_xwayland_surface *surface, const char *title)
Quentin Glidic248dd102016-08-12 10:41:34 +0200314{
315 weston_desktop_surface_set_title(surface->surface, title);
316}
317
318static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200319set_window_geometry(struct weston_desktop_xwayland_surface *surface,
Quentin Glidic248dd102016-08-12 10:41:34 +0200320 int32_t x, int32_t y, int32_t width, int32_t height)
321{
322 surface->has_next_geometry = true;
323 surface->next_geometry.x = x;
324 surface->next_geometry.y = y;
325 surface->next_geometry.width = width;
326 surface->next_geometry.height = height;
327}
328
329static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200330set_maximized(struct weston_desktop_xwayland_surface *surface)
Quentin Glidic248dd102016-08-12 10:41:34 +0200331{
332 weston_desktop_xwayland_surface_change_state(surface, MAXIMIZED, NULL,
333 0, 0);
334 weston_desktop_api_maximized_requested(surface->desktop,
335 surface->surface, true);
336}
337
338static void
Quentin Glidic955cec02016-08-12 10:41:35 +0200339set_pid(struct weston_desktop_xwayland_surface *surface, pid_t pid)
Quentin Glidic248dd102016-08-12 10:41:34 +0200340{
Quentin Glidic955cec02016-08-12 10:41:35 +0200341 weston_desktop_surface_set_pid(surface->surface, pid);
Quentin Glidic248dd102016-08-12 10:41:34 +0200342}
343
Quentin Glidic955cec02016-08-12 10:41:35 +0200344static const struct weston_desktop_xwayland_interface weston_desktop_xwayland_interface = {
345 .create_surface = create_surface,
346 .set_toplevel = set_toplevel,
347 .set_parent = set_parent,
348 .set_transient = set_transient,
349 .set_fullscreen = set_fullscreen,
350 .set_xwayland = set_xwayland,
351 .move = move,
352 .resize = resize,
353 .set_title = set_title,
354 .set_window_geometry = set_window_geometry,
355 .set_maximized = set_maximized,
356 .set_pid = set_pid,
357};
358
Quentin Glidic248dd102016-08-12 10:41:34 +0200359void
360weston_desktop_xwayland_init(struct weston_desktop *desktop)
361{
362 struct weston_compositor *compositor = weston_desktop_get_compositor(desktop);
363 struct weston_desktop_xwayland *xwayland;
364
365 xwayland = zalloc(sizeof(struct weston_desktop_xwayland));
366 if (xwayland == NULL)
367 return;
368
369 xwayland->desktop = desktop;
370 xwayland->client = weston_desktop_client_create(desktop, NULL, NULL, NULL, NULL, 0, 0);
371
372 weston_layer_init(&xwayland->layer, &compositor->cursor_layer.link);
373
Quentin Glidic955cec02016-08-12 10:41:35 +0200374 compositor->xwayland = xwayland;
375 compositor->xwayland_interface = &weston_desktop_xwayland_interface;
Quentin Glidic248dd102016-08-12 10:41:34 +0200376}