blob: 42258db9f6d0aa70c89463236a269a71890f6c44 [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
272 surface->surface_commit_listener.notify =
273 weston_desktop_surface_surface_committed;
274 wl_signal_add(&surface->surface->commit_signal,
275 &surface->surface_commit_listener);
276 surface->surface_destroy_listener.notify =
277 weston_desktop_surface_surface_destroyed;
278 wl_signal_add(&surface->surface->destroy_signal,
279 &surface->surface_destroy_listener);
280
281 wl_list_init(&surface->client_link);
282 wl_list_init(&surface->resource_list);
283 wl_list_init(&surface->children_list);
284 wl_list_init(&surface->children_link);
285 wl_list_init(&surface->view_list);
286 wl_list_init(&surface->grab_link);
287
288 return surface;
289}
290
291struct wl_resource *
292weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
293 const struct wl_interface *interface,
294 const void *implementation, uint32_t id,
295 wl_resource_destroy_func_t destroy)
296{
297 struct wl_resource *client_resource =
298 weston_desktop_client_get_resource(surface->client);
299 struct wl_client *wl_client =
300 weston_desktop_client_get_client(surface->client);
301 struct wl_resource *resource;
302
303 resource = wl_resource_create(wl_client,
304 interface,
305 wl_resource_get_version(client_resource),
306 id);
307 if (resource == NULL) {
308 wl_client_post_no_memory(wl_client);
309 weston_desktop_surface_destroy(surface);
310 return NULL;
311 }
312 if (destroy == NULL)
313 destroy = weston_desktop_surface_resource_destroy;
314 wl_resource_set_implementation(resource, implementation, surface, destroy);
315 wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
316
317 return resource;
318}
319
320struct weston_desktop_surface *
321weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
322{
323 struct weston_desktop_surface *surface =
324 wl_container_of(grab_link, surface, grab_link);
325
326 return surface;
327}
328
329WL_EXPORT bool
330weston_surface_is_desktop_surface(struct weston_surface *wsurface)
331{
332 return wsurface->committed == weston_desktop_surface_committed;
333}
334
335WL_EXPORT struct weston_desktop_surface *
336weston_surface_get_desktop_surface(struct weston_surface *wsurface)
337{
338 if (!weston_surface_is_desktop_surface(wsurface))
339 return NULL;
340 return wsurface->committed_private;
341}
342
343WL_EXPORT void
344weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
345 void *user_data)
346{
347 surface->user_data = user_data;
348}
349
350static struct weston_desktop_view *
351weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
352{
353 struct wl_client *wl_client=
354 weston_desktop_client_get_client(surface->client);
355 struct weston_desktop_view *view, *child_view;
356 struct weston_view *wview;
357 struct weston_desktop_surface *child;
358
359 wview = weston_view_create(surface->surface);
360 if (wview == NULL) {
361 if (wl_client != NULL)
362 wl_client_post_no_memory(wl_client);
363 return NULL;
364 }
365
366 view = zalloc(sizeof(struct weston_desktop_view));
367 if (view == NULL) {
368 if (wl_client != NULL)
369 wl_client_post_no_memory(wl_client);
370 return NULL;
371 }
372
373 view->view = wview;
374 wl_list_init(&view->children_list);
375 wl_list_init(&view->children_link);
376 wl_list_insert(surface->view_list.prev, &view->link);
377
378 wl_list_for_each(child, &surface->children_list, children_link) {
379 child_view =
380 weston_desktop_surface_create_desktop_view(child);
381 if (child_view == NULL) {
382 weston_desktop_view_destroy(view);
383 return NULL;
384 }
385
386 child_view->parent = view;
387 wl_list_insert(view->children_list.prev,
388 &child_view->children_link);
389 }
390
391 return view;
392}
393
394WL_EXPORT struct weston_view *
395weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
396{
397 struct weston_desktop_view *view;
398
399 view = weston_desktop_surface_create_desktop_view(surface);
400 if (view == NULL)
401 return NULL;
402
403 return view->view;
404}
405
406WL_EXPORT void
407weston_desktop_surface_destroy_view(struct weston_view *wview)
408{
409 struct weston_desktop_surface *surface;
410 struct weston_desktop_view *view;
411
412 if (!weston_surface_is_desktop_surface(wview->surface))
413 return;
414
415 surface = weston_surface_get_desktop_surface(wview->surface);
416 wl_list_for_each(view, &surface->view_list, link) {
417 if (view->view == wview) {
418 weston_desktop_view_destroy(view);
419 return;
420 }
421 }
422}
423
424static void
425weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
426{
427 struct weston_desktop_view *child;
428 struct wl_list *link = &view->view->layer_link.link;
429
430 wl_list_for_each_reverse(child, &view->children_list, children_link) {
431 struct weston_layer_entry *prev =
432 wl_container_of(link->prev, prev, link);
433
434 if (prev == &child->view->layer_link)
435 continue;
436
437 child->view->is_mapped = true;
438 weston_view_damage_below(child->view);
439 weston_view_geometry_dirty(child->view);
440 weston_layer_entry_remove(&child->view->layer_link);
441 weston_layer_entry_insert(prev, &child->view->layer_link);
442 weston_view_geometry_dirty(child->view);
443 weston_surface_damage(child->view->surface);
444 weston_view_update_transform(child->view);
445
446 weston_desktop_view_propagate_layer(child);
447 }
448}
449
450WL_EXPORT void
451weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
452{
453 struct weston_desktop_view *view;
454
455 wl_list_for_each(view, &surface->view_list, link)
456 weston_desktop_view_propagate_layer(view);
457}
458
459WL_EXPORT void
460weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
461{
462 if (surface->implementation->set_activated != NULL)
463 surface->implementation->set_activated(surface,
464 surface->implementation_data,
465 activated);
466}
467
468WL_EXPORT void
469weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
470{
471 if (surface->implementation->set_fullscreen != NULL)
472 surface->implementation->set_fullscreen(surface,
473 surface->implementation_data,
474 fullscreen);
475}
476
477WL_EXPORT void
478weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
479{
480 if (surface->implementation->set_maximized != NULL)
481 surface->implementation->set_maximized(surface,
482 surface->implementation_data,
483 maximized);
484}
485
486WL_EXPORT void
487weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
488{
489 if (surface->implementation->set_resizing != NULL)
490 surface->implementation->set_resizing(surface,
491 surface->implementation_data,
492 resizing);
493}
494
495WL_EXPORT void
496weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
497{
498 if (surface->implementation->set_size != NULL)
499 surface->implementation->set_size(surface,
500 surface->implementation_data,
501 width, height);
502}
503
504WL_EXPORT void
505weston_desktop_surface_close(struct weston_desktop_surface *surface)
506{
507 if (surface->implementation->close != NULL)
508 surface->implementation->close(surface,
509 surface->implementation_data);
510}
511
512struct weston_desktop_surface *
513weston_desktop_surface_from_client_link(struct wl_list *link)
514{
515 struct weston_desktop_surface *surface;
516
517 surface = wl_container_of(link, surface, client_link);
518 return surface;
519}
520
521struct wl_list *
522weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
523{
524 return &surface->client_link;
525}
526
527bool
528weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
529 const struct weston_desktop_surface_implementation *implementation)
530{
531 return surface->implementation == implementation;
532}
533
534const struct weston_desktop_surface_implementation *
535weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
536{
537 return surface->implementation;
538}
539
540void *
541weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
542{
543 return surface->implementation_data;
544}
545
546struct weston_desktop_surface *
547weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
548{
549 return surface->parent;
550}
551
552bool
553weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
554{
555 return !wl_list_empty(&surface->grab_link);
556}
557
558WL_EXPORT struct weston_desktop_client *
559weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
560{
561 return surface->client;
562}
563
564WL_EXPORT void *
565weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
566{
567 return surface->user_data;
568}
569
570WL_EXPORT struct weston_surface *
571weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
572{
573 return surface->surface;
574}
575
576WL_EXPORT const char *
577weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
578{
579 return surface->title;
580}
581
582WL_EXPORT const char *
583weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
584{
585 return surface->app_id;
586}
587
588WL_EXPORT pid_t
589weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
590{
591 pid_t pid;
592
593 if (surface->pid != 0) {
594 pid = surface->pid;
595 } else {
596 struct weston_desktop_client *client =
597 weston_desktop_surface_get_client(surface);
598 struct wl_client *wl_client =
599 weston_desktop_client_get_client(client);
600
601 wl_client_get_credentials(wl_client, &pid, NULL, NULL);
602 }
603 return pid;
604}
605
606WL_EXPORT bool
607weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
608{
609 if (surface->implementation->get_activated == NULL)
610 return false;
611 return surface->implementation->get_activated(surface,
612 surface->implementation_data);
613}
614
615WL_EXPORT bool
616weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
617{
618 if (surface->implementation->get_resizing == NULL)
619 return false;
620 return surface->implementation->get_resizing(surface,
621 surface->implementation_data);
622}
623
624WL_EXPORT bool
625weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
626{
627 if (surface->implementation->get_maximized == NULL)
628 return false;
629 return surface->implementation->get_maximized(surface,
630 surface->implementation_data);
631}
632
633WL_EXPORT bool
634weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
635{
636 if (surface->implementation->get_fullscreen == NULL)
637 return false;
638 return surface->implementation->get_fullscreen(surface,
639 surface->implementation_data);
640}
641
642WL_EXPORT struct weston_geometry
643weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface)
644{
645 if (surface->has_geometry)
646 return surface->geometry;
647 return weston_surface_get_bounding_box(surface->surface);
648}
649
650WL_EXPORT struct weston_size
651weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface)
652{
653 struct weston_size size = { 0, 0 };
654
655 if (surface->implementation->get_max_size == NULL)
656 return size;
657 return surface->implementation->get_max_size(surface,
658 surface->implementation_data);
659}
660
661WL_EXPORT struct weston_size
662weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
663{
664 struct weston_size size = { 0, 0 };
665
666 if (surface->implementation->get_min_size == NULL)
667 return size;
668 return surface->implementation->get_min_size(surface,
669 surface->implementation_data);
670}
671
672void
673weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
674 const char *title)
675{
676 char *tmp;
677
678 tmp = strdup(title);
679 if (tmp == NULL)
680 return;
681
682 free(surface->title);
683 surface->title = tmp;
684}
685
686void
687weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
688 const char *app_id)
689{
690 char *tmp;
691
692 tmp = strdup(app_id);
693 if (tmp == NULL)
694 return;
695
696 free(surface->app_id);
697 surface->app_id = tmp;
698}
699
700void
701weston_desktop_surface_set_pid(struct weston_desktop_surface *surface,
702 pid_t pid)
703{
704 surface->pid = pid;
705}
706
707void
708weston_desktop_surface_set_geometry(struct weston_desktop_surface *surface,
709 struct weston_geometry geometry)
710{
711 surface->has_geometry = true;
712 surface->geometry = geometry;
713}
714
715void
716weston_desktop_surface_set_relative_to(struct weston_desktop_surface *surface,
717 struct weston_desktop_surface *parent,
718 int32_t x, int32_t y, bool use_geometry)
719{
720 struct weston_desktop_view *view, *parent_view;
721 struct wl_list *link, *tmp;
722
723 assert(parent);
724
725 surface->position.x = x;
726 surface->position.y = y;
727 surface->use_geometry = use_geometry;
728
729 if (surface->parent == parent)
730 return;
731
732 surface->parent = parent;
733 wl_list_remove(&surface->children_link);
734 wl_list_insert(surface->parent->children_list.prev,
735 &surface->children_link);
736
737 link = surface->view_list.next;
738 tmp = link->next;
739 wl_list_for_each(parent_view, &parent->view_list, link) {
740 if (link == &surface->view_list) {
741 view = weston_desktop_surface_create_desktop_view(surface);
742 if (view == NULL)
743 return;
744 tmp = &surface->view_list;
745 } else {
746 view = wl_container_of(link, view, link);
747 wl_list_remove(&view->children_link);
748 }
749
750 view->parent = parent_view;
751 wl_list_insert(parent_view->children_list.prev,
752 &view->children_link);
753 weston_desktop_view_propagate_layer(view);
754
755 link = tmp;
756 tmp = link->next;
757 }
758 for (; link != &surface->view_list; link = tmp, tmp = link->next) {
759 view = wl_container_of(link, view, link);
760 weston_desktop_view_destroy(view);
761 }
762}
763
764void
765weston_desktop_surface_unset_relative_to(struct weston_desktop_surface *surface)
766{
767 struct weston_desktop_view *view, *tmp;
768
769 if (surface->parent == NULL)
770 return;
771
772 surface->parent = NULL;
773 wl_list_remove(&surface->children_link);
774 wl_list_init(&surface->children_link);
775
776 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
777 weston_desktop_view_destroy(view);
778}
779
780void
781weston_desktop_surface_popup_grab(struct weston_desktop_surface *surface,
782 struct weston_desktop_seat *seat,
783 uint32_t serial)
784{
785 struct wl_client *wl_client =
786 weston_desktop_client_get_client(surface->client);
787 if (weston_desktop_seat_popup_grab_start(seat, wl_client, serial))
788 weston_desktop_seat_popup_grab_add_surface(seat, &surface->grab_link);
789 else
790 weston_desktop_surface_popup_dismiss(surface);
791}
792
793void
794weston_desktop_surface_popup_ungrab(struct weston_desktop_surface *surface,
795 struct weston_desktop_seat *seat)
796{
797 weston_desktop_seat_popup_grab_remove_surface(seat, &surface->grab_link);
798}
799
800void
801weston_desktop_surface_popup_dismiss(struct weston_desktop_surface *surface)
802{
803 struct weston_desktop_view *view, *tmp;
804
805 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
806 weston_desktop_view_destroy(view);
807 wl_list_remove(&surface->grab_link);
808 wl_list_init(&surface->grab_link);
809 weston_desktop_surface_close(surface);
810}