blob: d3be9364089d114f3b32f48bde90b51fba79e959 [file] [log] [blame]
Quentin Glidic248dd102016-08-12 10:41:34 +02001/*
2 * Copyright © 2016 Quentin "Sardem FF7" Glidic
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "config.h"
25
26#include <string.h>
27#include <assert.h>
28
29#include <wayland-server.h>
30
31#include "compositor.h"
32#include "zalloc.h"
33
34#include "libweston-desktop.h"
35#include "internal.h"
36
37struct weston_desktop_view {
38 struct wl_list link;
39 struct weston_view *view;
40 struct weston_desktop_view *parent;
41 struct wl_list children_list;
42 struct wl_list children_link;
43};
44
45struct weston_desktop_surface {
46 struct weston_desktop *desktop;
47 struct weston_desktop_client *client;
48 struct wl_list client_link;
49 const struct weston_desktop_surface_implementation *implementation;
50 void *implementation_data;
51 void *user_data;
52 struct weston_surface *surface;
53 struct wl_list view_list;
Quentin Glidic003da882016-08-15 12:21:39 +020054 struct weston_position buffer_move;
Quentin Glidic248dd102016-08-12 10:41:34 +020055 struct wl_listener surface_commit_listener;
56 struct wl_listener surface_destroy_listener;
57 struct wl_listener client_destroy_listener;
58 struct wl_list children_list;
59
60 struct wl_list resource_list;
61 bool has_geometry;
62 struct weston_geometry geometry;
63 struct {
64 char *title;
65 char *app_id;
66 pid_t pid;
67 };
68 struct {
69 struct weston_desktop_surface *parent;
70 struct wl_list children_link;
71 struct weston_position position;
72 bool use_geometry;
73 };
74 struct {
75 struct wl_list grab_link;
76 };
77};
78
79static void
80weston_desktop_surface_update_view_position(struct weston_desktop_surface *surface)
81{
82 struct weston_desktop_view *view;
83 int32_t x, y;
84
85 x = surface->position.x;
86 y = surface->position.y;
87
88 if (surface->use_geometry) {
89 struct weston_desktop_surface *parent =
90 weston_desktop_surface_get_parent(surface);
91 struct weston_geometry geometry, parent_geometry;
92
93 geometry = weston_desktop_surface_get_geometry(surface);
94 parent_geometry = weston_desktop_surface_get_geometry(parent);
95
96 x += parent_geometry.x - geometry.x;
97 y += parent_geometry.y - geometry.y;
98 }
99 wl_list_for_each(view, &surface->view_list, link)
100 weston_view_set_position(view->view, x, y);
101}
102
103
104static void
105weston_desktop_view_propagate_layer(struct weston_desktop_view *view);
106
107static void
Quentin Glidic248dd102016-08-12 10:41:34 +0200108weston_desktop_view_destroy(struct weston_desktop_view *view)
109{
110 struct weston_desktop_view *child_view, *tmp;
111
112 wl_list_for_each_safe(child_view, tmp, &view->children_list, children_link)
113 weston_desktop_view_destroy(child_view);
114
115 wl_list_remove(&view->children_link);
116 wl_list_remove(&view->link);
117
118 weston_view_damage_below(view->view);
119 if (view->parent != NULL)
120 weston_view_destroy(view->view);
121
122 free(view);
123}
124
125void
126weston_desktop_surface_destroy(struct weston_desktop_surface *surface)
127{
128 struct weston_desktop_view *view, *next_view;
129 struct weston_desktop_surface *child, *next_child;
130
131 wl_list_remove(&surface->surface_commit_listener.link);
132 wl_list_remove(&surface->surface_destroy_listener.link);
133 wl_list_remove(&surface->client_destroy_listener.link);
134
135 if (!wl_list_empty(&surface->resource_list)) {
136 struct wl_resource *resource, *tmp;
137 wl_resource_for_each_safe(resource, tmp, &surface->resource_list) {
138 wl_resource_set_user_data(resource, NULL);
139 wl_list_remove(wl_resource_get_link(resource));
140 }
141 }
142
143 surface->implementation->destroy(surface, surface->implementation_data);
144
145 surface->surface->committed = NULL;
146 surface->surface->committed_private = NULL;
147
148 weston_desktop_surface_unset_relative_to(surface);
149 wl_list_remove(&surface->client_link);
150
151 wl_list_for_each_safe(child, next_child,
152 &surface->children_list,
153 children_link)
154 weston_desktop_surface_unset_relative_to(child);
155
156 wl_list_for_each_safe(view, next_view, &surface->view_list, link)
157 weston_desktop_view_destroy(view);
158
159 free(surface->title);
160 free(surface->app_id);
161
162 free(surface);
163}
164
165static void
166weston_desktop_surface_surface_committed(struct wl_listener *listener,
167 void *data)
168{
169 struct weston_desktop_surface *surface =
170 wl_container_of(listener, surface, surface_commit_listener);
171
Quentin Glidic003da882016-08-15 12:21:39 +0200172 if (surface->implementation->committed != NULL)
173 surface->implementation->committed(surface,
174 surface->implementation_data,
175 surface->buffer_move.x,
176 surface->buffer_move.y);
177
178 if (surface->parent != NULL) {
179 struct weston_desktop_view *view;
180
181 wl_list_for_each(view, &surface->view_list, link) {
182 weston_view_set_transform_parent(view->view,
183 view->parent->view);
184 weston_desktop_view_propagate_layer(view->parent);
185 }
186 weston_desktop_surface_update_view_position(surface);
187 }
188
189 if (!wl_list_empty(&surface->children_list)) {
190 struct weston_desktop_surface *child;
191
192 wl_list_for_each(child, &surface->children_list, children_link)
193 weston_desktop_surface_update_view_position(child);
194 }
195
196 surface->buffer_move.x = 0;
197 surface->buffer_move.y = 0;
Quentin Glidic248dd102016-08-12 10:41:34 +0200198}
199
200static void
201weston_desktop_surface_surface_destroyed(struct wl_listener *listener,
202 void *data)
203{
204 struct weston_desktop_surface *surface =
205 wl_container_of(listener, surface, surface_destroy_listener);
206
207 weston_desktop_surface_destroy(surface);
208}
209
210void
211weston_desktop_surface_resource_destroy(struct wl_resource *resource)
212{
213 struct weston_desktop_surface *surface =
214 wl_resource_get_user_data(resource);
215
216 if (surface != NULL)
217 weston_desktop_surface_destroy(surface);
218}
219
220static void
221weston_desktop_surface_committed(struct weston_surface *wsurface,
222 int32_t sx, int32_t sy)
223{
224 struct weston_desktop_surface *surface = wsurface->committed_private;
225
Quentin Glidic003da882016-08-15 12:21:39 +0200226 surface->buffer_move.x = sx;
227 surface->buffer_move.y = sy;
Quentin Glidic248dd102016-08-12 10:41:34 +0200228}
229
230static void
231weston_desktop_surface_client_destroyed(struct wl_listener *listener,
232 void *data)
233{
234 struct weston_desktop_surface *surface =
235 wl_container_of(listener, surface, client_destroy_listener);
236
237 weston_desktop_surface_destroy(surface);
238}
239
240struct weston_desktop_surface *
241weston_desktop_surface_create(struct weston_desktop *desktop,
242 struct weston_desktop_client *client,
243 struct weston_surface *wsurface,
244 const struct weston_desktop_surface_implementation *implementation,
245 void *implementation_data)
246{
247 assert(implementation->destroy != NULL);
248
249 struct weston_desktop_surface *surface;
250
251 surface = zalloc(sizeof(struct weston_desktop_surface));
252 if (surface == NULL) {
253 if (client != NULL)
254 wl_client_post_no_memory(weston_desktop_client_get_client(client));
255 return NULL;
256 }
257
258 surface->desktop = desktop;
259 surface->implementation = implementation;
260 surface->implementation_data = implementation_data;
261 surface->surface = wsurface;
262
263 surface->client = client;
264 surface->client_destroy_listener.notify =
265 weston_desktop_surface_client_destroyed;
266 weston_desktop_client_add_destroy_listener(
267 client, &surface->client_destroy_listener);
268
269 wsurface->committed = weston_desktop_surface_committed;
270 wsurface->committed_private = surface;
271
Giulio Camuffof15320f2016-12-08 09:21:08 +0100272 surface->pid = -1;
273
Quentin Glidic248dd102016-08-12 10:41:34 +0200274 surface->surface_commit_listener.notify =
275 weston_desktop_surface_surface_committed;
276 wl_signal_add(&surface->surface->commit_signal,
277 &surface->surface_commit_listener);
278 surface->surface_destroy_listener.notify =
279 weston_desktop_surface_surface_destroyed;
280 wl_signal_add(&surface->surface->destroy_signal,
281 &surface->surface_destroy_listener);
282
283 wl_list_init(&surface->client_link);
284 wl_list_init(&surface->resource_list);
285 wl_list_init(&surface->children_list);
286 wl_list_init(&surface->children_link);
287 wl_list_init(&surface->view_list);
288 wl_list_init(&surface->grab_link);
289
290 return surface;
291}
292
293struct wl_resource *
294weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
295 const struct wl_interface *interface,
296 const void *implementation, uint32_t id,
297 wl_resource_destroy_func_t destroy)
298{
299 struct wl_resource *client_resource =
300 weston_desktop_client_get_resource(surface->client);
301 struct wl_client *wl_client =
302 weston_desktop_client_get_client(surface->client);
303 struct wl_resource *resource;
304
305 resource = wl_resource_create(wl_client,
306 interface,
307 wl_resource_get_version(client_resource),
308 id);
309 if (resource == NULL) {
310 wl_client_post_no_memory(wl_client);
311 weston_desktop_surface_destroy(surface);
312 return NULL;
313 }
314 if (destroy == NULL)
315 destroy = weston_desktop_surface_resource_destroy;
316 wl_resource_set_implementation(resource, implementation, surface, destroy);
317 wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
318
319 return resource;
320}
321
322struct weston_desktop_surface *
323weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
324{
325 struct weston_desktop_surface *surface =
326 wl_container_of(grab_link, surface, grab_link);
327
328 return surface;
329}
330
331WL_EXPORT bool
332weston_surface_is_desktop_surface(struct weston_surface *wsurface)
333{
334 return wsurface->committed == weston_desktop_surface_committed;
335}
336
337WL_EXPORT struct weston_desktop_surface *
338weston_surface_get_desktop_surface(struct weston_surface *wsurface)
339{
340 if (!weston_surface_is_desktop_surface(wsurface))
341 return NULL;
342 return wsurface->committed_private;
343}
344
345WL_EXPORT void
346weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
347 void *user_data)
348{
349 surface->user_data = user_data;
350}
351
352static struct weston_desktop_view *
353weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
354{
355 struct wl_client *wl_client=
356 weston_desktop_client_get_client(surface->client);
357 struct weston_desktop_view *view, *child_view;
358 struct weston_view *wview;
359 struct weston_desktop_surface *child;
360
361 wview = weston_view_create(surface->surface);
362 if (wview == NULL) {
363 if (wl_client != NULL)
364 wl_client_post_no_memory(wl_client);
365 return NULL;
366 }
367
368 view = zalloc(sizeof(struct weston_desktop_view));
369 if (view == NULL) {
370 if (wl_client != NULL)
371 wl_client_post_no_memory(wl_client);
372 return NULL;
373 }
374
375 view->view = wview;
376 wl_list_init(&view->children_list);
377 wl_list_init(&view->children_link);
378 wl_list_insert(surface->view_list.prev, &view->link);
379
380 wl_list_for_each(child, &surface->children_list, children_link) {
381 child_view =
382 weston_desktop_surface_create_desktop_view(child);
383 if (child_view == NULL) {
384 weston_desktop_view_destroy(view);
385 return NULL;
386 }
387
388 child_view->parent = view;
389 wl_list_insert(view->children_list.prev,
390 &child_view->children_link);
391 }
392
393 return view;
394}
395
396WL_EXPORT struct weston_view *
397weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
398{
399 struct weston_desktop_view *view;
400
401 view = weston_desktop_surface_create_desktop_view(surface);
402 if (view == NULL)
403 return NULL;
404
405 return view->view;
406}
407
408WL_EXPORT void
Quentin Glidicf01ecee2016-08-16 10:52:46 +0200409weston_desktop_surface_unlink_view(struct weston_view *wview)
Quentin Glidic248dd102016-08-12 10:41:34 +0200410{
411 struct weston_desktop_surface *surface;
412 struct weston_desktop_view *view;
413
414 if (!weston_surface_is_desktop_surface(wview->surface))
415 return;
416
417 surface = weston_surface_get_desktop_surface(wview->surface);
418 wl_list_for_each(view, &surface->view_list, link) {
419 if (view->view == wview) {
420 weston_desktop_view_destroy(view);
421 return;
422 }
423 }
424}
425
426static void
427weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
428{
429 struct weston_desktop_view *child;
430 struct wl_list *link = &view->view->layer_link.link;
431
432 wl_list_for_each_reverse(child, &view->children_list, children_link) {
433 struct weston_layer_entry *prev =
434 wl_container_of(link->prev, prev, link);
435
436 if (prev == &child->view->layer_link)
437 continue;
438
439 child->view->is_mapped = true;
440 weston_view_damage_below(child->view);
441 weston_view_geometry_dirty(child->view);
442 weston_layer_entry_remove(&child->view->layer_link);
443 weston_layer_entry_insert(prev, &child->view->layer_link);
444 weston_view_geometry_dirty(child->view);
445 weston_surface_damage(child->view->surface);
446 weston_view_update_transform(child->view);
447
448 weston_desktop_view_propagate_layer(child);
449 }
450}
451
452WL_EXPORT void
453weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
454{
455 struct weston_desktop_view *view;
456
457 wl_list_for_each(view, &surface->view_list, link)
458 weston_desktop_view_propagate_layer(view);
459}
460
461WL_EXPORT void
462weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
463{
464 if (surface->implementation->set_activated != NULL)
465 surface->implementation->set_activated(surface,
466 surface->implementation_data,
467 activated);
468}
469
470WL_EXPORT void
471weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
472{
473 if (surface->implementation->set_fullscreen != NULL)
474 surface->implementation->set_fullscreen(surface,
475 surface->implementation_data,
476 fullscreen);
477}
478
479WL_EXPORT void
480weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
481{
482 if (surface->implementation->set_maximized != NULL)
483 surface->implementation->set_maximized(surface,
484 surface->implementation_data,
485 maximized);
486}
487
488WL_EXPORT void
489weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
490{
491 if (surface->implementation->set_resizing != NULL)
492 surface->implementation->set_resizing(surface,
493 surface->implementation_data,
494 resizing);
495}
496
497WL_EXPORT void
498weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
499{
500 if (surface->implementation->set_size != NULL)
501 surface->implementation->set_size(surface,
502 surface->implementation_data,
503 width, height);
504}
505
506WL_EXPORT void
507weston_desktop_surface_close(struct weston_desktop_surface *surface)
508{
509 if (surface->implementation->close != NULL)
510 surface->implementation->close(surface,
511 surface->implementation_data);
512}
513
514struct weston_desktop_surface *
515weston_desktop_surface_from_client_link(struct wl_list *link)
516{
517 struct weston_desktop_surface *surface;
518
519 surface = wl_container_of(link, surface, client_link);
520 return surface;
521}
522
523struct wl_list *
524weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
525{
526 return &surface->client_link;
527}
528
529bool
530weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
531 const struct weston_desktop_surface_implementation *implementation)
532{
533 return surface->implementation == implementation;
534}
535
536const struct weston_desktop_surface_implementation *
537weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
538{
539 return surface->implementation;
540}
541
542void *
543weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
544{
545 return surface->implementation_data;
546}
547
548struct weston_desktop_surface *
549weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
550{
551 return surface->parent;
552}
553
554bool
555weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
556{
557 return !wl_list_empty(&surface->grab_link);
558}
559
560WL_EXPORT struct weston_desktop_client *
561weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
562{
563 return surface->client;
564}
565
566WL_EXPORT void *
567weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
568{
569 return surface->user_data;
570}
571
572WL_EXPORT struct weston_surface *
573weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
574{
575 return surface->surface;
576}
577
578WL_EXPORT const char *
579weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
580{
581 return surface->title;
582}
583
584WL_EXPORT const char *
585weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
586{
587 return surface->app_id;
588}
589
590WL_EXPORT pid_t
591weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
592{
593 pid_t pid;
594
Giulio Camuffof15320f2016-12-08 09:21:08 +0100595 if (surface->pid != -1) {
Quentin Glidic248dd102016-08-12 10:41:34 +0200596 pid = surface->pid;
597 } else {
598 struct weston_desktop_client *client =
599 weston_desktop_surface_get_client(surface);
600 struct wl_client *wl_client =
601 weston_desktop_client_get_client(client);
602
Giulio Camuffof15320f2016-12-08 09:21:08 +0100603 /* wl_client should always be valid, because only in the
604 * xwayland case it wouldn't be, but in that case we won't
605 * reach here, as the pid is initialized to 0. */
606 assert(wl_client);
Quentin Glidic248dd102016-08-12 10:41:34 +0200607 wl_client_get_credentials(wl_client, &pid, NULL, NULL);
608 }
609 return pid;
610}
611
612WL_EXPORT bool
613weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
614{
615 if (surface->implementation->get_activated == NULL)
616 return false;
617 return surface->implementation->get_activated(surface,
618 surface->implementation_data);
619}
620
621WL_EXPORT bool
622weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
623{
624 if (surface->implementation->get_resizing == NULL)
625 return false;
626 return surface->implementation->get_resizing(surface,
627 surface->implementation_data);
628}
629
630WL_EXPORT bool
631weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
632{
633 if (surface->implementation->get_maximized == NULL)
634 return false;
635 return surface->implementation->get_maximized(surface,
636 surface->implementation_data);
637}
638
639WL_EXPORT bool
640weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
641{
642 if (surface->implementation->get_fullscreen == NULL)
643 return false;
644 return surface->implementation->get_fullscreen(surface,
645 surface->implementation_data);
646}
647
648WL_EXPORT struct weston_geometry
649weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface)
650{
651 if (surface->has_geometry)
652 return surface->geometry;
653 return weston_surface_get_bounding_box(surface->surface);
654}
655
656WL_EXPORT struct weston_size
657weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface)
658{
659 struct weston_size size = { 0, 0 };
660
661 if (surface->implementation->get_max_size == NULL)
662 return size;
663 return surface->implementation->get_max_size(surface,
664 surface->implementation_data);
665}
666
667WL_EXPORT struct weston_size
668weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
669{
670 struct weston_size size = { 0, 0 };
671
672 if (surface->implementation->get_min_size == NULL)
673 return size;
674 return surface->implementation->get_min_size(surface,
675 surface->implementation_data);
676}
677
678void
679weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
680 const char *title)
681{
682 char *tmp;
683
684 tmp = strdup(title);
685 if (tmp == NULL)
686 return;
687
688 free(surface->title);
689 surface->title = tmp;
690}
691
692void
693weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
694 const char *app_id)
695{
696 char *tmp;
697
698 tmp = strdup(app_id);
699 if (tmp == NULL)
700 return;
701
702 free(surface->app_id);
703 surface->app_id = tmp;
704}
705
706void
707weston_desktop_surface_set_pid(struct weston_desktop_surface *surface,
708 pid_t pid)
709{
710 surface->pid = pid;
711}
712
713void
714weston_desktop_surface_set_geometry(struct weston_desktop_surface *surface,
715 struct weston_geometry geometry)
716{
717 surface->has_geometry = true;
718 surface->geometry = geometry;
719}
720
721void
722weston_desktop_surface_set_relative_to(struct weston_desktop_surface *surface,
723 struct weston_desktop_surface *parent,
724 int32_t x, int32_t y, bool use_geometry)
725{
726 struct weston_desktop_view *view, *parent_view;
727 struct wl_list *link, *tmp;
728
729 assert(parent);
730
731 surface->position.x = x;
732 surface->position.y = y;
733 surface->use_geometry = use_geometry;
734
735 if (surface->parent == parent)
736 return;
737
738 surface->parent = parent;
739 wl_list_remove(&surface->children_link);
740 wl_list_insert(surface->parent->children_list.prev,
741 &surface->children_link);
742
743 link = surface->view_list.next;
744 tmp = link->next;
745 wl_list_for_each(parent_view, &parent->view_list, link) {
746 if (link == &surface->view_list) {
747 view = weston_desktop_surface_create_desktop_view(surface);
748 if (view == NULL)
749 return;
750 tmp = &surface->view_list;
751 } else {
752 view = wl_container_of(link, view, link);
753 wl_list_remove(&view->children_link);
754 }
755
756 view->parent = parent_view;
757 wl_list_insert(parent_view->children_list.prev,
758 &view->children_link);
759 weston_desktop_view_propagate_layer(view);
760
761 link = tmp;
762 tmp = link->next;
763 }
764 for (; link != &surface->view_list; link = tmp, tmp = link->next) {
765 view = wl_container_of(link, view, link);
766 weston_desktop_view_destroy(view);
767 }
768}
769
770void
771weston_desktop_surface_unset_relative_to(struct weston_desktop_surface *surface)
772{
773 struct weston_desktop_view *view, *tmp;
774
775 if (surface->parent == NULL)
776 return;
777
778 surface->parent = NULL;
779 wl_list_remove(&surface->children_link);
780 wl_list_init(&surface->children_link);
781
782 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
783 weston_desktop_view_destroy(view);
784}
785
786void
787weston_desktop_surface_popup_grab(struct weston_desktop_surface *surface,
788 struct weston_desktop_seat *seat,
789 uint32_t serial)
790{
791 struct wl_client *wl_client =
792 weston_desktop_client_get_client(surface->client);
793 if (weston_desktop_seat_popup_grab_start(seat, wl_client, serial))
794 weston_desktop_seat_popup_grab_add_surface(seat, &surface->grab_link);
795 else
796 weston_desktop_surface_popup_dismiss(surface);
797}
798
799void
800weston_desktop_surface_popup_ungrab(struct weston_desktop_surface *surface,
801 struct weston_desktop_seat *seat)
802{
803 weston_desktop_seat_popup_grab_remove_surface(seat, &surface->grab_link);
804}
805
806void
807weston_desktop_surface_popup_dismiss(struct weston_desktop_surface *surface)
808{
809 struct weston_desktop_view *view, *tmp;
810
811 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
812 weston_desktop_view_destroy(view);
813 wl_list_remove(&surface->grab_link);
814 wl_list_init(&surface->grab_link);
815 weston_desktop_surface_close(surface);
816}