blob: dd3608629f2e73124712c7b50a11ffa7dff11ff2 [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 Glidic749637a2017-07-18 12:59:14 +020049struct weston_desktop_xdg_surface_configure {
50 struct wl_list link; /* weston_desktop_xdg_surface::configure_list */
51 uint32_t serial;
52 struct weston_desktop_xdg_surface_state state;
53 struct weston_size size;
54};
55
Quentin Glidic248dd102016-08-12 10:41:34 +020056struct weston_desktop_xdg_surface {
57 struct wl_resource *resource;
58 struct weston_desktop_surface *surface;
59 struct weston_desktop *desktop;
Quentin Glidic6967f0e2016-08-18 15:51:38 +020060 bool added;
Quentin Glidic248dd102016-08-12 10:41:34 +020061 struct wl_event_source *add_idle;
62 struct wl_event_source *configure_idle;
Quentin Glidic749637a2017-07-18 12:59:14 +020063 struct wl_list configure_list; /* weston_desktop_xdg_surface_configure::link */
Quentin Glidic248dd102016-08-12 10:41:34 +020064 struct {
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020065 struct weston_desktop_xdg_surface_state state;
66 struct weston_size size;
67 } pending;
68 struct {
69 struct weston_desktop_xdg_surface_state state;
Quentin Glidicac394a12017-07-12 09:45:43 +020070 struct weston_size size;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020071 } next;
72 struct {
73 struct weston_desktop_xdg_surface_state state;
74 } current;
Quentin Glidic248dd102016-08-12 10:41:34 +020075 bool has_next_geometry;
76 struct weston_geometry next_geometry;
77};
78
79struct weston_desktop_xdg_popup {
80 struct wl_resource *resource;
81 struct weston_desktop_surface *popup;
82 struct weston_desktop *desktop;
83 struct weston_desktop_seat *seat;
84 struct wl_display *display;
85};
86
87static void
Quentin Glidic6967f0e2016-08-18 15:51:38 +020088weston_desktop_xdg_surface_ensure_added(struct weston_desktop_xdg_surface *surface)
89{
90 if (surface->added)
91 return;
92
93 if (surface->add_idle != NULL)
94 wl_event_source_remove(surface->add_idle);
95 surface->add_idle = NULL;
96 weston_desktop_api_surface_added(surface->desktop, surface->surface);
97 surface->added = true;
98}
99
100static void
Quentin Glidic248dd102016-08-12 10:41:34 +0200101weston_desktop_xdg_surface_send_configure(void *data)
102{
103 struct weston_desktop_xdg_surface *surface = data;
Quentin Glidic749637a2017-07-18 12:59:14 +0200104 struct weston_desktop_xdg_surface_configure *configure;
Quentin Glidic248dd102016-08-12 10:41:34 +0200105 uint32_t *s;
106 struct wl_array states;
107
108 surface->configure_idle = NULL;
109
Quentin Glidic749637a2017-07-18 12:59:14 +0200110 configure = zalloc(sizeof(struct weston_desktop_xdg_surface_configure));
111 if (configure == NULL) {
112 struct weston_desktop_client *client =
113 weston_desktop_surface_get_client(surface->surface);
114 struct wl_client *wl_client =
115 weston_desktop_client_get_client(client);
116 wl_client_post_no_memory(wl_client);
117 return;
118 }
119 wl_list_insert(surface->configure_list.prev, &configure->link);
120 configure->serial =
Quentin Glidic248dd102016-08-12 10:41:34 +0200121 wl_display_next_serial(weston_desktop_get_display(surface->desktop));
Quentin Glidic749637a2017-07-18 12:59:14 +0200122 configure->state = surface->pending.state;
123 configure->size = surface->pending.size;
Quentin Glidic248dd102016-08-12 10:41:34 +0200124
125 wl_array_init(&states);
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200126 if (surface->pending.state.maximized) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200127 s = wl_array_add(&states, sizeof(uint32_t));
128 *s = XDG_SURFACE_STATE_MAXIMIZED;
129 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200130 if (surface->pending.state.fullscreen) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200131 s = wl_array_add(&states, sizeof(uint32_t));
132 *s = XDG_SURFACE_STATE_FULLSCREEN;
133 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200134 if (surface->pending.state.resizing) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200135 s = wl_array_add(&states, sizeof(uint32_t));
136 *s = XDG_SURFACE_STATE_RESIZING;
137 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200138 if (surface->pending.state.activated) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200139 s = wl_array_add(&states, sizeof(uint32_t));
140 *s = XDG_SURFACE_STATE_ACTIVATED;
141 }
142
143 xdg_surface_send_configure(surface->resource,
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200144 surface->pending.size.width,
145 surface->pending.size.height,
Quentin Glidic248dd102016-08-12 10:41:34 +0200146 &states,
Quentin Glidic749637a2017-07-18 12:59:14 +0200147 configure->serial);
Quentin Glidic248dd102016-08-12 10:41:34 +0200148
149 wl_array_release(&states);
150};
151
Quentin Glidicd51f8262017-04-13 20:25:27 +0200152static bool
153weston_desktop_xdg_surface_state_compare(struct weston_desktop_xdg_surface *surface)
154{
155 struct weston_surface *wsurface =
156 weston_desktop_surface_get_surface(surface->surface);
157
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200158 if (surface->pending.state.activated != surface->current.state.activated)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200159 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200160 if (surface->pending.state.fullscreen != surface->current.state.fullscreen)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200161 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200162 if (surface->pending.state.maximized != surface->current.state.maximized)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200163 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200164 if (surface->pending.state.resizing != surface->current.state.resizing)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200165 return false;
166
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200167 if (wsurface->width == surface->pending.size.width &&
168 wsurface->height == surface->pending.size.height)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200169 return true;
170
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200171 if (surface->pending.size.width == 0 &&
172 surface->pending.size.height == 0)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200173 return true;
174
175 return false;
176}
177
Quentin Glidic248dd102016-08-12 10:41:34 +0200178static void
Quentin Glidicd51f8262017-04-13 20:25:27 +0200179weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
180 bool force)
Quentin Glidic248dd102016-08-12 10:41:34 +0200181{
182 struct wl_display *display = weston_desktop_get_display(surface->desktop);
183 struct wl_event_loop *loop = wl_display_get_event_loop(display);
Quentin Glidic218126d2017-07-11 13:31:36 +0200184 bool pending_same =
Quentin Glidicd51f8262017-04-13 20:25:27 +0200185 !force && weston_desktop_xdg_surface_state_compare(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200186
Quentin Glidicd51f8262017-04-13 20:25:27 +0200187 if (surface->configure_idle != NULL) {
Quentin Glidic218126d2017-07-11 13:31:36 +0200188 if (!pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200189 return;
190
191 wl_event_source_remove(surface->configure_idle);
192 surface->configure_idle = NULL;
193 } else {
Quentin Glidic218126d2017-07-11 13:31:36 +0200194 if (pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200195 return;
196
197 surface->configure_idle =
198 wl_event_loop_add_idle(loop,
199 weston_desktop_xdg_surface_send_configure,
200 surface);
201 }
Quentin Glidic248dd102016-08-12 10:41:34 +0200202}
203
204static void
205weston_desktop_xdg_surface_set_maximized(struct weston_desktop_surface *dsurface,
206 void *user_data, bool maximized)
207{
208 struct weston_desktop_xdg_surface *surface = user_data;
209
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200210 surface->pending.state.maximized = maximized;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200211 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200212}
213
214static void
215weston_desktop_xdg_surface_set_fullscreen(struct weston_desktop_surface *dsurface,
216 void *user_data, bool fullscreen)
217{
218 struct weston_desktop_xdg_surface *surface = user_data;
219
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200220 surface->pending.state.fullscreen = fullscreen;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200221 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200222}
223
224static void
225weston_desktop_xdg_surface_set_resizing(struct weston_desktop_surface *dsurface,
226 void *user_data, bool resizing)
227{
228 struct weston_desktop_xdg_surface *surface = user_data;
229
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200230 surface->pending.state.resizing = resizing;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200231 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200232}
233
234static void
235weston_desktop_xdg_surface_set_activated(struct weston_desktop_surface *dsurface,
236 void *user_data, bool activated)
237{
238 struct weston_desktop_xdg_surface *surface = user_data;
239
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200240 surface->pending.state.activated = activated;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200241 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200242}
243
244static void
245weston_desktop_xdg_surface_set_size(struct weston_desktop_surface *dsurface,
246 void *user_data,
247 int32_t width, int32_t height)
248{
249 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidic248dd102016-08-12 10:41:34 +0200250
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200251 surface->pending.size.width = width;
252 surface->pending.size.height = height;
Quentin Glidica56b0532016-09-13 10:05:58 +0200253
Quentin Glidicd51f8262017-04-13 20:25:27 +0200254 weston_desktop_xdg_surface_schedule_configure(surface, false);
Quentin Glidic248dd102016-08-12 10:41:34 +0200255}
256
257static void
258weston_desktop_xdg_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +0200259 void *user_data,
Quentin Glidic248dd102016-08-12 10:41:34 +0200260 int32_t sx, int32_t sy)
261{
262 struct weston_desktop_xdg_surface *surface = user_data;
263 struct weston_surface *wsurface =
264 weston_desktop_surface_get_surface(surface->surface);
265 bool reconfigure = false;
266
Philipp Kerlingc6239022017-07-26 14:02:21 +0200267 /* TODO: use the window geometry and not the surface size here
268 * We need to check the next geometry if there is one, but not accept it
269 * until we checked it, maybe.
270 */
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200271 if (surface->next.state.maximized || surface->next.state.fullscreen)
Quentin Glidicac394a12017-07-12 09:45:43 +0200272 reconfigure = surface->next.size.width != wsurface->width ||
273 surface->next.size.height != wsurface->height;
Quentin Glidic248dd102016-08-12 10:41:34 +0200274
275 if (reconfigure) {
Quentin Glidicd51f8262017-04-13 20:25:27 +0200276 weston_desktop_xdg_surface_schedule_configure(surface, true);
Quentin Glidic248dd102016-08-12 10:41:34 +0200277 } else {
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200278 surface->current.state = surface->next.state;
Quentin Glidic248dd102016-08-12 10:41:34 +0200279 if (surface->has_next_geometry) {
280 surface->has_next_geometry = false;
281 weston_desktop_surface_set_geometry(surface->surface,
282 surface->next_geometry);
283 }
284
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200285 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200286 weston_desktop_api_committed(surface->desktop, surface->surface,
287 sx, sy);
288 }
289}
290
291static void
292weston_desktop_xdg_surface_ping(struct weston_desktop_surface *dsurface,
293 uint32_t serial, void *user_data)
294{
295 struct weston_desktop_client *client =
296 weston_desktop_surface_get_client(dsurface);
297
298 xdg_shell_send_ping(weston_desktop_client_get_resource(client),
299 serial);
300}
301
302static void
303weston_desktop_xdg_surface_close(struct weston_desktop_surface *dsurface,
304 void *user_data)
305{
306 struct weston_desktop_xdg_surface *surface = user_data;
307
308 xdg_surface_send_close(surface->resource);
309}
310
311static bool
312weston_desktop_xdg_surface_get_maximized(struct weston_desktop_surface *dsurface,
313 void *user_data)
314{
315 struct weston_desktop_xdg_surface *surface = user_data;
316
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200317 return surface->current.state.maximized;
Quentin Glidic248dd102016-08-12 10:41:34 +0200318}
319
320static bool
321weston_desktop_xdg_surface_get_fullscreen(struct weston_desktop_surface *dsurface,
322 void *user_data)
323{
324 struct weston_desktop_xdg_surface *surface = user_data;
325
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200326 return surface->current.state.fullscreen;
Quentin Glidic248dd102016-08-12 10:41:34 +0200327}
328
329static bool
330weston_desktop_xdg_surface_get_resizing(struct weston_desktop_surface *dsurface,
331 void *user_data)
332{
333 struct weston_desktop_xdg_surface *surface = user_data;
334
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200335 return surface->current.state.resizing;
Quentin Glidic248dd102016-08-12 10:41:34 +0200336}
337
338static bool
339weston_desktop_xdg_surface_get_activated(struct weston_desktop_surface *dsurface,
340 void *user_data)
341{
342 struct weston_desktop_xdg_surface *surface = user_data;
343
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200344 return surface->current.state.activated;
Quentin Glidic248dd102016-08-12 10:41:34 +0200345}
346
347static void
348weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
349 void *user_data)
350{
351 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidic749637a2017-07-18 12:59:14 +0200352 struct weston_desktop_xdg_surface_configure *configure, *temp;
Quentin Glidic248dd102016-08-12 10:41:34 +0200353
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200354 if (surface->added)
355 weston_desktop_api_surface_removed(surface->desktop,
356 surface->surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200357
358 if (surface->add_idle != NULL)
359 wl_event_source_remove(surface->add_idle);
360
361 if (surface->configure_idle != NULL)
362 wl_event_source_remove(surface->configure_idle);
363
Quentin Glidic749637a2017-07-18 12:59:14 +0200364 wl_list_for_each_safe(configure, temp, &surface->configure_list, link)
365 free(configure);
366
Quentin Glidic248dd102016-08-12 10:41:34 +0200367 free(surface);
368}
369
370static void
371weston_desktop_xdg_surface_protocol_set_parent(struct wl_client *wl_client,
372 struct wl_resource *resource,
373 struct wl_resource *parent_resource)
374{
375 struct weston_desktop_surface *dsurface =
376 wl_resource_get_user_data(resource);
377 struct weston_desktop_xdg_surface *surface =
378 weston_desktop_surface_get_implementation_data(dsurface);
379 struct weston_desktop_surface *parent = NULL;
380
381 if (parent_resource != NULL)
382 parent = wl_resource_get_user_data(parent_resource);
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200383
384 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200385 weston_desktop_api_set_parent(surface->desktop, dsurface, parent);
386}
387
388static void
389weston_desktop_xdg_surface_protocol_set_title(struct wl_client *wl_client,
390 struct wl_resource *resource,
391 const char *title)
392{
393 struct weston_desktop_surface *surface =
394 wl_resource_get_user_data(resource);
395
396 weston_desktop_surface_set_title(surface, title);
397}
398
399static void
400weston_desktop_xdg_surface_protocol_set_app_id(struct wl_client *wl_client,
401 struct wl_resource *resource,
402 const char *app_id)
403{
404 struct weston_desktop_surface *surface =
405 wl_resource_get_user_data(resource);
406
407 weston_desktop_surface_set_app_id(surface, app_id);
408}
409
410static void
411weston_desktop_xdg_surface_protocol_show_window_menu(struct wl_client *wl_client,
412 struct wl_resource *resource,
413 struct wl_resource *seat_resource,
414 uint32_t serial,
415 int32_t x, int32_t y)
416{
417 struct weston_desktop_surface *dsurface =
418 wl_resource_get_user_data(resource);
419 struct weston_seat *seat =
420 wl_resource_get_user_data(seat_resource);
421 struct weston_desktop_xdg_surface *surface =
422 weston_desktop_surface_get_implementation_data(dsurface);
423
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200424 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200425 weston_desktop_api_show_window_menu(surface->desktop, dsurface, seat, x, y);
426}
427
428static void
429weston_desktop_xdg_surface_protocol_move(struct wl_client *wl_client,
430 struct wl_resource *resource,
431 struct wl_resource *seat_resource,
432 uint32_t serial)
433{
434 struct weston_desktop_surface *dsurface =
435 wl_resource_get_user_data(resource);
436 struct weston_seat *seat =
437 wl_resource_get_user_data(seat_resource);
438 struct weston_desktop_xdg_surface *surface =
439 weston_desktop_surface_get_implementation_data(dsurface);
440
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200441 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200442 weston_desktop_api_move(surface->desktop, dsurface, seat, serial);
443}
444
445static void
446weston_desktop_xdg_surface_protocol_resize(struct wl_client *wl_client,
447 struct wl_resource *resource,
448 struct wl_resource *seat_resource,
449 uint32_t serial,
450 enum xdg_surface_resize_edge edges)
451{
452 struct weston_desktop_surface *dsurface =
453 wl_resource_get_user_data(resource);
454 struct weston_seat *seat =
455 wl_resource_get_user_data(seat_resource);
456 struct weston_desktop_xdg_surface *surface =
457 weston_desktop_surface_get_implementation_data(dsurface);
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200458 enum weston_desktop_surface_edge surf_edges =
459 (enum weston_desktop_surface_edge) edges;
Quentin Glidic248dd102016-08-12 10:41:34 +0200460
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200461 weston_desktop_xdg_surface_ensure_added(surface);
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200462 weston_desktop_api_resize(surface->desktop, dsurface, seat, serial, surf_edges);
Quentin Glidic248dd102016-08-12 10:41:34 +0200463}
464
465static void
466weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
467 struct wl_resource *resource,
468 uint32_t serial)
469{
470 struct weston_desktop_surface *dsurface =
471 wl_resource_get_user_data(resource);
472 struct weston_desktop_xdg_surface *surface =
473 weston_desktop_surface_get_implementation_data(dsurface);
Quentin Glidic749637a2017-07-18 12:59:14 +0200474 struct weston_desktop_xdg_surface_configure *configure, *temp;
475 bool found = false;
Quentin Glidic248dd102016-08-12 10:41:34 +0200476
Quentin Glidic749637a2017-07-18 12:59:14 +0200477 wl_list_for_each_safe(configure, temp, &surface->configure_list, link) {
478 if (configure->serial < serial) {
479 wl_list_remove(&configure->link);
480 free(configure);
481 } else if (configure->serial == serial) {
482 wl_list_remove(&configure->link);
483 found = true;
Derek Foremane3715522017-07-26 14:35:58 -0500484 break;
485 } else {
486 break;
Quentin Glidic749637a2017-07-18 12:59:14 +0200487 }
Quentin Glidic749637a2017-07-18 12:59:14 +0200488 }
489 if (!found) {
490 struct weston_desktop_client *client =
491 weston_desktop_surface_get_client(dsurface);
492 struct wl_resource *client_resource =
493 weston_desktop_client_get_resource(client);
494 wl_resource_post_error(client_resource,
495 XDG_SHELL_ERROR_DEFUNCT_SURFACES,
496 "Wrong configure serial: %u", serial);
Quentin Glidic248dd102016-08-12 10:41:34 +0200497 return;
Quentin Glidic749637a2017-07-18 12:59:14 +0200498 }
Quentin Glidic248dd102016-08-12 10:41:34 +0200499
Quentin Glidic749637a2017-07-18 12:59:14 +0200500 surface->next.state = configure->state;
501 surface->next.size = configure->size;
502
503 free(configure);
Quentin Glidic248dd102016-08-12 10:41:34 +0200504}
505
506static void
507weston_desktop_xdg_surface_protocol_set_window_geometry(struct wl_client *wl_client,
508 struct wl_resource *resource,
509 int32_t x, int32_t y,
510 int32_t width, int32_t height)
511{
512 struct weston_desktop_surface *dsurface =
513 wl_resource_get_user_data(resource);
514 struct weston_desktop_xdg_surface *surface =
515 weston_desktop_surface_get_implementation_data(dsurface);
516
517 surface->has_next_geometry = true;
518 surface->next_geometry.x = x;
519 surface->next_geometry.y = y;
520 surface->next_geometry.width = width;
521 surface->next_geometry.height = height;
522}
523
524static void
525weston_desktop_xdg_surface_protocol_set_maximized(struct wl_client *wl_client,
526 struct wl_resource *resource)
527{
528 struct weston_desktop_surface *dsurface =
529 wl_resource_get_user_data(resource);
530 struct weston_desktop_xdg_surface *surface =
531 weston_desktop_surface_get_implementation_data(dsurface);
532
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200533 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200534 weston_desktop_api_maximized_requested(surface->desktop, dsurface, true);
535}
536
537static void
538weston_desktop_xdg_surface_protocol_unset_maximized(struct wl_client *wl_client,
539 struct wl_resource *resource)
540{
541 struct weston_desktop_surface *dsurface =
542 wl_resource_get_user_data(resource);
543 struct weston_desktop_xdg_surface *surface =
544 weston_desktop_surface_get_implementation_data(dsurface);
545
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200546 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200547 weston_desktop_api_maximized_requested(surface->desktop, dsurface, false);
548}
549
550static void
551weston_desktop_xdg_surface_protocol_set_fullscreen(struct wl_client *wl_client,
552 struct wl_resource *resource,
553 struct wl_resource *output_resource)
554{
555 struct weston_desktop_surface *dsurface =
556 wl_resource_get_user_data(resource);
557 struct weston_desktop_xdg_surface *surface =
558 weston_desktop_surface_get_implementation_data(dsurface);
559 struct weston_output *output = NULL;
560
561 if (output_resource != NULL)
Pekka Paalanen9ffb2502017-03-27 15:14:32 +0300562 output = weston_output_from_resource(output_resource);
Quentin Glidic248dd102016-08-12 10:41:34 +0200563
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200564 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200565 weston_desktop_api_fullscreen_requested(surface->desktop, dsurface,
566 true, output);
567}
568
569static void
570weston_desktop_xdg_surface_protocol_unset_fullscreen(struct wl_client *wl_client,
571 struct wl_resource *resource)
572{
573 struct weston_desktop_surface *dsurface =
574 wl_resource_get_user_data(resource);
575 struct weston_desktop_xdg_surface *surface =
576 weston_desktop_surface_get_implementation_data(dsurface);
577
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200578 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200579 weston_desktop_api_fullscreen_requested(surface->desktop, dsurface,
580 false, NULL);
581}
582
583static void
584weston_desktop_xdg_surface_protocol_set_minimized(struct wl_client *wl_client,
585 struct wl_resource *resource)
586{
587 struct weston_desktop_surface *dsurface =
588 wl_resource_get_user_data(resource);
589 struct weston_desktop_xdg_surface *surface =
590 weston_desktop_surface_get_implementation_data(dsurface);
591
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200592 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200593 weston_desktop_api_minimized_requested(surface->desktop, dsurface);
594}
595
596static const struct xdg_surface_interface weston_desktop_xdg_surface_implementation = {
597 .destroy = weston_desktop_destroy_request,
598 .set_parent = weston_desktop_xdg_surface_protocol_set_parent,
599 .set_title = weston_desktop_xdg_surface_protocol_set_title,
600 .set_app_id = weston_desktop_xdg_surface_protocol_set_app_id,
601 .show_window_menu = weston_desktop_xdg_surface_protocol_show_window_menu,
602 .move = weston_desktop_xdg_surface_protocol_move,
603 .resize = weston_desktop_xdg_surface_protocol_resize,
604 .ack_configure = weston_desktop_xdg_surface_protocol_ack_configure,
605 .set_window_geometry = weston_desktop_xdg_surface_protocol_set_window_geometry,
606 .set_maximized = weston_desktop_xdg_surface_protocol_set_maximized,
607 .unset_maximized = weston_desktop_xdg_surface_protocol_unset_maximized,
608 .set_fullscreen = weston_desktop_xdg_surface_protocol_set_fullscreen,
609 .unset_fullscreen = weston_desktop_xdg_surface_protocol_unset_fullscreen,
610 .set_minimized = weston_desktop_xdg_surface_protocol_set_minimized,
611};
612
613static const struct weston_desktop_surface_implementation weston_desktop_xdg_surface_internal_implementation = {
614 .set_maximized = weston_desktop_xdg_surface_set_maximized,
615 .set_fullscreen = weston_desktop_xdg_surface_set_fullscreen,
616 .set_resizing = weston_desktop_xdg_surface_set_resizing,
617 .set_activated = weston_desktop_xdg_surface_set_activated,
618 .set_size = weston_desktop_xdg_surface_set_size,
619 .committed = weston_desktop_xdg_surface_committed,
620 .ping = weston_desktop_xdg_surface_ping,
621 .close = weston_desktop_xdg_surface_close,
622
623 .get_maximized = weston_desktop_xdg_surface_get_maximized,
624 .get_fullscreen = weston_desktop_xdg_surface_get_fullscreen,
625 .get_resizing = weston_desktop_xdg_surface_get_resizing,
626 .get_activated = weston_desktop_xdg_surface_get_activated,
627
628 .destroy = weston_desktop_xdg_surface_destroy,
629};
630
631static void
632weston_desktop_xdg_popup_close(struct weston_desktop_surface *dsurface,
633 void *user_data)
634{
635 struct weston_desktop_xdg_popup *popup = user_data;
636
637 xdg_popup_send_popup_done(popup->resource);
638}
639
640static void
641weston_desktop_xdg_popup_destroy(struct weston_desktop_surface *dsurface,
642 void *user_data)
643{
644 struct weston_desktop_xdg_popup *popup = user_data;
645 struct weston_desktop_surface *topmost;
646 struct weston_desktop_client *client =
647 weston_desktop_surface_get_client(popup->popup);
648
649 if (!weston_desktop_surface_get_grab(popup->popup))
650 goto end;
651
652 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(popup->seat);
653 if (topmost != popup->popup) {
654 struct wl_resource *client_resource =
655 weston_desktop_client_get_resource(client);
656
657 wl_resource_post_error(client_resource,
658 XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
659 "xdg_popup was destroyed while it was not the topmost popup.");
660 }
661
662 weston_desktop_surface_popup_ungrab(popup->popup, popup->seat);
663
664end:
665 free(popup);
666}
667
668static const struct xdg_popup_interface weston_desktop_xdg_popup_implementation = {
669 .destroy = weston_desktop_destroy_request,
670};
671
672static const struct weston_desktop_surface_implementation weston_desktop_xdg_popup_internal_implementation = {
673 .close = weston_desktop_xdg_popup_close,
674
675 .destroy = weston_desktop_xdg_popup_destroy,
676};
677
678static void
679weston_desktop_xdg_shell_protocol_use_unstable_version(struct wl_client *wl_client,
680 struct wl_resource *resource,
681 int32_t version)
682{
683 if (version > 1) {
684 wl_resource_post_error(resource,
685 1, "xdg_shell version not supported");
686 return;
687 }
688}
689
690static void
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200691weston_desktop_xdg_surface_add_idle_callback(void *user_data)
Quentin Glidic248dd102016-08-12 10:41:34 +0200692{
693 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200694
Quentin Glidic248dd102016-08-12 10:41:34 +0200695 surface->add_idle = NULL;
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200696 weston_desktop_xdg_surface_ensure_added(surface);
Quentin Glidic248dd102016-08-12 10:41:34 +0200697}
698
699static void
700weston_desktop_xdg_shell_protocol_get_xdg_surface(struct wl_client *wl_client,
701 struct wl_resource *resource,
702 uint32_t id,
703 struct wl_resource *surface_resource)
704{
705 struct weston_desktop_client *client =
706 wl_resource_get_user_data(resource);
707 struct weston_desktop *desktop =
708 weston_desktop_client_get_desktop(client);
709 struct weston_surface *wsurface =
710 wl_resource_get_user_data(surface_resource);
711 struct weston_desktop_xdg_surface *surface;
712 struct wl_display *display = weston_desktop_get_display(desktop);
713 struct wl_event_loop *loop = wl_display_get_event_loop(display);
714
715 if (weston_surface_set_role(wsurface, "xdg_surface", resource, XDG_SHELL_ERROR_ROLE) < 0)
716 return;
717
718 surface = zalloc(sizeof(struct weston_desktop_xdg_surface));
719 if (surface == NULL) {
720 wl_client_post_no_memory(wl_client);
721 return;
722 }
723
724 surface->desktop = desktop;
725
726 surface->surface =
727 weston_desktop_surface_create(surface->desktop, client,
728 wsurface,
729 &weston_desktop_xdg_surface_internal_implementation,
730 surface);
731 if (surface->surface == NULL) {
732 free(surface);
733 return;
734 }
735
736 surface->resource =
737 weston_desktop_surface_add_resource(surface->surface,
738 &xdg_surface_interface,
739 &weston_desktop_xdg_surface_implementation,
740 id, NULL);
741 if (surface->resource == NULL)
742 return;
743
744 surface->add_idle =
745 wl_event_loop_add_idle(loop,
Quentin Glidic6967f0e2016-08-18 15:51:38 +0200746 weston_desktop_xdg_surface_add_idle_callback,
Quentin Glidic248dd102016-08-12 10:41:34 +0200747 surface);
748}
749
750static void
751weston_desktop_xdg_shell_protocol_get_xdg_popup(struct wl_client *wl_client,
752 struct wl_resource *resource,
753 uint32_t id,
754 struct wl_resource *surface_resource,
755 struct wl_resource *parent_resource,
756 struct wl_resource *seat_resource,
757 uint32_t serial,
758 int32_t x, int32_t y)
759{
760 struct weston_desktop_client *client =
761 wl_resource_get_user_data(resource);
762 struct weston_surface *wsurface =
763 wl_resource_get_user_data(surface_resource);
764 struct weston_surface *wparent =
765 wl_resource_get_user_data(parent_resource);
766 struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
767 struct weston_desktop_seat *seat = weston_desktop_seat_from_seat(wseat);
768 struct weston_desktop_surface *parent, *topmost;
769 bool parent_is_popup, parent_is_xdg;
770 struct weston_desktop_xdg_popup *popup;
771
772 if (weston_surface_set_role(wsurface, "xdg_popup", resource, XDG_SHELL_ERROR_ROLE) < 0)
773 return;
774
775 if (!weston_surface_is_desktop_surface(wparent)) {
776 wl_resource_post_error(resource,
777 XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
778 "xdg_popup parent was invalid");
779 return;
780 }
781
782 parent = weston_surface_get_desktop_surface(wparent);
783 parent_is_xdg =
784 weston_desktop_surface_has_implementation(parent,
785 &weston_desktop_xdg_surface_internal_implementation);
786 parent_is_popup =
787 weston_desktop_surface_has_implementation(parent,
788 &weston_desktop_xdg_popup_internal_implementation);
789
790 if (!parent_is_xdg && !parent_is_popup) {
791 wl_resource_post_error(resource,
792 XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
793 "xdg_popup parent was invalid");
794 return;
795 }
796
797 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(seat);
798 if ((topmost == NULL && parent_is_popup) ||
799 (topmost != NULL && topmost != parent)) {
800 wl_resource_post_error(resource,
801 XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
802 "xdg_popup was not created on the topmost popup");
803 return;
804 }
805
806 popup = zalloc(sizeof(struct weston_desktop_xdg_popup));
807 if (popup == NULL) {
808 wl_client_post_no_memory(wl_client);
809 return;
810 }
811
812 popup->desktop = weston_desktop_client_get_desktop(client);
813 popup->display = weston_desktop_get_display(popup->desktop);
814 popup->seat = seat;
815
816 popup->popup =
817 weston_desktop_surface_create(popup->desktop, client, wsurface,
818 &weston_desktop_xdg_popup_internal_implementation,
819 popup);
820 if (popup->popup == NULL) {
821 free(popup);
822 return;
823 }
824
825 popup->resource =
826 weston_desktop_surface_add_resource(popup->popup,
827 &xdg_popup_interface,
828 &weston_desktop_xdg_popup_implementation,
829 id, NULL);
830 if (popup->resource == NULL)
831 return;
832
833 weston_desktop_surface_set_relative_to(popup->popup, parent, x, y, false);
834 weston_desktop_surface_popup_grab(popup->popup, popup->seat, serial);
835}
836
837static void
838weston_desktop_xdg_shell_protocol_pong(struct wl_client *wl_client,
839 struct wl_resource *resource,
840 uint32_t serial)
841{
842 struct weston_desktop_client *client =
843 wl_resource_get_user_data(resource);
844
845 weston_desktop_client_pong(client, serial);
846}
847
848static const struct xdg_shell_interface weston_desktop_xdg_shell_implementation = {
849 .destroy = weston_desktop_destroy_request,
850 .use_unstable_version = weston_desktop_xdg_shell_protocol_use_unstable_version,
851 .get_xdg_surface = weston_desktop_xdg_shell_protocol_get_xdg_surface,
852 .get_xdg_popup = weston_desktop_xdg_shell_protocol_get_xdg_popup,
853 .pong = weston_desktop_xdg_shell_protocol_pong,
854};
855
856static int
857xdg_shell_unversioned_dispatch(const void *implementation,
858 void *_target, uint32_t opcode,
859 const struct wl_message *message,
860 union wl_argument *args)
861{
862 struct wl_resource *resource = _target;
863 struct weston_desktop_client *client =
864 wl_resource_get_user_data(resource);
865
866 if (opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */) {
867 wl_resource_post_error(resource,
868 WL_DISPLAY_ERROR_INVALID_OBJECT,
869 "must call use_unstable_version first");
870 return 0;
871 }
872
873#define XDG_SERVER_VERSION 5
874
875 if (args[0].i != XDG_SERVER_VERSION) {
876 wl_resource_post_error(resource,
877 WL_DISPLAY_ERROR_INVALID_OBJECT,
878 "incompatible version, server is %d " "client wants %d",
879 XDG_SERVER_VERSION, args[0].i);
880 return 0;
881 }
882
883 wl_resource_set_implementation(resource,
884 &weston_desktop_xdg_shell_implementation,
885 client, implementation);
886
887 return 1;
888}
889
890static void
891weston_desktop_xdg_shell_bind(struct wl_client *client, void *data,
892 uint32_t version, uint32_t id)
893{
894 struct weston_desktop *desktop = data;
895
896 weston_desktop_client_create(desktop, client,
897 xdg_shell_unversioned_dispatch,
898 &xdg_shell_interface, NULL, version, id);
899}
900
901struct wl_global *
902weston_desktop_xdg_shell_v5_create(struct weston_desktop *desktop,
903 struct wl_display *display)
904{
905 return wl_global_create(display,
906 &xdg_shell_interface,
907 WD_XDG_SHELL_PROTOCOL_VERSION,
908 desktop, weston_desktop_xdg_shell_bind);
909}