blob: 0fb067abf7bd129b3c91d7efccbd23de8d3d083f [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 <stdbool.h>
30
31#include <wayland-server.h>
32
33#include "compositor.h"
34#include "zalloc.h"
Daniel Stone7dbb0e12016-11-24 15:30:41 +000035#include "xdg-shell-unstable-v5-server-protocol.h"
Quentin Glidic248dd102016-08-12 10:41:34 +020036
37#include "libweston-desktop.h"
38#include "internal.h"
39
40#define WD_XDG_SHELL_PROTOCOL_VERSION 1
41
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020042struct weston_desktop_xdg_surface_state {
43 bool maximized;
44 bool fullscreen;
45 bool resizing;
46 bool activated;
47};
48
Quentin Glidic248dd102016-08-12 10:41:34 +020049struct weston_desktop_xdg_surface {
50 struct wl_resource *resource;
51 struct weston_desktop_surface *surface;
52 struct weston_desktop *desktop;
Quentin Glidic6967f0e2016-08-18 15:51:38 +020053 bool added;
Quentin Glidic248dd102016-08-12 10:41:34 +020054 struct wl_event_source *add_idle;
55 struct wl_event_source *configure_idle;
56 uint32_t configure_serial;
Quentin Glidic248dd102016-08-12 10:41:34 +020057 struct {
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020058 struct weston_desktop_xdg_surface_state state;
59 struct weston_size size;
60 } pending;
61 struct {
62 struct weston_desktop_xdg_surface_state state;
63 } next;
64 struct {
65 struct weston_desktop_xdg_surface_state state;
66 } current;
Quentin Glidic248dd102016-08-12 10:41:34 +020067 bool has_next_geometry;
68 struct weston_geometry next_geometry;
69};
70
71struct weston_desktop_xdg_popup {
72 struct wl_resource *resource;
73 struct weston_desktop_surface *popup;
74 struct weston_desktop *desktop;
75 struct weston_desktop_seat *seat;
76 struct wl_display *display;
77};
78
79static void
Quentin Glidic6967f0e2016-08-18 15:51:38 +020080weston_desktop_xdg_surface_ensure_added(struct weston_desktop_xdg_surface *surface)
81{
82 if (surface->added)
83 return;
84
85 if (surface->add_idle != NULL)
86 wl_event_source_remove(surface->add_idle);
87 surface->add_idle = NULL;
88 weston_desktop_api_surface_added(surface->desktop, surface->surface);
89 surface->added = true;
90}
91
92static void
Quentin Glidic248dd102016-08-12 10:41:34 +020093weston_desktop_xdg_surface_send_configure(void *data)
94{
95 struct weston_desktop_xdg_surface *surface = data;
96 uint32_t *s;
97 struct wl_array states;
98
99 surface->configure_idle = NULL;
100
101 surface->configure_serial =
102 wl_display_next_serial(weston_desktop_get_display(surface->desktop));
103
104 wl_array_init(&states);
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200105 if (surface->pending.state.maximized) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200106 s = wl_array_add(&states, sizeof(uint32_t));
107 *s = XDG_SURFACE_STATE_MAXIMIZED;
108 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200109 if (surface->pending.state.fullscreen) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200110 s = wl_array_add(&states, sizeof(uint32_t));
111 *s = XDG_SURFACE_STATE_FULLSCREEN;
112 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200113 if (surface->pending.state.resizing) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200114 s = wl_array_add(&states, sizeof(uint32_t));
115 *s = XDG_SURFACE_STATE_RESIZING;
116 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200117 if (surface->pending.state.activated) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200118 s = wl_array_add(&states, sizeof(uint32_t));
119 *s = XDG_SURFACE_STATE_ACTIVATED;
120 }
121
122 xdg_surface_send_configure(surface->resource,
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200123 surface->pending.size.width,
124 surface->pending.size.height,
Quentin Glidic248dd102016-08-12 10:41:34 +0200125 &states,
126 surface->configure_serial);
127
128 wl_array_release(&states);
129};
130
Quentin Glidicd51f8262017-04-13 20:25:27 +0200131static bool
132weston_desktop_xdg_surface_state_compare(struct weston_desktop_xdg_surface *surface)
133{
134 struct weston_surface *wsurface =
135 weston_desktop_surface_get_surface(surface->surface);
136
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200137 if (surface->pending.state.activated != surface->current.state.activated)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200138 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200139 if (surface->pending.state.fullscreen != surface->current.state.fullscreen)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200140 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200141 if (surface->pending.state.maximized != surface->current.state.maximized)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200142 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200143 if (surface->pending.state.resizing != surface->current.state.resizing)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200144 return false;
145
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200146 if (wsurface->width == surface->pending.size.width &&
147 wsurface->height == surface->pending.size.height)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200148 return true;
149
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200150 if (surface->pending.size.width == 0 &&
151 surface->pending.size.height == 0)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200152 return true;
153
154 return false;
155}
156
Quentin Glidic248dd102016-08-12 10:41:34 +0200157static void
Quentin Glidicd51f8262017-04-13 20:25:27 +0200158weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
159 bool force)
Quentin Glidic248dd102016-08-12 10:41:34 +0200160{
161 struct wl_display *display = weston_desktop_get_display(surface->desktop);
162 struct wl_event_loop *loop = wl_display_get_event_loop(display);
Quentin Glidic218126d2017-07-11 13:31:36 +0200163 bool pending_same =
Quentin Glidicd51f8262017-04-13 20:25:27 +0200164 !force && weston_desktop_xdg_surface_state_compare(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200165
Quentin Glidicd51f8262017-04-13 20:25:27 +0200166 if (surface->configure_idle != NULL) {
Quentin Glidic218126d2017-07-11 13:31:36 +0200167 if (!pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200168 return;
169
170 wl_event_source_remove(surface->configure_idle);
171 surface->configure_idle = NULL;
172 } else {
Quentin Glidic218126d2017-07-11 13:31:36 +0200173 if (pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200174 return;
175
176 surface->configure_idle =
177 wl_event_loop_add_idle(loop,
178 weston_desktop_xdg_surface_send_configure,
179 surface);
180 }
Quentin Glidic248dd102016-08-12 10:41:34 +0200181}
182
183static void
184weston_desktop_xdg_surface_set_maximized(struct weston_desktop_surface *dsurface,
185 void *user_data, bool maximized)
186{
187 struct weston_desktop_xdg_surface *surface = user_data;
188
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200189 surface->pending.state.maximized = maximized;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200190 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200191}
192
193static void
194weston_desktop_xdg_surface_set_fullscreen(struct weston_desktop_surface *dsurface,
195 void *user_data, bool fullscreen)
196{
197 struct weston_desktop_xdg_surface *surface = user_data;
198
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200199 surface->pending.state.fullscreen = fullscreen;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200200 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200201}
202
203static void
204weston_desktop_xdg_surface_set_resizing(struct weston_desktop_surface *dsurface,
205 void *user_data, bool resizing)
206{
207 struct weston_desktop_xdg_surface *surface = user_data;
208
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200209 surface->pending.state.resizing = resizing;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200210 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200211}
212
213static void
214weston_desktop_xdg_surface_set_activated(struct weston_desktop_surface *dsurface,
215 void *user_data, bool activated)
216{
217 struct weston_desktop_xdg_surface *surface = user_data;
218
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200219 surface->pending.state.activated = activated;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200220 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200221}
222
223static void
224weston_desktop_xdg_surface_set_size(struct weston_desktop_surface *dsurface,
225 void *user_data,
226 int32_t width, int32_t height)
227{
228 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200229
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200230 surface->pending.size.width = width;
231 surface->pending.size.height = height;
Quentin Glidica56b0532016-09-13 10:05:58 +0200232
Quentin Glidicd51f8262017-04-13 20:25:27 +0200233 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200234}
235
236static void
237weston_desktop_xdg_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +0200238 void *user_data,
Quentin Glidic248dd102016-08-12 10:41:34 +0200239 int32_t sx, int32_t sy)
240{
241 struct weston_desktop_xdg_surface *surface = user_data;
242 struct weston_surface *wsurface =
243 weston_desktop_surface_get_surface(surface->surface);
244 bool reconfigure = false;
245
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200246 if (surface->next.state.maximized || surface->next.state.fullscreen)
247 reconfigure = surface->pending.size.width != wsurface->width ||
248 surface->pending.size.height != wsurface->height;
Quentin Glidic248dd102016-08-12 10:41:34 +0200249
250 if (reconfigure) {
Quentin Glidicd51f8262017-04-13 20:25:27 +0200251 weston_desktop_xdg_surface_schedule_configure(surface, true);
Quentin Glidic248dd102016-08-12 10:41:34 +0200252 } else {
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200253 surface->current.state = surface->next.state;
Quentin Glidic248dd102016-08-12 10:41:34 +0200254 if (surface->has_next_geometry) {
255 surface->has_next_geometry = false;
256 weston_desktop_surface_set_geometry(surface->surface,
257 surface->next_geometry);
258 }
259
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200260 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200261 weston_desktop_api_committed(surface->desktop, surface->surface,
262 sx, sy);
263 }
264}
265
266static void
267weston_desktop_xdg_surface_ping(struct weston_desktop_surface *dsurface,
268 uint32_t serial, void *user_data)
269{
270 struct weston_desktop_client *client =
271 weston_desktop_surface_get_client(dsurface);
272
273 xdg_shell_send_ping(weston_desktop_client_get_resource(client),
274 serial);
275}
276
277static void
278weston_desktop_xdg_surface_close(struct weston_desktop_surface *dsurface,
279 void *user_data)
280{
281 struct weston_desktop_xdg_surface *surface = user_data;
282
283 xdg_surface_send_close(surface->resource);
284}
285
286static bool
287weston_desktop_xdg_surface_get_maximized(struct weston_desktop_surface *dsurface,
288 void *user_data)
289{
290 struct weston_desktop_xdg_surface *surface = user_data;
291
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200292 return surface->current.state.maximized;
Quentin Glidic248dd102016-08-12 10:41:34 +0200293}
294
295static bool
296weston_desktop_xdg_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
297 void *user_data)
298{
299 struct weston_desktop_xdg_surface *surface = user_data;
300
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200301 return surface->current.state.fullscreen;
Quentin Glidic248dd102016-08-12 10:41:34 +0200302}
303
304static bool
305weston_desktop_xdg_surface_get_resizing(struct weston_desktop_surface *dsurface,
306 void *user_data)
307{
308 struct weston_desktop_xdg_surface *surface = user_data;
309
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200310 return surface->current.state.resizing;
Quentin Glidic248dd102016-08-12 10:41:34 +0200311}
312
313static bool
314weston_desktop_xdg_surface_get_activated(struct weston_desktop_surface *dsurface,
315 void *user_data)
316{
317 struct weston_desktop_xdg_surface *surface = user_data;
318
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200319 return surface->current.state.activated;
Quentin Glidic248dd102016-08-12 10:41:34 +0200320}
321
322static void
323weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
324 void *user_data)
325{
326 struct weston_desktop_xdg_surface *surface = user_data;
327
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200328 if (surface->added)
329 weston_desktop_api_surface_removed(surface->desktop,
330 surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200331
332 if (surface->add_idle != NULL)
333 wl_event_source_remove(surface->add_idle);
334
335 if (surface->configure_idle != NULL)
336 wl_event_source_remove(surface->configure_idle);
337
338 free(surface);
339}
340
341static void
342weston_desktop_xdg_surface_protocol_set_parent(struct wl_client *wl_client,
343 struct wl_resource *resource,
344 struct wl_resource *parent_resource)
345{
346 struct weston_desktop_surface *dsurface =
347 wl_resource_get_user_data(resource);
348 struct weston_desktop_xdg_surface *surface =
349 weston_desktop_surface_get_implementation_data(dsurface);
350 struct weston_desktop_surface *parent = NULL;
351
352 if (parent_resource != NULL)
353 parent = wl_resource_get_user_data(parent_resource);
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200354
355 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200356 weston_desktop_api_set_parent(surface->desktop, dsurface, parent);
357}
358
359static void
360weston_desktop_xdg_surface_protocol_set_title(struct wl_client *wl_client,
361 struct wl_resource *resource,
362 const char *title)
363{
364 struct weston_desktop_surface *surface =
365 wl_resource_get_user_data(resource);
366
367 weston_desktop_surface_set_title(surface, title);
368}
369
370static void
371weston_desktop_xdg_surface_protocol_set_app_id(struct wl_client *wl_client,
372 struct wl_resource *resource,
373 const char *app_id)
374{
375 struct weston_desktop_surface *surface =
376 wl_resource_get_user_data(resource);
377
378 weston_desktop_surface_set_app_id(surface, app_id);
379}
380
381static void
382weston_desktop_xdg_surface_protocol_show_window_menu(struct wl_client *wl_client,
383 struct wl_resource *resource,
384 struct wl_resource *seat_resource,
385 uint32_t serial,
386 int32_t x, int32_t y)
387{
388 struct weston_desktop_surface *dsurface =
389 wl_resource_get_user_data(resource);
390 struct weston_seat *seat =
391 wl_resource_get_user_data(seat_resource);
392 struct weston_desktop_xdg_surface *surface =
393 weston_desktop_surface_get_implementation_data(dsurface);
394
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200395 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200396 weston_desktop_api_show_window_menu(surface->desktop, dsurface, seat, x, y);
397}
398
399static void
400weston_desktop_xdg_surface_protocol_move(struct wl_client *wl_client,
401 struct wl_resource *resource,
402 struct wl_resource *seat_resource,
403 uint32_t serial)
404{
405 struct weston_desktop_surface *dsurface =
406 wl_resource_get_user_data(resource);
407 struct weston_seat *seat =
408 wl_resource_get_user_data(seat_resource);
409 struct weston_desktop_xdg_surface *surface =
410 weston_desktop_surface_get_implementation_data(dsurface);
411
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200412 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200413 weston_desktop_api_move(surface->desktop, dsurface, seat, serial);
414}
415
416static void
417weston_desktop_xdg_surface_protocol_resize(struct wl_client *wl_client,
418 struct wl_resource *resource,
419 struct wl_resource *seat_resource,
420 uint32_t serial,
421 enum xdg_surface_resize_edge edges)
422{
423 struct weston_desktop_surface *dsurface =
424 wl_resource_get_user_data(resource);
425 struct weston_seat *seat =
426 wl_resource_get_user_data(seat_resource);
427 struct weston_desktop_xdg_surface *surface =
428 weston_desktop_surface_get_implementation_data(dsurface);
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200429 enum weston_desktop_surface_edge surf_edges =
430 (enum weston_desktop_surface_edge) edges;
Quentin Glidic248dd102016-08-12 10:41:34 +0200431
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200432 weston_desktop_xdg_surface_ensure_added(surface);
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200433 weston_desktop_api_resize(surface->desktop, dsurface, seat, serial, surf_edges);
Quentin Glidic248dd102016-08-12 10:41:34 +0200434}
435
436static void
437weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
438 struct wl_resource *resource,
439 uint32_t serial)
440{
441 struct weston_desktop_surface *dsurface =
442 wl_resource_get_user_data(resource);
443 struct weston_desktop_xdg_surface *surface =
444 weston_desktop_surface_get_implementation_data(dsurface);
445
446 if (surface->configure_serial != serial)
447 return;
448
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200449 surface->next.state = surface->pending.state;
Quentin Glidic248dd102016-08-12 10:41:34 +0200450}
451
452static void
453weston_desktop_xdg_surface_protocol_set_window_geometry(struct wl_client *wl_client,
454 struct wl_resource *resource,
455 int32_t x, int32_t y,
456 int32_t width, int32_t height)
457{
458 struct weston_desktop_surface *dsurface =
459 wl_resource_get_user_data(resource);
460 struct weston_desktop_xdg_surface *surface =
461 weston_desktop_surface_get_implementation_data(dsurface);
462
463 surface->has_next_geometry = true;
464 surface->next_geometry.x = x;
465 surface->next_geometry.y = y;
466 surface->next_geometry.width = width;
467 surface->next_geometry.height = height;
468}
469
470static void
471weston_desktop_xdg_surface_protocol_set_maximized(struct wl_client *wl_client,
472 struct wl_resource *resource)
473{
474 struct weston_desktop_surface *dsurface =
475 wl_resource_get_user_data(resource);
476 struct weston_desktop_xdg_surface *surface =
477 weston_desktop_surface_get_implementation_data(dsurface);
478
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200479 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200480 weston_desktop_api_maximized_requested(surface->desktop, dsurface, true);
481}
482
483static void
484weston_desktop_xdg_surface_protocol_unset_maximized(struct wl_client *wl_client,
485 struct wl_resource *resource)
486{
487 struct weston_desktop_surface *dsurface =
488 wl_resource_get_user_data(resource);
489 struct weston_desktop_xdg_surface *surface =
490 weston_desktop_surface_get_implementation_data(dsurface);
491
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200492 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200493 weston_desktop_api_maximized_requested(surface->desktop, dsurface, false);
494}
495
496static void
497weston_desktop_xdg_surface_protocol_set_fullscreen(struct wl_client *wl_client,
498 struct wl_resource *resource,
499 struct wl_resource *output_resource)
500{
501 struct weston_desktop_surface *dsurface =
502 wl_resource_get_user_data(resource);
503 struct weston_desktop_xdg_surface *surface =
504 weston_desktop_surface_get_implementation_data(dsurface);
505 struct weston_output *output = NULL;
506
507 if (output_resource != NULL)
508 output = wl_resource_get_user_data(output_resource);
509
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200510 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200511 weston_desktop_api_fullscreen_requested(surface->desktop, dsurface,
512 true, output);
513}
514
515static void
516weston_desktop_xdg_surface_protocol_unset_fullscreen(struct wl_client *wl_client,
517 struct wl_resource *resource)
518{
519 struct weston_desktop_surface *dsurface =
520 wl_resource_get_user_data(resource);
521 struct weston_desktop_xdg_surface *surface =
522 weston_desktop_surface_get_implementation_data(dsurface);
523
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200524 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200525 weston_desktop_api_fullscreen_requested(surface->desktop, dsurface,
526 false, NULL);
527}
528
529static void
530weston_desktop_xdg_surface_protocol_set_minimized(struct wl_client *wl_client,
531 struct wl_resource *resource)
532{
533 struct weston_desktop_surface *dsurface =
534 wl_resource_get_user_data(resource);
535 struct weston_desktop_xdg_surface *surface =
536 weston_desktop_surface_get_implementation_data(dsurface);
537
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200538 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200539 weston_desktop_api_minimized_requested(surface->desktop, dsurface);
540}
541
542static const struct xdg_surface_interface weston_desktop_xdg_surface_implementation = {
543 .destroy = weston_desktop_destroy_request,
544 .set_parent = weston_desktop_xdg_surface_protocol_set_parent,
545 .set_title = weston_desktop_xdg_surface_protocol_set_title,
546 .set_app_id = weston_desktop_xdg_surface_protocol_set_app_id,
547 .show_window_menu = weston_desktop_xdg_surface_protocol_show_window_menu,
548 .move = weston_desktop_xdg_surface_protocol_move,
549 .resize = weston_desktop_xdg_surface_protocol_resize,
550 .ack_configure = weston_desktop_xdg_surface_protocol_ack_configure,
551 .set_window_geometry = weston_desktop_xdg_surface_protocol_set_window_geometry,
552 .set_maximized = weston_desktop_xdg_surface_protocol_set_maximized,
553 .unset_maximized = weston_desktop_xdg_surface_protocol_unset_maximized,
554 .set_fullscreen = weston_desktop_xdg_surface_protocol_set_fullscreen,
555 .unset_fullscreen = weston_desktop_xdg_surface_protocol_unset_fullscreen,
556 .set_minimized = weston_desktop_xdg_surface_protocol_set_minimized,
557};
558
559static const struct weston_desktop_surface_implementation weston_desktop_xdg_surface_internal_implementation = {
560 .set_maximized = weston_desktop_xdg_surface_set_maximized,
561 .set_fullscreen = weston_desktop_xdg_surface_set_fullscreen,
562 .set_resizing = weston_desktop_xdg_surface_set_resizing,
563 .set_activated = weston_desktop_xdg_surface_set_activated,
564 .set_size = weston_desktop_xdg_surface_set_size,
565 .committed = weston_desktop_xdg_surface_committed,
566 .ping = weston_desktop_xdg_surface_ping,
567 .close = weston_desktop_xdg_surface_close,
568
569 .get_maximized = weston_desktop_xdg_surface_get_maximized,
570 .get_fullscreen = weston_desktop_xdg_surface_get_fullscreen,
571 .get_resizing = weston_desktop_xdg_surface_get_resizing,
572 .get_activated = weston_desktop_xdg_surface_get_activated,
573
574 .destroy = weston_desktop_xdg_surface_destroy,
575};
576
577static void
578weston_desktop_xdg_popup_close(struct weston_desktop_surface *dsurface,
579 void *user_data)
580{
581 struct weston_desktop_xdg_popup *popup = user_data;
582
583 xdg_popup_send_popup_done(popup->resource);
584}
585
586static void
587weston_desktop_xdg_popup_destroy(struct weston_desktop_surface *dsurface,
588 void *user_data)
589{
590 struct weston_desktop_xdg_popup *popup = user_data;
591 struct weston_desktop_surface *topmost;
592 struct weston_desktop_client *client =
593 weston_desktop_surface_get_client(popup->popup);
594
595 if (!weston_desktop_surface_get_grab(popup->popup))
596 goto end;
597
598 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(popup->seat);
599 if (topmost != popup->popup) {
600 struct wl_resource *client_resource =
601 weston_desktop_client_get_resource(client);
602
603 wl_resource_post_error(client_resource,
604 XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
605 "xdg_popup was destroyed while it was not the topmost popup.");
606 }
607
608 weston_desktop_surface_popup_ungrab(popup->popup, popup->seat);
609
610end:
611 free(popup);
612}
613
614static const struct xdg_popup_interface weston_desktop_xdg_popup_implementation = {
615 .destroy = weston_desktop_destroy_request,
616};
617
618static const struct weston_desktop_surface_implementation weston_desktop_xdg_popup_internal_implementation = {
619 .close = weston_desktop_xdg_popup_close,
620
621 .destroy = weston_desktop_xdg_popup_destroy,
622};
623
624static void
625weston_desktop_xdg_shell_protocol_use_unstable_version(struct wl_client *wl_client,
626 struct wl_resource *resource,
627 int32_t version)
628{
629 if (version > 1) {
630 wl_resource_post_error(resource,
631 1, "xdg_shell version not supported");
632 return;
633 }
634}
635
636static void
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200637weston_desktop_xdg_surface_add_idle_callback(void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200638{
639 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200640
Quentin Glidic248dd102016-08-12 10:41:34 +0200641 surface->add_idle = NULL;
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200642 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200643}
644
645static void
646weston_desktop_xdg_shell_protocol_get_xdg_surface(struct wl_client *wl_client,
647 struct wl_resource *resource,
648 uint32_t id,
649 struct wl_resource *surface_resource)
650{
651 struct weston_desktop_client *client =
652 wl_resource_get_user_data(resource);
653 struct weston_desktop *desktop =
654 weston_desktop_client_get_desktop(client);
655 struct weston_surface *wsurface =
656 wl_resource_get_user_data(surface_resource);
657 struct weston_desktop_xdg_surface *surface;
658 struct wl_display *display = weston_desktop_get_display(desktop);
659 struct wl_event_loop *loop = wl_display_get_event_loop(display);
660
661 if (weston_surface_set_role(wsurface, "xdg_surface", resource, XDG_SHELL_ERROR_ROLE) < 0)
662 return;
663
664 surface = zalloc(sizeof(struct weston_desktop_xdg_surface));
665 if (surface == NULL) {
666 wl_client_post_no_memory(wl_client);
667 return;
668 }
669
670 surface->desktop = desktop;
671
672 surface->surface =
673 weston_desktop_surface_create(surface->desktop, client,
674 wsurface,
675 &weston_desktop_xdg_surface_internal_implementation,
676 surface);
677 if (surface->surface == NULL) {
678 free(surface);
679 return;
680 }
681
682 surface->resource =
683 weston_desktop_surface_add_resource(surface->surface,
684 &xdg_surface_interface,
685 &weston_desktop_xdg_surface_implementation,
686 id, NULL);
687 if (surface->resource == NULL)
688 return;
689
690 surface->add_idle =
691 wl_event_loop_add_idle(loop,
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200692 weston_desktop_xdg_surface_add_idle_callback,
Quentin Glidic248dd102016-08-12 10:41:34 +0200693 surface);
694}
695
696static void
697weston_desktop_xdg_shell_protocol_get_xdg_popup(struct wl_client *wl_client,
698 struct wl_resource *resource,
699 uint32_t id,
700 struct wl_resource *surface_resource,
701 struct wl_resource *parent_resource,
702 struct wl_resource *seat_resource,
703 uint32_t serial,
704 int32_t x, int32_t y)
705{
706 struct weston_desktop_client *client =
707 wl_resource_get_user_data(resource);
708 struct weston_surface *wsurface =
709 wl_resource_get_user_data(surface_resource);
710 struct weston_surface *wparent =
711 wl_resource_get_user_data(parent_resource);
712 struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
713 struct weston_desktop_seat *seat = weston_desktop_seat_from_seat(wseat);
714 struct weston_desktop_surface *parent, *topmost;
715 bool parent_is_popup, parent_is_xdg;
716 struct weston_desktop_xdg_popup *popup;
717
718 if (weston_surface_set_role(wsurface, "xdg_popup", resource, XDG_SHELL_ERROR_ROLE) < 0)
719 return;
720
721 if (!weston_surface_is_desktop_surface(wparent)) {
722 wl_resource_post_error(resource,
723 XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
724 "xdg_popup parent was invalid");
725 return;
726 }
727
728 parent = weston_surface_get_desktop_surface(wparent);
729 parent_is_xdg =
730 weston_desktop_surface_has_implementation(parent,
731 &weston_desktop_xdg_surface_internal_implementation);
732 parent_is_popup =
733 weston_desktop_surface_has_implementation(parent,
734 &weston_desktop_xdg_popup_internal_implementation);
735
736 if (!parent_is_xdg && !parent_is_popup) {
737 wl_resource_post_error(resource,
738 XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
739 "xdg_popup parent was invalid");
740 return;
741 }
742
743 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(seat);
744 if ((topmost == NULL && parent_is_popup) ||
745 (topmost != NULL && topmost != parent)) {
746 wl_resource_post_error(resource,
747 XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
748 "xdg_popup was not created on the topmost popup");
749 return;
750 }
751
752 popup = zalloc(sizeof(struct weston_desktop_xdg_popup));
753 if (popup == NULL) {
754 wl_client_post_no_memory(wl_client);
755 return;
756 }
757
758 popup->desktop = weston_desktop_client_get_desktop(client);
759 popup->display = weston_desktop_get_display(popup->desktop);
760 popup->seat = seat;
761
762 popup->popup =
763 weston_desktop_surface_create(popup->desktop, client, wsurface,
764 &weston_desktop_xdg_popup_internal_implementation,
765 popup);
766 if (popup->popup == NULL) {
767 free(popup);
768 return;
769 }
770
771 popup->resource =
772 weston_desktop_surface_add_resource(popup->popup,
773 &xdg_popup_interface,
774 &weston_desktop_xdg_popup_implementation,
775 id, NULL);
776 if (popup->resource == NULL)
777 return;
778
779 weston_desktop_surface_set_relative_to(popup->popup, parent, x, y, false);
780 weston_desktop_surface_popup_grab(popup->popup, popup->seat, serial);
781}
782
783static void
784weston_desktop_xdg_shell_protocol_pong(struct wl_client *wl_client,
785 struct wl_resource *resource,
786 uint32_t serial)
787{
788 struct weston_desktop_client *client =
789 wl_resource_get_user_data(resource);
790
791 weston_desktop_client_pong(client, serial);
792}
793
794static const struct xdg_shell_interface weston_desktop_xdg_shell_implementation = {
795 .destroy = weston_desktop_destroy_request,
796 .use_unstable_version = weston_desktop_xdg_shell_protocol_use_unstable_version,
797 .get_xdg_surface = weston_desktop_xdg_shell_protocol_get_xdg_surface,
798 .get_xdg_popup = weston_desktop_xdg_shell_protocol_get_xdg_popup,
799 .pong = weston_desktop_xdg_shell_protocol_pong,
800};
801
802static int
803xdg_shell_unversioned_dispatch(const void *implementation,
804 void *_target, uint32_t opcode,
805 const struct wl_message *message,
806 union wl_argument *args)
807{
808 struct wl_resource *resource = _target;
809 struct weston_desktop_client *client =
810 wl_resource_get_user_data(resource);
811
812 if (opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */) {
813 wl_resource_post_error(resource,
814 WL_DISPLAY_ERROR_INVALID_OBJECT,
815 "must call use_unstable_version first");
816 return 0;
817 }
818
819#define XDG_SERVER_VERSION 5
820
821 if (args[0].i != XDG_SERVER_VERSION) {
822 wl_resource_post_error(resource,
823 WL_DISPLAY_ERROR_INVALID_OBJECT,
824 "incompatible version, server is %d " "client wants %d",
825 XDG_SERVER_VERSION, args[0].i);
826 return 0;
827 }
828
829 wl_resource_set_implementation(resource,
830 &weston_desktop_xdg_shell_implementation,
831 client, implementation);
832
833 return 1;
834}
835
836static void
837weston_desktop_xdg_shell_bind(struct wl_client *client, void *data,
838 uint32_t version, uint32_t id)
839{
840 struct weston_desktop *desktop = data;
841
842 weston_desktop_client_create(desktop, client,
843 xdg_shell_unversioned_dispatch,
844 &xdg_shell_interface, NULL, version, id);
845}
846
847struct wl_global *
848weston_desktop_xdg_shell_v5_create(struct weston_desktop *desktop,
849 struct wl_display *display)
850{
851 return wl_global_create(display,
852 &xdg_shell_interface,
853 WD_XDG_SHELL_PROTOCOL_VERSION,
854 desktop, weston_desktop_xdg_shell_bind);
855}