blob: db894d4ab25a5b51a83ca9a67b5991a1f7b78f9c [file] [log] [blame]
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +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#include <assert.h>
31
32#include <wayland-server.h>
33
34#include "compositor.h"
35#include "zalloc.h"
Daniel Stone7dbb0e12016-11-24 15:30:41 +000036#include "xdg-shell-unstable-v6-server-protocol.h"
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +020037
38#include "libweston-desktop.h"
39#include "internal.h"
40
41#define WD_XDG_SHELL_PROTOCOL_VERSION 1
42
43static const char *weston_desktop_xdg_toplevel_role = "xdg_toplevel";
44static const char *weston_desktop_xdg_popup_role = "xdg_popup";
45
46struct weston_desktop_xdg_positioner {
47 struct weston_desktop *desktop;
48 struct weston_desktop_client *client;
49 struct wl_resource *resource;
50
51 struct weston_size size;
52 struct weston_geometry anchor_rect;
53 enum zxdg_positioner_v6_anchor anchor;
54 enum zxdg_positioner_v6_gravity gravity;
55 enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment;
56 struct weston_position offset;
57};
58
59enum weston_desktop_xdg_surface_role {
60 WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE,
61 WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL,
62 WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP,
63};
64
65struct weston_desktop_xdg_surface {
66 struct wl_resource *resource;
67 struct weston_desktop *desktop;
68 struct weston_surface *surface;
69 struct weston_desktop_surface *desktop_surface;
70 bool configured;
71 struct wl_event_source *configure_idle;
72 uint32_t configure_serial;
73
74 bool has_next_geometry;
75 struct weston_geometry next_geometry;
76
77 enum weston_desktop_xdg_surface_role role;
78};
79
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020080struct weston_desktop_xdg_toplevel_state {
81 bool maximized;
82 bool fullscreen;
83 bool resizing;
84 bool activated;
85};
86
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +020087struct weston_desktop_xdg_toplevel {
88 struct weston_desktop_xdg_surface base;
89
90 struct wl_resource *resource;
91 bool added;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +020092 struct {
Quentin Glidic19d1f6e2017-07-12 09:42:57 +020093 struct weston_desktop_xdg_toplevel_state state;
94 struct weston_size size;
95 } pending;
96 struct {
97 struct weston_desktop_xdg_toplevel_state state;
98 struct weston_size min_size, max_size;
99 } next;
100 struct {
101 struct weston_desktop_xdg_toplevel_state state;
102 struct weston_size min_size, max_size;
103 } current;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200104};
105
106struct weston_desktop_xdg_popup {
107 struct weston_desktop_xdg_surface base;
108
109 struct wl_resource *resource;
110 bool committed;
111 struct weston_desktop_xdg_surface *parent;
112 struct weston_desktop_seat *seat;
113 struct weston_geometry geometry;
114};
115
116#define weston_desktop_surface_role_biggest_size (sizeof(struct weston_desktop_xdg_toplevel))
117
118
119static struct weston_geometry
120weston_desktop_xdg_positioner_get_geometry(struct weston_desktop_xdg_positioner *positioner,
121 struct weston_desktop_surface *dsurface,
122 struct weston_desktop_surface *parent)
123{
124 struct weston_geometry geometry = {
125 .x = positioner->offset.x,
126 .y = positioner->offset.y,
127 .width = positioner->size.width,
128 .height = positioner->size.height,
129 };
130
131 if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP)
132 geometry.y += positioner->anchor_rect.y;
133 else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)
134 geometry.y += positioner->anchor_rect.y + positioner->anchor_rect.height;
135 else
136 geometry.y += positioner->anchor_rect.y + positioner->anchor_rect.height / 2;
137
138 if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT)
139 geometry.x += positioner->anchor_rect.x;
140 else if (positioner->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT)
141 geometry.x += positioner->anchor_rect.x + positioner->anchor_rect.width;
142 else
143 geometry.x += positioner->anchor_rect.x + positioner->anchor_rect.width / 2;
144
145 if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP)
146 geometry.y -= geometry.height;
147 else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)
148 geometry.y = geometry.y;
149 else
150 geometry.y -= geometry.height / 2;
151
152 if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
153 geometry.x -= geometry.width;
154 else if (positioner->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT)
155 geometry.x = geometry.x;
156 else
157 geometry.x -= geometry.width / 2;
158
159 if (positioner->constraint_adjustment == ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE)
160 return geometry;
161
162 /* TODO: add compositor policy configuration and the code here */
163
164 return geometry;
165}
166
167static void
168weston_desktop_xdg_positioner_protocol_set_size(struct wl_client *wl_client,
169 struct wl_resource *resource,
170 int32_t width, int32_t height)
171{
172 struct weston_desktop_xdg_positioner *positioner =
173 wl_resource_get_user_data(resource);
174
175 if (width < 1 || height < 1) {
176 wl_resource_post_error(resource,
177 ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
178 "width and height must be positives and non-zero");
179 return;
180 }
181
182 positioner->size.width = width;
183 positioner->size.height = height;
184}
185
186static void
187weston_desktop_xdg_positioner_protocol_set_anchor_rect(struct wl_client *wl_client,
188 struct wl_resource *resource,
189 int32_t x, int32_t y,
190 int32_t width, int32_t height)
191{
192 struct weston_desktop_xdg_positioner *positioner =
193 wl_resource_get_user_data(resource);
194
195 if (width < 1 || height < 1) {
196 wl_resource_post_error(resource,
197 ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
198 "width and height must be positives and non-zero");
199 return;
200 }
201
202 positioner->anchor_rect.x = x;
203 positioner->anchor_rect.y = y;
204 positioner->anchor_rect.width = width;
205 positioner->anchor_rect.height = height;
206}
207
208static void
209weston_desktop_xdg_positioner_protocol_set_anchor(struct wl_client *wl_client,
210 struct wl_resource *resource,
211 enum zxdg_positioner_v6_anchor anchor)
212{
213 struct weston_desktop_xdg_positioner *positioner =
214 wl_resource_get_user_data(resource);
215
216 if (((anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP ) &&
217 (anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) ||
218 ((anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT) &&
219 (anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT))) {
220 wl_resource_post_error(resource,
221 ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
222 "same-axis values are not allowed");
223 return;
224 }
225
226 positioner->anchor = anchor;
227}
228
229static void
230weston_desktop_xdg_positioner_protocol_set_gravity(struct wl_client *wl_client,
231 struct wl_resource *resource,
232 enum zxdg_positioner_v6_gravity gravity)
233{
234 struct weston_desktop_xdg_positioner *positioner =
235 wl_resource_get_user_data(resource);
236
237 if (((gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP) &&
238 (gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) ||
239 ((gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT) &&
240 (gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))) {
241 wl_resource_post_error(resource,
242 ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
243 "same-axis values are not allowed");
244 return;
245 }
246
247 positioner->gravity = gravity;
248}
249
250static void
251weston_desktop_xdg_positioner_protocol_set_constraint_adjustment(struct wl_client *wl_client,
252 struct wl_resource *resource,
253 enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
254{
255 struct weston_desktop_xdg_positioner *positioner =
256 wl_resource_get_user_data(resource);
257
258 positioner->constraint_adjustment = constraint_adjustment;
259}
260
261static void
262weston_desktop_xdg_positioner_protocol_set_offset(struct wl_client *wl_client,
263 struct wl_resource *resource,
264 int32_t x, int32_t y)
265{
266 struct weston_desktop_xdg_positioner *positioner =
267 wl_resource_get_user_data(resource);
268
269 positioner->offset.x = x;
270 positioner->offset.y = y;
271}
272
273static void
274weston_desktop_xdg_positioner_destroy(struct wl_resource *resource)
275{
276 struct weston_desktop_xdg_positioner *positioner =
277 wl_resource_get_user_data(resource);
278
279 free(positioner);
280}
281
282static const struct zxdg_positioner_v6_interface weston_desktop_xdg_positioner_implementation = {
283 .destroy = weston_desktop_destroy_request,
284 .set_size = weston_desktop_xdg_positioner_protocol_set_size,
285 .set_anchor_rect = weston_desktop_xdg_positioner_protocol_set_anchor_rect,
286 .set_anchor = weston_desktop_xdg_positioner_protocol_set_anchor,
287 .set_gravity = weston_desktop_xdg_positioner_protocol_set_gravity,
288 .set_constraint_adjustment = weston_desktop_xdg_positioner_protocol_set_constraint_adjustment,
289 .set_offset = weston_desktop_xdg_positioner_protocol_set_offset,
290};
291
292static void
Quentin Glidicd51f8262017-04-13 20:25:27 +0200293weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
294 bool force);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200295
296static void
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200297weston_desktop_xdg_toplevel_ensure_added(struct weston_desktop_xdg_toplevel *toplevel)
298{
299 if (toplevel->added)
300 return;
301
302 weston_desktop_api_surface_added(toplevel->base.desktop,
303 toplevel->base.desktop_surface);
Quentin Glidicd51f8262017-04-13 20:25:27 +0200304 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, true);
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200305 toplevel->added = true;
306}
307
308static void
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200309weston_desktop_xdg_toplevel_protocol_set_parent(struct wl_client *wl_client,
310 struct wl_resource *resource,
311 struct wl_resource *parent_resource)
312{
313 struct weston_desktop_surface *dsurface =
314 wl_resource_get_user_data(resource);
315 struct weston_desktop_xdg_toplevel *toplevel =
316 weston_desktop_surface_get_implementation_data(dsurface);
317 struct weston_desktop_surface *parent = NULL;
318
319 if (parent_resource != NULL)
320 parent = wl_resource_get_user_data(parent_resource);
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200321
322 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200323 weston_desktop_api_set_parent(toplevel->base.desktop, dsurface, parent);
324}
325
326static void
327weston_desktop_xdg_toplevel_protocol_set_title(struct wl_client *wl_client,
328 struct wl_resource *resource,
329 const char *title)
330{
331 struct weston_desktop_surface *toplevel =
332 wl_resource_get_user_data(resource);
333
334 weston_desktop_surface_set_title(toplevel, title);
335}
336
337static void
338weston_desktop_xdg_toplevel_protocol_set_app_id(struct wl_client *wl_client,
339 struct wl_resource *resource,
340 const char *app_id)
341{
342 struct weston_desktop_surface *toplevel =
343 wl_resource_get_user_data(resource);
344
345 weston_desktop_surface_set_app_id(toplevel, app_id);
346}
347
348static void
349weston_desktop_xdg_toplevel_protocol_show_window_menu(struct wl_client *wl_client,
350 struct wl_resource *resource,
351 struct wl_resource *seat_resource,
352 uint32_t serial,
353 int32_t x, int32_t y)
354{
355 struct weston_desktop_surface *dsurface =
356 wl_resource_get_user_data(resource);
357 struct weston_seat *seat =
358 wl_resource_get_user_data(seat_resource);
359 struct weston_desktop_xdg_toplevel *toplevel =
360 weston_desktop_surface_get_implementation_data(dsurface);
361
Quentin Glidic0abf8902016-09-11 11:34:47 +0200362 if (!toplevel->base.configured) {
363 wl_resource_post_error(toplevel->resource,
364 ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
365 "Surface has not been configured yet");
366 return;
367 }
368
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200369 weston_desktop_api_show_window_menu(toplevel->base.desktop,
370 dsurface, seat, x, y);
371}
372
373static void
374weston_desktop_xdg_toplevel_protocol_move(struct wl_client *wl_client,
375 struct wl_resource *resource,
376 struct wl_resource *seat_resource,
377 uint32_t serial)
378{
379 struct weston_desktop_surface *dsurface =
380 wl_resource_get_user_data(resource);
381 struct weston_seat *seat =
382 wl_resource_get_user_data(seat_resource);
383 struct weston_desktop_xdg_toplevel *toplevel =
384 weston_desktop_surface_get_implementation_data(dsurface);
385
Quentin Glidic0abf8902016-09-11 11:34:47 +0200386 if (!toplevel->base.configured) {
387 wl_resource_post_error(toplevel->resource,
388 ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
389 "Surface has not been configured yet");
390 return;
391 }
392
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200393 weston_desktop_api_move(toplevel->base.desktop, dsurface, seat, serial);
394}
395
396static void
397weston_desktop_xdg_toplevel_protocol_resize(struct wl_client *wl_client,
398 struct wl_resource *resource,
399 struct wl_resource *seat_resource,
400 uint32_t serial,
401 enum zxdg_toplevel_v6_resize_edge edges)
402{
403 struct weston_desktop_surface *dsurface =
404 wl_resource_get_user_data(resource);
405 struct weston_seat *seat =
406 wl_resource_get_user_data(seat_resource);
407 struct weston_desktop_xdg_toplevel *toplevel =
408 weston_desktop_surface_get_implementation_data(dsurface);
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200409 enum weston_desktop_surface_edge surf_edges =
410 (enum weston_desktop_surface_edge) edges;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200411
Quentin Glidic0abf8902016-09-11 11:34:47 +0200412 if (!toplevel->base.configured) {
413 wl_resource_post_error(toplevel->resource,
414 ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
415 "Surface has not been configured yet");
416 return;
417 }
418
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200419 weston_desktop_api_resize(toplevel->base.desktop,
Armin Krezović4e2fa0a2016-09-10 19:11:21 +0200420 dsurface, seat, serial, surf_edges);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200421}
422
423static void
424weston_desktop_xdg_toplevel_ack_configure(struct weston_desktop_xdg_toplevel *toplevel)
425{
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200426 toplevel->next.state = toplevel->pending.state;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200427}
428
429static void
430weston_desktop_xdg_toplevel_protocol_set_min_size(struct wl_client *wl_client,
431 struct wl_resource *resource,
432 int32_t width, int32_t height)
433{
434 struct weston_desktop_surface *dsurface =
435 wl_resource_get_user_data(resource);
436 struct weston_desktop_xdg_toplevel *toplevel =
437 weston_desktop_surface_get_implementation_data(dsurface);
438
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200439 toplevel->next.min_size.width = width;
440 toplevel->next.min_size.height = height;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200441}
442
443static void
444weston_desktop_xdg_toplevel_protocol_set_max_size(struct wl_client *wl_client,
445 struct wl_resource *resource,
446 int32_t width, int32_t height)
447{
448 struct weston_desktop_surface *dsurface =
449 wl_resource_get_user_data(resource);
450 struct weston_desktop_xdg_toplevel *toplevel =
451 weston_desktop_surface_get_implementation_data(dsurface);
452
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200453 toplevel->next.max_size.width = width;
454 toplevel->next.max_size.height = height;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200455}
456
457static void
458weston_desktop_xdg_toplevel_protocol_set_maximized(struct wl_client *wl_client,
459 struct wl_resource *resource)
460{
461 struct weston_desktop_surface *dsurface =
462 wl_resource_get_user_data(resource);
463 struct weston_desktop_xdg_toplevel *toplevel =
464 weston_desktop_surface_get_implementation_data(dsurface);
465
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200466 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200467 weston_desktop_api_maximized_requested(toplevel->base.desktop, dsurface, true);
468}
469
470static void
471weston_desktop_xdg_toplevel_protocol_unset_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_toplevel *toplevel =
477 weston_desktop_surface_get_implementation_data(dsurface);
478
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200479 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200480 weston_desktop_api_maximized_requested(toplevel->base.desktop, dsurface, false);
481}
482
483static void
484weston_desktop_xdg_toplevel_protocol_set_fullscreen(struct wl_client *wl_client,
485 struct wl_resource *resource,
486 struct wl_resource *output_resource)
487{
488 struct weston_desktop_surface *dsurface =
489 wl_resource_get_user_data(resource);
490 struct weston_desktop_xdg_toplevel *toplevel =
491 weston_desktop_surface_get_implementation_data(dsurface);
492 struct weston_output *output = NULL;
493
494 if (output_resource != NULL)
495 output = wl_resource_get_user_data(output_resource);
496
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200497 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200498 weston_desktop_api_fullscreen_requested(toplevel->base.desktop, dsurface,
499 true, output);
500}
501
502static void
503weston_desktop_xdg_toplevel_protocol_unset_fullscreen(struct wl_client *wl_client,
504 struct wl_resource *resource)
505{
506 struct weston_desktop_surface *dsurface =
507 wl_resource_get_user_data(resource);
508 struct weston_desktop_xdg_toplevel *toplevel =
509 weston_desktop_surface_get_implementation_data(dsurface);
510
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200511 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200512 weston_desktop_api_fullscreen_requested(toplevel->base.desktop, dsurface,
513 false, NULL);
514}
515
516static void
517weston_desktop_xdg_toplevel_protocol_set_minimized(struct wl_client *wl_client,
518 struct wl_resource *resource)
519{
520 struct weston_desktop_surface *dsurface =
521 wl_resource_get_user_data(resource);
522 struct weston_desktop_xdg_toplevel *toplevel =
523 weston_desktop_surface_get_implementation_data(dsurface);
524
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200525 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200526 weston_desktop_api_minimized_requested(toplevel->base.desktop, dsurface);
527}
528
529static void
530weston_desktop_xdg_toplevel_send_configure(struct weston_desktop_xdg_toplevel *toplevel)
531{
532 uint32_t *s;
533 struct wl_array states;
534
535 wl_array_init(&states);
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200536 if (toplevel->pending.state.maximized) {
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200537 s = wl_array_add(&states, sizeof(uint32_t));
538 *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
539 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200540 if (toplevel->pending.state.fullscreen) {
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200541 s = wl_array_add(&states, sizeof(uint32_t));
542 *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
543 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200544 if (toplevel->pending.state.resizing) {
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200545 s = wl_array_add(&states, sizeof(uint32_t));
546 *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
547 }
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200548 if (toplevel->pending.state.activated) {
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200549 s = wl_array_add(&states, sizeof(uint32_t));
550 *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
551 }
552
553 zxdg_toplevel_v6_send_configure(toplevel->resource,
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200554 toplevel->pending.size.width,
555 toplevel->pending.size.height,
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200556 &states);
557
558 wl_array_release(&states);
559};
560
561static void
562weston_desktop_xdg_toplevel_set_maximized(struct weston_desktop_surface *dsurface,
563 void *user_data, bool maximized)
564{
565 struct weston_desktop_xdg_toplevel *toplevel = user_data;
566
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200567 toplevel->pending.state.maximized = maximized;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200568 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200569}
570
571static void
572weston_desktop_xdg_toplevel_set_fullscreen(struct weston_desktop_surface *dsurface,
573 void *user_data, bool fullscreen)
574{
575 struct weston_desktop_xdg_toplevel *toplevel = user_data;
576
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200577 toplevel->pending.state.fullscreen = fullscreen;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200578 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200579}
580
581static void
582weston_desktop_xdg_toplevel_set_resizing(struct weston_desktop_surface *dsurface,
583 void *user_data, bool resizing)
584{
585 struct weston_desktop_xdg_toplevel *toplevel = user_data;
586
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200587 toplevel->pending.state.resizing = resizing;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200588 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200589}
590
591static void
592weston_desktop_xdg_toplevel_set_activated(struct weston_desktop_surface *dsurface,
593 void *user_data, bool activated)
594{
595 struct weston_desktop_xdg_toplevel *toplevel = user_data;
596
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200597 toplevel->pending.state.activated = activated;
Quentin Glidicd51f8262017-04-13 20:25:27 +0200598 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200599}
600
601static void
602weston_desktop_xdg_toplevel_set_size(struct weston_desktop_surface *dsurface,
603 void *user_data,
604 int32_t width, int32_t height)
605{
606 struct weston_desktop_xdg_toplevel *toplevel = user_data;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200607
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200608 toplevel->pending.size.width = width;
609 toplevel->pending.size.height = height;
Quentin Glidica56b0532016-09-13 10:05:58 +0200610
Quentin Glidicd51f8262017-04-13 20:25:27 +0200611 weston_desktop_xdg_surface_schedule_configure(&toplevel->base, false);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200612}
613
614static void
615weston_desktop_xdg_toplevel_committed(struct weston_desktop_xdg_toplevel *toplevel,
Quentin Glidiccba26e72016-08-15 12:20:22 +0200616 int32_t sx, int32_t sy)
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200617{
618 struct weston_surface *wsurface =
619 weston_desktop_surface_get_surface(toplevel->base.desktop_surface);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200620
Quentin Glidiccba26e72016-08-15 12:20:22 +0200621 if (!wsurface->buffer_ref.buffer && !toplevel->added) {
Quentin Glidic3d7e6072016-09-11 11:29:23 +0200622 weston_desktop_xdg_toplevel_ensure_added(toplevel);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200623 return;
624 }
Quentin Glidiccba26e72016-08-15 12:20:22 +0200625 if (!wsurface->buffer_ref.buffer)
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200626 return;
627
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200628 if ((toplevel->next.state.maximized || toplevel->next.state.fullscreen) &&
629 (toplevel->pending.size.width != wsurface->width ||
630 toplevel->pending.size.height != wsurface->height)) {
Quentin Glidicc84423b2017-03-10 11:50:41 +0100631 struct weston_desktop_client *client =
632 weston_desktop_surface_get_client(toplevel->base.desktop_surface);
633 struct wl_resource *client_resource =
634 weston_desktop_client_get_resource(client);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200635
Quentin Glidicc84423b2017-03-10 11:50:41 +0100636 wl_resource_post_error(client_resource,
637 ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
638 "xdg_surface buffer does not match the configured state");
639 return;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200640 }
Quentin Glidicc84423b2017-03-10 11:50:41 +0100641
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200642 toplevel->current.state = toplevel->next.state;
643 toplevel->current.min_size = toplevel->next.min_size;
644 toplevel->current.max_size = toplevel->next.max_size;
Quentin Glidicc84423b2017-03-10 11:50:41 +0100645
646 weston_desktop_api_committed(toplevel->base.desktop,
647 toplevel->base.desktop_surface,
648 sx, sy);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200649}
650
651static void
652weston_desktop_xdg_toplevel_close(struct weston_desktop_xdg_toplevel *toplevel)
653{
654 zxdg_toplevel_v6_send_close(toplevel->resource);
655}
656
657static bool
658weston_desktop_xdg_toplevel_get_maximized(struct weston_desktop_surface *dsurface,
659 void *user_data)
660{
661 struct weston_desktop_xdg_toplevel *toplevel = user_data;
662
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200663 return toplevel->current.state.maximized;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200664}
665
666static bool
667weston_desktop_xdg_toplevel_get_fullscreen(struct weston_desktop_surface *dsurface,
668 void *user_data)
669{
670 struct weston_desktop_xdg_toplevel *toplevel = user_data;
671
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200672 return toplevel->current.state.fullscreen;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200673}
674
675static bool
676weston_desktop_xdg_toplevel_get_resizing(struct weston_desktop_surface *dsurface,
677 void *user_data)
678{
679 struct weston_desktop_xdg_toplevel *toplevel = user_data;
680
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200681 return toplevel->current.state.resizing;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200682}
683
684static bool
685weston_desktop_xdg_toplevel_get_activated(struct weston_desktop_surface *dsurface,
686 void *user_data)
687{
688 struct weston_desktop_xdg_toplevel *toplevel = user_data;
689
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200690 return toplevel->current.state.activated;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200691}
692
693static void
694weston_desktop_xdg_toplevel_destroy(struct weston_desktop_xdg_toplevel *toplevel)
695{
696 if (toplevel->added)
697 weston_desktop_api_surface_removed(toplevel->base.desktop,
698 toplevel->base.desktop_surface);
699}
700
701static void
702weston_desktop_xdg_toplevel_resource_destroy(struct wl_resource *resource)
703{
704 struct weston_desktop_surface *dsurface =
705 wl_resource_get_user_data(resource);
706
707 if (dsurface != NULL)
708 weston_desktop_surface_resource_destroy(resource);
709}
710
711static const struct zxdg_toplevel_v6_interface weston_desktop_xdg_toplevel_implementation = {
712 .destroy = weston_desktop_destroy_request,
713 .set_parent = weston_desktop_xdg_toplevel_protocol_set_parent,
714 .set_title = weston_desktop_xdg_toplevel_protocol_set_title,
715 .set_app_id = weston_desktop_xdg_toplevel_protocol_set_app_id,
716 .show_window_menu = weston_desktop_xdg_toplevel_protocol_show_window_menu,
717 .move = weston_desktop_xdg_toplevel_protocol_move,
718 .resize = weston_desktop_xdg_toplevel_protocol_resize,
719 .set_min_size = weston_desktop_xdg_toplevel_protocol_set_min_size,
720 .set_max_size = weston_desktop_xdg_toplevel_protocol_set_max_size,
721 .set_maximized = weston_desktop_xdg_toplevel_protocol_set_maximized,
722 .unset_maximized = weston_desktop_xdg_toplevel_protocol_unset_maximized,
723 .set_fullscreen = weston_desktop_xdg_toplevel_protocol_set_fullscreen,
724 .unset_fullscreen = weston_desktop_xdg_toplevel_protocol_unset_fullscreen,
725 .set_minimized = weston_desktop_xdg_toplevel_protocol_set_minimized,
726};
727
728static void
729weston_desktop_xdg_popup_protocol_grab(struct wl_client *wl_client,
730 struct wl_resource *resource,
731 struct wl_resource *seat_resource,
732 uint32_t serial)
733{
734 struct weston_desktop_surface *dsurface =
735 wl_resource_get_user_data(resource);
736 struct weston_desktop_xdg_popup *popup =
737 weston_desktop_surface_get_implementation_data(dsurface);
738 struct weston_seat *wseat = wl_resource_get_user_data(seat_resource);
739 struct weston_desktop_seat *seat = weston_desktop_seat_from_seat(wseat);
740 struct weston_desktop_surface *topmost;
741 bool parent_is_toplevel =
742 popup->parent->role == WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL;
743
744 if (popup->committed) {
745 wl_resource_post_error(popup->resource,
746 ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
747 "xdg_popup already is mapped");
748 return;
749 }
750
751 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(seat);
752 if ((topmost == NULL && !parent_is_toplevel) ||
753 (topmost != NULL && topmost != popup->parent->desktop_surface)) {
754 struct weston_desktop_client *client =
755 weston_desktop_surface_get_client(dsurface);
756 struct wl_resource *client_resource =
757 weston_desktop_client_get_resource(client);
758
759 wl_resource_post_error(client_resource,
760 ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP,
761 "xdg_popup was not created on the topmost popup");
762 return;
763 }
764
765 popup->seat = seat;
766 weston_desktop_surface_popup_grab(popup->base.desktop_surface,
767 popup->seat, serial);
768}
769
770static void
771weston_desktop_xdg_popup_send_configure(struct weston_desktop_xdg_popup *popup)
772{
773 zxdg_popup_v6_send_configure(popup->resource,
774 popup->geometry.x,
775 popup->geometry.y,
776 popup->geometry.width,
777 popup->geometry.height);
778}
779
780static void
781weston_desktop_xdg_popup_update_position(struct weston_desktop_surface *dsurface,
782 void *user_data);
783
784static void
785weston_desktop_xdg_popup_committed(struct weston_desktop_xdg_popup *popup)
786{
787 if (!popup->committed)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200788 weston_desktop_xdg_surface_schedule_configure(&popup->base, true);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200789 popup->committed = true;
790 weston_desktop_xdg_popup_update_position(popup->base.desktop_surface,
791 popup);
792}
793
794static void
795weston_desktop_xdg_popup_update_position(struct weston_desktop_surface *dsurface,
796 void *user_data)
797{
798}
799
800static void
801weston_desktop_xdg_popup_close(struct weston_desktop_xdg_popup *popup)
802{
803 zxdg_popup_v6_send_popup_done(popup->resource);
804}
805
806static void
807weston_desktop_xdg_popup_destroy(struct weston_desktop_xdg_popup *popup)
808{
809 struct weston_desktop_surface *topmost;
810 struct weston_desktop_client *client =
811 weston_desktop_surface_get_client(popup->base.desktop_surface);
812
813 if (!weston_desktop_surface_get_grab(popup->base.desktop_surface))
814 return;
815
816 topmost = weston_desktop_seat_popup_grab_get_topmost_surface(popup->seat);
817 if (topmost != popup->base.desktop_surface) {
818 struct wl_resource *client_resource =
819 weston_desktop_client_get_resource(client);
820
821 wl_resource_post_error(client_resource,
822 ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP,
823 "xdg_popup was destroyed while it was not the topmost popup.");
824 }
825
826 weston_desktop_surface_popup_ungrab(popup->base.desktop_surface,
827 popup->seat);
828}
829
830static void
831weston_desktop_xdg_popup_resource_destroy(struct wl_resource *resource)
832{
833 struct weston_desktop_surface *dsurface =
834 wl_resource_get_user_data(resource);
835
836 if (dsurface != NULL)
837 weston_desktop_surface_resource_destroy(resource);
838}
839
840static const struct zxdg_popup_v6_interface weston_desktop_xdg_popup_implementation = {
841 .destroy = weston_desktop_destroy_request,
842 .grab = weston_desktop_xdg_popup_protocol_grab,
843};
844
845static void
846weston_desktop_xdg_surface_send_configure(void *user_data)
847{
848 struct weston_desktop_xdg_surface *surface = user_data;
849
850 surface->configure_idle = NULL;
851 surface->configure_serial =
852 wl_display_next_serial(weston_desktop_get_display(surface->desktop));
853
854 switch (surface->role) {
855 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
856 assert(0 && "not reached");
857 break;
858 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
859 weston_desktop_xdg_toplevel_send_configure((struct weston_desktop_xdg_toplevel *) surface);
860 break;
861 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
862 weston_desktop_xdg_popup_send_configure((struct weston_desktop_xdg_popup *) surface);
863 break;
864 }
865
866 zxdg_surface_v6_send_configure(surface->resource, surface->configure_serial);
867}
868
Quentin Glidicd51f8262017-04-13 20:25:27 +0200869static bool
870weston_desktop_xdg_toplevel_state_compare(struct weston_desktop_xdg_toplevel *toplevel)
871{
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200872 if (toplevel->pending.state.activated != toplevel->current.state.activated)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200873 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200874 if (toplevel->pending.state.fullscreen != toplevel->current.state.fullscreen)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200875 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200876 if (toplevel->pending.state.maximized != toplevel->current.state.maximized)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200877 return false;
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200878 if (toplevel->pending.state.resizing != toplevel->current.state.resizing)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200879 return false;
880
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200881 if (toplevel->base.surface->width == toplevel->pending.size.width &&
882 toplevel->base.surface->height == toplevel->pending.size.height)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200883 return true;
884
Quentin Glidic19d1f6e2017-07-12 09:42:57 +0200885 if (toplevel->pending.size.width == 0 &&
886 toplevel->pending.size.height == 0)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200887 return true;
888
889 return false;
890}
891
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200892static void
Quentin Glidicd51f8262017-04-13 20:25:27 +0200893weston_desktop_xdg_surface_schedule_configure(struct weston_desktop_xdg_surface *surface,
894 bool force)
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200895{
896 struct wl_display *display = weston_desktop_get_display(surface->desktop);
897 struct wl_event_loop *loop = wl_display_get_event_loop(display);
Quentin Glidic218126d2017-07-11 13:31:36 +0200898 bool pending_same = !force;
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200899
Quentin Glidicd51f8262017-04-13 20:25:27 +0200900 switch (surface->role) {
901 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
902 assert(0 && "not reached");
903 break;
904 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
Quentin Glidic218126d2017-07-11 13:31:36 +0200905 pending_same = pending_same &&
Quentin Glidicd51f8262017-04-13 20:25:27 +0200906 weston_desktop_xdg_toplevel_state_compare((struct weston_desktop_xdg_toplevel *) surface);
907 break;
908 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
909 break;
910 }
911
912 if (surface->configure_idle != NULL) {
Quentin Glidic218126d2017-07-11 13:31:36 +0200913 if (!pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200914 return;
915
916 wl_event_source_remove(surface->configure_idle);
917 surface->configure_idle = NULL;
918 } else {
Quentin Glidic218126d2017-07-11 13:31:36 +0200919 if (pending_same)
Quentin Glidicd51f8262017-04-13 20:25:27 +0200920 return;
921
922 surface->configure_idle =
923 wl_event_loop_add_idle(loop,
924 weston_desktop_xdg_surface_send_configure,
925 surface);
926 }
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200927}
928
929static void
930weston_desktop_xdg_surface_protocol_get_toplevel(struct wl_client *wl_client,
931 struct wl_resource *resource,
932 uint32_t id)
933{
934 struct weston_desktop_surface *dsurface =
935 wl_resource_get_user_data(resource);
936 struct weston_surface *wsurface =
937 weston_desktop_surface_get_surface(dsurface);
938 struct weston_desktop_xdg_toplevel *toplevel =
939 weston_desktop_surface_get_implementation_data(dsurface);
940
941 if (weston_surface_set_role(wsurface, weston_desktop_xdg_toplevel_role,
942 resource, ZXDG_SHELL_V6_ERROR_ROLE) < 0)
943 return;
944
945 toplevel->resource =
946 weston_desktop_surface_add_resource(toplevel->base.desktop_surface,
947 &zxdg_toplevel_v6_interface,
948 &weston_desktop_xdg_toplevel_implementation,
949 id, weston_desktop_xdg_toplevel_resource_destroy);
950 if (toplevel->resource == NULL)
951 return;
952
953 toplevel->base.role = WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL;
954}
955
956static void
957weston_desktop_xdg_surface_protocol_get_popup(struct wl_client *wl_client,
958 struct wl_resource *resource,
959 uint32_t id,
960 struct wl_resource *parent_resource,
961 struct wl_resource *positioner_resource)
962{
963 struct weston_desktop_surface *dsurface =
964 wl_resource_get_user_data(resource);
965 struct weston_surface *wsurface =
966 weston_desktop_surface_get_surface(dsurface);
967 struct weston_desktop_xdg_popup *popup =
968 weston_desktop_surface_get_implementation_data(dsurface);
969 struct weston_desktop_surface *parent_surface =
970 wl_resource_get_user_data(parent_resource);
971 struct weston_desktop_xdg_surface *parent =
972 weston_desktop_surface_get_implementation_data(parent_surface);
973 struct weston_desktop_xdg_positioner *positioner =
974 wl_resource_get_user_data(positioner_resource);
975
Sjoerd Simonsbe8a6d32016-09-23 09:31:23 +0200976 /* Checking whether the size and anchor rect both have a positive size
977 * is enough to verify both have been correctly set */
978 if (positioner->size.width == 0 || positioner->anchor_rect.width == 0) {
979 wl_resource_post_error(resource,
980 ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
981 "positioner object is not complete");
982 return;
983 }
984
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +0200985 if (weston_surface_set_role(wsurface, weston_desktop_xdg_popup_role,
986 resource, ZXDG_SHELL_V6_ERROR_ROLE) < 0)
987 return;
988
989 popup->resource =
990 weston_desktop_surface_add_resource(popup->base.desktop_surface,
991 &zxdg_popup_v6_interface,
992 &weston_desktop_xdg_popup_implementation,
993 id, weston_desktop_xdg_popup_resource_destroy);
994 if (popup->resource == NULL)
995 return;
996
997 popup->base.role = WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP;
998 popup->parent = parent;
999
1000 popup->geometry =
1001 weston_desktop_xdg_positioner_get_geometry(positioner,
1002 dsurface,
1003 parent_surface);
1004
1005 weston_desktop_surface_set_relative_to(popup->base.desktop_surface,
1006 parent_surface,
1007 popup->geometry.x,
1008 popup->geometry.y,
1009 true);
1010}
1011
1012static bool
1013weston_desktop_xdg_surface_check_role(struct weston_desktop_xdg_surface *surface)
1014{
1015 struct weston_surface *wsurface =
1016 weston_desktop_surface_get_surface(surface->desktop_surface);
1017 const char *role;
1018
1019 role = weston_surface_get_role(wsurface);
1020 if (role != NULL &&
1021 (role == weston_desktop_xdg_toplevel_role ||
1022 role == weston_desktop_xdg_popup_role))
1023 return true;
1024
1025 wl_resource_post_error(surface->resource,
1026 ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
1027 "xdg_surface must have a role");
1028 return false;
1029}
1030
1031static void
1032weston_desktop_xdg_surface_protocol_set_window_geometry(struct wl_client *wl_client,
1033 struct wl_resource *resource,
1034 int32_t x, int32_t y,
1035 int32_t width, int32_t height)
1036{
1037 struct weston_desktop_surface *dsurface =
1038 wl_resource_get_user_data(resource);
1039 struct weston_desktop_xdg_surface *surface =
1040 weston_desktop_surface_get_implementation_data(dsurface);
1041
1042 if (!weston_desktop_xdg_surface_check_role(surface))
1043 return;
1044
1045 surface->has_next_geometry = true;
1046 surface->next_geometry.x = x;
1047 surface->next_geometry.y = y;
1048 surface->next_geometry.width = width;
1049 surface->next_geometry.height = height;
1050}
1051
1052static void
1053weston_desktop_xdg_surface_protocol_ack_configure(struct wl_client *wl_client,
1054 struct wl_resource *resource,
1055 uint32_t serial)
1056{
1057 struct weston_desktop_surface *dsurface =
1058 wl_resource_get_user_data(resource);
1059 struct weston_desktop_xdg_surface *surface =
1060 weston_desktop_surface_get_implementation_data(dsurface);
1061
1062 if (!weston_desktop_xdg_surface_check_role(surface))
1063 return;
1064
1065 if (surface->configure_serial != serial)
1066 return;
1067
1068 surface->configured = true;
1069
1070 switch (surface->role) {
1071 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
1072 assert(0 && "not reached");
1073 break;
1074 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
1075 weston_desktop_xdg_toplevel_ack_configure((struct weston_desktop_xdg_toplevel *) surface);
1076 break;
1077 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
1078 break;
1079 }
1080}
1081
1082static void
1083weston_desktop_xdg_surface_ping(struct weston_desktop_surface *dsurface,
1084 uint32_t serial, void *user_data)
1085{
1086 struct weston_desktop_client *client =
1087 weston_desktop_surface_get_client(dsurface);
1088
1089 zxdg_shell_v6_send_ping(weston_desktop_client_get_resource(client),
1090 serial);
1091}
1092
1093static void
1094weston_desktop_xdg_surface_committed(struct weston_desktop_surface *dsurface,
Quentin Glidic003da882016-08-15 12:21:39 +02001095 void *user_data,
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02001096 int32_t sx, int32_t sy)
1097{
1098 struct weston_desktop_xdg_surface *surface = user_data;
Quentin Glidiccba26e72016-08-15 12:20:22 +02001099 struct weston_surface *wsurface =
1100 weston_desktop_surface_get_surface (dsurface);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02001101
Quentin Glidiccba26e72016-08-15 12:20:22 +02001102 if (wsurface->buffer_ref.buffer && !surface->configured) {
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02001103 wl_resource_post_error(surface->resource,
1104 ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
1105 "xdg_surface has never been configured");
1106 return;
1107 }
1108
1109 if (surface->has_next_geometry) {
1110 surface->has_next_geometry = false;
1111 weston_desktop_surface_set_geometry(surface->desktop_surface,
1112 surface->next_geometry);
1113 }
1114
1115 switch (surface->role) {
1116 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
1117 wl_resource_post_error(surface->resource,
1118 ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
1119 "xdg_surface must have a role");
1120 break;
1121 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
Quentin Glidiccba26e72016-08-15 12:20:22 +02001122 weston_desktop_xdg_toplevel_committed((struct weston_desktop_xdg_toplevel *) surface, sx, sy);
Quentin Glidic9c5dd7e2016-08-12 10:41:37 +02001123 break;
1124 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
1125 weston_desktop_xdg_popup_committed((struct weston_desktop_xdg_popup *) surface);
1126 break;
1127 }
1128}
1129
1130static void
1131weston_desktop_xdg_surface_close(struct weston_desktop_surface *dsurface,
1132 void *user_data)
1133{
1134 struct weston_desktop_xdg_surface *surface = user_data;
1135
1136 switch (surface->role) {
1137 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
1138 assert(0 && "not reached");
1139 break;
1140 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
1141 weston_desktop_xdg_toplevel_close((struct weston_desktop_xdg_toplevel *) surface);
1142 break;
1143 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
1144 weston_desktop_xdg_popup_close((struct weston_desktop_xdg_popup *) surface);
1145 break;
1146 }
1147}
1148
1149static void
1150weston_desktop_xdg_surface_destroy(struct weston_desktop_surface *dsurface,
1151 void *user_data)
1152{
1153 struct weston_desktop_xdg_surface *surface = user_data;
1154
1155 switch (surface->role) {
1156 case WESTON_DESKTOP_XDG_SURFACE_ROLE_NONE:
1157 break;
1158 case WESTON_DESKTOP_XDG_SURFACE_ROLE_TOPLEVEL:
1159 weston_desktop_xdg_toplevel_destroy((struct weston_desktop_xdg_toplevel *) surface);
1160 break;
1161 case WESTON_DESKTOP_XDG_SURFACE_ROLE_POPUP:
1162 weston_desktop_xdg_popup_destroy((struct weston_desktop_xdg_popup *) surface);
1163 break;
1164 }
1165
1166 if (surface->configure_idle != NULL)
1167 wl_event_source_remove(surface->configure_idle);
1168
1169 free(surface);
1170}
1171
1172static const struct zxdg_surface_v6_interface weston_desktop_xdg_surface_implementation = {
1173 .destroy = weston_desktop_destroy_request,
1174 .get_toplevel = weston_desktop_xdg_surface_protocol_get_toplevel,
1175 .get_popup = weston_desktop_xdg_surface_protocol_get_popup,
1176 .set_window_geometry = weston_desktop_xdg_surface_protocol_set_window_geometry,
1177 .ack_configure = weston_desktop_xdg_surface_protocol_ack_configure,
1178};
1179
1180static const struct weston_desktop_surface_implementation weston_desktop_xdg_surface_internal_implementation = {
1181 /* These are used for toplevel only */
1182 .set_maximized = weston_desktop_xdg_toplevel_set_maximized,
1183 .set_fullscreen = weston_desktop_xdg_toplevel_set_fullscreen,
1184 .set_resizing = weston_desktop_xdg_toplevel_set_resizing,
1185 .set_activated = weston_desktop_xdg_toplevel_set_activated,
1186 .set_size = weston_desktop_xdg_toplevel_set_size,
1187
1188 .get_maximized = weston_desktop_xdg_toplevel_get_maximized,
1189 .get_fullscreen = weston_desktop_xdg_toplevel_get_fullscreen,
1190 .get_resizing = weston_desktop_xdg_toplevel_get_resizing,
1191 .get_activated = weston_desktop_xdg_toplevel_get_activated,
1192
1193 /* These are used for popup only */
1194 .update_position = weston_desktop_xdg_popup_update_position,
1195
1196 /* Common API */
1197 .committed = weston_desktop_xdg_surface_committed,
1198 .ping = weston_desktop_xdg_surface_ping,
1199 .close = weston_desktop_xdg_surface_close,
1200
1201 .destroy = weston_desktop_xdg_surface_destroy,
1202};
1203
1204static void
1205weston_desktop_xdg_shell_protocol_create_positioner(struct wl_client *wl_client,
1206 struct wl_resource *resource,
1207 uint32_t id)
1208{
1209 struct weston_desktop_client *client =
1210 wl_resource_get_user_data(resource);
1211 struct weston_desktop_xdg_positioner *positioner;
1212
1213 positioner = zalloc(sizeof(struct weston_desktop_xdg_positioner));
1214 if (positioner == NULL) {
1215 wl_client_post_no_memory(wl_client);
1216 return;
1217 }
1218
1219 positioner->client = client;
1220 positioner->desktop = weston_desktop_client_get_desktop(positioner->client);
1221
1222 positioner->resource =
1223 wl_resource_create(wl_client,
1224 &zxdg_positioner_v6_interface,
1225 wl_resource_get_version(resource), id);
1226 if (positioner->resource == NULL) {
1227 wl_client_post_no_memory(wl_client);
1228 free(positioner);
1229 return;
1230 }
1231 wl_resource_set_implementation(positioner->resource,
1232 &weston_desktop_xdg_positioner_implementation,
1233 positioner, weston_desktop_xdg_positioner_destroy);
1234}
1235
1236static void
1237weston_desktop_xdg_surface_resource_destroy(struct wl_resource *resource)
1238{
1239 struct weston_desktop_surface *dsurface =
1240 wl_resource_get_user_data(resource);
1241
1242 if (dsurface != NULL)
1243 weston_desktop_surface_resource_destroy(resource);
1244}
1245
1246static void
1247weston_desktop_xdg_shell_protocol_get_xdg_surface(struct wl_client *wl_client,
1248 struct wl_resource *resource,
1249 uint32_t id,
1250 struct wl_resource *surface_resource)
1251{
1252 struct weston_desktop_client *client =
1253 wl_resource_get_user_data(resource);
1254 struct weston_surface *wsurface =
1255 wl_resource_get_user_data(surface_resource);
1256 struct weston_desktop_xdg_surface *surface;
1257
1258 surface = zalloc(weston_desktop_surface_role_biggest_size);
1259 if (surface == NULL) {
1260 wl_client_post_no_memory(wl_client);
1261 return;
1262 }
1263
1264 surface->desktop = weston_desktop_client_get_desktop(client);
1265 surface->surface = wsurface;
1266
1267 surface->desktop_surface =
1268 weston_desktop_surface_create(surface->desktop, client,
1269 surface->surface,
1270 &weston_desktop_xdg_surface_internal_implementation,
1271 surface);
1272 if (surface->desktop_surface == NULL) {
1273 free(surface);
1274 return;
1275 }
1276
1277 surface->resource =
1278 weston_desktop_surface_add_resource(surface->desktop_surface,
1279 &zxdg_surface_v6_interface,
1280 &weston_desktop_xdg_surface_implementation,
1281 id, weston_desktop_xdg_surface_resource_destroy);
1282 if (surface->resource == NULL)
1283 return;
1284
1285 if (wsurface->buffer_ref.buffer != NULL) {
1286 wl_resource_post_error(surface->resource,
1287 ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
1288 "xdg_surface must not have a buffer at creation");
1289 return;
1290 }
1291}
1292
1293static void
1294weston_desktop_xdg_shell_protocol_pong(struct wl_client *wl_client,
1295 struct wl_resource *resource,
1296 uint32_t serial)
1297{
1298 struct weston_desktop_client *client =
1299 wl_resource_get_user_data(resource);
1300
1301 weston_desktop_client_pong(client, serial);
1302}
1303
1304static const struct zxdg_shell_v6_interface weston_desktop_xdg_shell_implementation = {
1305 .destroy = weston_desktop_destroy_request,
1306 .create_positioner = weston_desktop_xdg_shell_protocol_create_positioner,
1307 .get_xdg_surface = weston_desktop_xdg_shell_protocol_get_xdg_surface,
1308 .pong = weston_desktop_xdg_shell_protocol_pong,
1309};
1310
1311static void
1312weston_desktop_xdg_shell_bind(struct wl_client *client, void *data,
1313 uint32_t version, uint32_t id)
1314{
1315 struct weston_desktop *desktop = data;
1316
1317 weston_desktop_client_create(desktop, client, NULL,
1318 &zxdg_shell_v6_interface,
1319 &weston_desktop_xdg_shell_implementation,
1320 version, id);
1321}
1322
1323struct wl_global *
1324weston_desktop_xdg_shell_v6_create(struct weston_desktop *desktop, struct wl_display *display)
1325{
1326 return wl_global_create(display, &zxdg_shell_v6_interface,
1327 WD_XDG_SHELL_PROTOCOL_VERSION, desktop,
1328 weston_desktop_xdg_shell_bind);
1329}