blob: bdf6dbc1beffb9d4022219320bf725d1b3d8cc6e [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;
54 bool has_new_buffer;
55 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
108weston_desktop_surface_committed_common(struct weston_desktop_surface *surface,
109 bool new_buffer, int32_t sx, int32_t sy)
110{
111 if (surface->implementation->committed != NULL)
112 surface->implementation->committed(surface,
113 surface->implementation_data,
114 new_buffer, sx, sy);
115
116 if (surface->parent != NULL) {
117 struct weston_desktop_view *view;
118
119 wl_list_for_each(view, &surface->view_list, link) {
120 weston_view_set_transform_parent(view->view,
121 view->parent->view);
122 weston_desktop_view_propagate_layer(view->parent);
123 }
124 weston_desktop_surface_update_view_position(surface);
125 }
126
127 if (!wl_list_empty(&surface->children_list)) {
128 struct weston_desktop_surface *child;
129
130 wl_list_for_each(child, &surface->children_list, children_link)
131 weston_desktop_surface_update_view_position(child);
132 }
133}
134
135static void
136weston_desktop_view_destroy(struct weston_desktop_view *view)
137{
138 struct weston_desktop_view *child_view, *tmp;
139
140 wl_list_for_each_safe(child_view, tmp, &view->children_list, children_link)
141 weston_desktop_view_destroy(child_view);
142
143 wl_list_remove(&view->children_link);
144 wl_list_remove(&view->link);
145
146 weston_view_damage_below(view->view);
147 if (view->parent != NULL)
148 weston_view_destroy(view->view);
149
150 free(view);
151}
152
153void
154weston_desktop_surface_destroy(struct weston_desktop_surface *surface)
155{
156 struct weston_desktop_view *view, *next_view;
157 struct weston_desktop_surface *child, *next_child;
158
159 wl_list_remove(&surface->surface_commit_listener.link);
160 wl_list_remove(&surface->surface_destroy_listener.link);
161 wl_list_remove(&surface->client_destroy_listener.link);
162
163 if (!wl_list_empty(&surface->resource_list)) {
164 struct wl_resource *resource, *tmp;
165 wl_resource_for_each_safe(resource, tmp, &surface->resource_list) {
166 wl_resource_set_user_data(resource, NULL);
167 wl_list_remove(wl_resource_get_link(resource));
168 }
169 }
170
171 surface->implementation->destroy(surface, surface->implementation_data);
172
173 surface->surface->committed = NULL;
174 surface->surface->committed_private = NULL;
175
176 weston_desktop_surface_unset_relative_to(surface);
177 wl_list_remove(&surface->client_link);
178
179 wl_list_for_each_safe(child, next_child,
180 &surface->children_list,
181 children_link)
182 weston_desktop_surface_unset_relative_to(child);
183
184 wl_list_for_each_safe(view, next_view, &surface->view_list, link)
185 weston_desktop_view_destroy(view);
186
187 free(surface->title);
188 free(surface->app_id);
189
190 free(surface);
191}
192
193static void
194weston_desktop_surface_surface_committed(struct wl_listener *listener,
195 void *data)
196{
197 struct weston_desktop_surface *surface =
198 wl_container_of(listener, surface, surface_commit_listener);
199
200 if (surface->has_new_buffer)
201 surface->has_new_buffer = false;
202 else
203 weston_desktop_surface_committed_common(surface, false, 0, 0);
204}
205
206static void
207weston_desktop_surface_surface_destroyed(struct wl_listener *listener,
208 void *data)
209{
210 struct weston_desktop_surface *surface =
211 wl_container_of(listener, surface, surface_destroy_listener);
212
213 weston_desktop_surface_destroy(surface);
214}
215
216void
217weston_desktop_surface_resource_destroy(struct wl_resource *resource)
218{
219 struct weston_desktop_surface *surface =
220 wl_resource_get_user_data(resource);
221
222 if (surface != NULL)
223 weston_desktop_surface_destroy(surface);
224}
225
226static void
227weston_desktop_surface_committed(struct weston_surface *wsurface,
228 int32_t sx, int32_t sy)
229{
230 struct weston_desktop_surface *surface = wsurface->committed_private;
231
232 weston_desktop_surface_committed_common(surface, true, sx, sy);
233 surface->has_new_buffer = true;
234}
235
236static void
237weston_desktop_surface_client_destroyed(struct wl_listener *listener,
238 void *data)
239{
240 struct weston_desktop_surface *surface =
241 wl_container_of(listener, surface, client_destroy_listener);
242
243 weston_desktop_surface_destroy(surface);
244}
245
246struct weston_desktop_surface *
247weston_desktop_surface_create(struct weston_desktop *desktop,
248 struct weston_desktop_client *client,
249 struct weston_surface *wsurface,
250 const struct weston_desktop_surface_implementation *implementation,
251 void *implementation_data)
252{
253 assert(implementation->destroy != NULL);
254
255 struct weston_desktop_surface *surface;
256
257 surface = zalloc(sizeof(struct weston_desktop_surface));
258 if (surface == NULL) {
259 if (client != NULL)
260 wl_client_post_no_memory(weston_desktop_client_get_client(client));
261 return NULL;
262 }
263
264 surface->desktop = desktop;
265 surface->implementation = implementation;
266 surface->implementation_data = implementation_data;
267 surface->surface = wsurface;
268
269 surface->client = client;
270 surface->client_destroy_listener.notify =
271 weston_desktop_surface_client_destroyed;
272 weston_desktop_client_add_destroy_listener(
273 client, &surface->client_destroy_listener);
274
275 wsurface->committed = weston_desktop_surface_committed;
276 wsurface->committed_private = surface;
277
278 surface->surface_commit_listener.notify =
279 weston_desktop_surface_surface_committed;
280 wl_signal_add(&surface->surface->commit_signal,
281 &surface->surface_commit_listener);
282 surface->surface_destroy_listener.notify =
283 weston_desktop_surface_surface_destroyed;
284 wl_signal_add(&surface->surface->destroy_signal,
285 &surface->surface_destroy_listener);
286
287 wl_list_init(&surface->client_link);
288 wl_list_init(&surface->resource_list);
289 wl_list_init(&surface->children_list);
290 wl_list_init(&surface->children_link);
291 wl_list_init(&surface->view_list);
292 wl_list_init(&surface->grab_link);
293
294 return surface;
295}
296
297struct wl_resource *
298weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
299 const struct wl_interface *interface,
300 const void *implementation, uint32_t id,
301 wl_resource_destroy_func_t destroy)
302{
303 struct wl_resource *client_resource =
304 weston_desktop_client_get_resource(surface->client);
305 struct wl_client *wl_client =
306 weston_desktop_client_get_client(surface->client);
307 struct wl_resource *resource;
308
309 resource = wl_resource_create(wl_client,
310 interface,
311 wl_resource_get_version(client_resource),
312 id);
313 if (resource == NULL) {
314 wl_client_post_no_memory(wl_client);
315 weston_desktop_surface_destroy(surface);
316 return NULL;
317 }
318 if (destroy == NULL)
319 destroy = weston_desktop_surface_resource_destroy;
320 wl_resource_set_implementation(resource, implementation, surface, destroy);
321 wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
322
323 return resource;
324}
325
326struct weston_desktop_surface *
327weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
328{
329 struct weston_desktop_surface *surface =
330 wl_container_of(grab_link, surface, grab_link);
331
332 return surface;
333}
334
335WL_EXPORT bool
336weston_surface_is_desktop_surface(struct weston_surface *wsurface)
337{
338 return wsurface->committed == weston_desktop_surface_committed;
339}
340
341WL_EXPORT struct weston_desktop_surface *
342weston_surface_get_desktop_surface(struct weston_surface *wsurface)
343{
344 if (!weston_surface_is_desktop_surface(wsurface))
345 return NULL;
346 return wsurface->committed_private;
347}
348
349WL_EXPORT void
350weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
351 void *user_data)
352{
353 surface->user_data = user_data;
354}
355
356static struct weston_desktop_view *
357weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
358{
359 struct wl_client *wl_client=
360 weston_desktop_client_get_client(surface->client);
361 struct weston_desktop_view *view, *child_view;
362 struct weston_view *wview;
363 struct weston_desktop_surface *child;
364
365 wview = weston_view_create(surface->surface);
366 if (wview == NULL) {
367 if (wl_client != NULL)
368 wl_client_post_no_memory(wl_client);
369 return NULL;
370 }
371
372 view = zalloc(sizeof(struct weston_desktop_view));
373 if (view == NULL) {
374 if (wl_client != NULL)
375 wl_client_post_no_memory(wl_client);
376 return NULL;
377 }
378
379 view->view = wview;
380 wl_list_init(&view->children_list);
381 wl_list_init(&view->children_link);
382 wl_list_insert(surface->view_list.prev, &view->link);
383
384 wl_list_for_each(child, &surface->children_list, children_link) {
385 child_view =
386 weston_desktop_surface_create_desktop_view(child);
387 if (child_view == NULL) {
388 weston_desktop_view_destroy(view);
389 return NULL;
390 }
391
392 child_view->parent = view;
393 wl_list_insert(view->children_list.prev,
394 &child_view->children_link);
395 }
396
397 return view;
398}
399
400WL_EXPORT struct weston_view *
401weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
402{
403 struct weston_desktop_view *view;
404
405 view = weston_desktop_surface_create_desktop_view(surface);
406 if (view == NULL)
407 return NULL;
408
409 return view->view;
410}
411
412WL_EXPORT void
413weston_desktop_surface_destroy_view(struct weston_view *wview)
414{
415 struct weston_desktop_surface *surface;
416 struct weston_desktop_view *view;
417
418 if (!weston_surface_is_desktop_surface(wview->surface))
419 return;
420
421 surface = weston_surface_get_desktop_surface(wview->surface);
422 wl_list_for_each(view, &surface->view_list, link) {
423 if (view->view == wview) {
424 weston_desktop_view_destroy(view);
425 return;
426 }
427 }
428}
429
430static void
431weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
432{
433 struct weston_desktop_view *child;
434 struct wl_list *link = &view->view->layer_link.link;
435
436 wl_list_for_each_reverse(child, &view->children_list, children_link) {
437 struct weston_layer_entry *prev =
438 wl_container_of(link->prev, prev, link);
439
440 if (prev == &child->view->layer_link)
441 continue;
442
443 child->view->is_mapped = true;
444 weston_view_damage_below(child->view);
445 weston_view_geometry_dirty(child->view);
446 weston_layer_entry_remove(&child->view->layer_link);
447 weston_layer_entry_insert(prev, &child->view->layer_link);
448 weston_view_geometry_dirty(child->view);
449 weston_surface_damage(child->view->surface);
450 weston_view_update_transform(child->view);
451
452 weston_desktop_view_propagate_layer(child);
453 }
454}
455
456WL_EXPORT void
457weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
458{
459 struct weston_desktop_view *view;
460
461 wl_list_for_each(view, &surface->view_list, link)
462 weston_desktop_view_propagate_layer(view);
463}
464
465WL_EXPORT void
466weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
467{
468 if (surface->implementation->set_activated != NULL)
469 surface->implementation->set_activated(surface,
470 surface->implementation_data,
471 activated);
472}
473
474WL_EXPORT void
475weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
476{
477 if (surface->implementation->set_fullscreen != NULL)
478 surface->implementation->set_fullscreen(surface,
479 surface->implementation_data,
480 fullscreen);
481}
482
483WL_EXPORT void
484weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
485{
486 if (surface->implementation->set_maximized != NULL)
487 surface->implementation->set_maximized(surface,
488 surface->implementation_data,
489 maximized);
490}
491
492WL_EXPORT void
493weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
494{
495 if (surface->implementation->set_resizing != NULL)
496 surface->implementation->set_resizing(surface,
497 surface->implementation_data,
498 resizing);
499}
500
501WL_EXPORT void
502weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
503{
504 if (surface->implementation->set_size != NULL)
505 surface->implementation->set_size(surface,
506 surface->implementation_data,
507 width, height);
508}
509
510WL_EXPORT void
511weston_desktop_surface_close(struct weston_desktop_surface *surface)
512{
513 if (surface->implementation->close != NULL)
514 surface->implementation->close(surface,
515 surface->implementation_data);
516}
517
518struct weston_desktop_surface *
519weston_desktop_surface_from_client_link(struct wl_list *link)
520{
521 struct weston_desktop_surface *surface;
522
523 surface = wl_container_of(link, surface, client_link);
524 return surface;
525}
526
527struct wl_list *
528weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
529{
530 return &surface->client_link;
531}
532
533bool
534weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
535 const struct weston_desktop_surface_implementation *implementation)
536{
537 return surface->implementation == implementation;
538}
539
540const struct weston_desktop_surface_implementation *
541weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
542{
543 return surface->implementation;
544}
545
546void *
547weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
548{
549 return surface->implementation_data;
550}
551
552struct weston_desktop_surface *
553weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
554{
555 return surface->parent;
556}
557
558bool
559weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
560{
561 return !wl_list_empty(&surface->grab_link);
562}
563
564WL_EXPORT struct weston_desktop_client *
565weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
566{
567 return surface->client;
568}
569
570WL_EXPORT void *
571weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
572{
573 return surface->user_data;
574}
575
576WL_EXPORT struct weston_surface *
577weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
578{
579 return surface->surface;
580}
581
582WL_EXPORT const char *
583weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
584{
585 return surface->title;
586}
587
588WL_EXPORT const char *
589weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
590{
591 return surface->app_id;
592}
593
594WL_EXPORT pid_t
595weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
596{
597 pid_t pid;
598
599 if (surface->pid != 0) {
600 pid = surface->pid;
601 } else {
602 struct weston_desktop_client *client =
603 weston_desktop_surface_get_client(surface);
604 struct wl_client *wl_client =
605 weston_desktop_client_get_client(client);
606
607 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}