blob: b6075673956d4e3615d7197864f325fe2f2a76de [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;
Bryce Harringtone7069bc2016-08-23 13:40:30 -070057 struct wl_listener surface_drop_idle_inhibitor_listener;
Quentin Glidic248dd102016-08-12 10:41:34 +020058 struct wl_listener client_destroy_listener;
59 struct wl_list children_list;
60
61 struct wl_list resource_list;
62 bool has_geometry;
63 struct weston_geometry geometry;
64 struct {
65 char *title;
66 char *app_id;
67 pid_t pid;
68 };
69 struct {
70 struct weston_desktop_surface *parent;
71 struct wl_list children_link;
72 struct weston_position position;
73 bool use_geometry;
74 };
75 struct {
76 struct wl_list grab_link;
77 };
78};
79
80static void
81weston_desktop_surface_update_view_position(struct weston_desktop_surface *surface)
82{
83 struct weston_desktop_view *view;
84 int32_t x, y;
85
86 x = surface->position.x;
87 y = surface->position.y;
88
89 if (surface->use_geometry) {
90 struct weston_desktop_surface *parent =
91 weston_desktop_surface_get_parent(surface);
92 struct weston_geometry geometry, parent_geometry;
93
94 geometry = weston_desktop_surface_get_geometry(surface);
95 parent_geometry = weston_desktop_surface_get_geometry(parent);
96
97 x += parent_geometry.x - geometry.x;
98 y += parent_geometry.y - geometry.y;
99 }
100 wl_list_for_each(view, &surface->view_list, link)
101 weston_view_set_position(view->view, x, y);
102}
103
104
105static void
106weston_desktop_view_propagate_layer(struct weston_desktop_view *view);
107
108static void
Quentin Glidic248dd102016-08-12 10:41:34 +0200109weston_desktop_view_destroy(struct weston_desktop_view *view)
110{
111 struct weston_desktop_view *child_view, *tmp;
112
113 wl_list_for_each_safe(child_view, tmp, &view->children_list, children_link)
114 weston_desktop_view_destroy(child_view);
115
116 wl_list_remove(&view->children_link);
117 wl_list_remove(&view->link);
118
119 weston_view_damage_below(view->view);
120 if (view->parent != NULL)
121 weston_view_destroy(view->view);
122
123 free(view);
124}
125
126void
127weston_desktop_surface_destroy(struct weston_desktop_surface *surface)
128{
129 struct weston_desktop_view *view, *next_view;
130 struct weston_desktop_surface *child, *next_child;
131
132 wl_list_remove(&surface->surface_commit_listener.link);
133 wl_list_remove(&surface->surface_destroy_listener.link);
Bryce Harringtone7069bc2016-08-23 13:40:30 -0700134 wl_list_remove(&surface->surface_drop_idle_inhibitor_listener.link);
Quentin Glidic248dd102016-08-12 10:41:34 +0200135 wl_list_remove(&surface->client_destroy_listener.link);
136
137 if (!wl_list_empty(&surface->resource_list)) {
138 struct wl_resource *resource, *tmp;
139 wl_resource_for_each_safe(resource, tmp, &surface->resource_list) {
140 wl_resource_set_user_data(resource, NULL);
141 wl_list_remove(wl_resource_get_link(resource));
142 }
143 }
144
145 surface->implementation->destroy(surface, surface->implementation_data);
146
147 surface->surface->committed = NULL;
148 surface->surface->committed_private = NULL;
149
150 weston_desktop_surface_unset_relative_to(surface);
151 wl_list_remove(&surface->client_link);
152
153 wl_list_for_each_safe(child, next_child,
154 &surface->children_list,
155 children_link)
156 weston_desktop_surface_unset_relative_to(child);
157
158 wl_list_for_each_safe(view, next_view, &surface->view_list, link)
159 weston_desktop_view_destroy(view);
160
161 free(surface->title);
162 free(surface->app_id);
163
164 free(surface);
165}
166
167static void
168weston_desktop_surface_surface_committed(struct wl_listener *listener,
169 void *data)
170{
171 struct weston_desktop_surface *surface =
172 wl_container_of(listener, surface, surface_commit_listener);
173
Quentin Glidic003da882016-08-15 12:21:39 +0200174 if (surface->implementation->committed != NULL)
175 surface->implementation->committed(surface,
176 surface->implementation_data,
177 surface->buffer_move.x,
178 surface->buffer_move.y);
179
180 if (surface->parent != NULL) {
181 struct weston_desktop_view *view;
182
183 wl_list_for_each(view, &surface->view_list, link) {
184 weston_view_set_transform_parent(view->view,
185 view->parent->view);
186 weston_desktop_view_propagate_layer(view->parent);
187 }
188 weston_desktop_surface_update_view_position(surface);
189 }
190
191 if (!wl_list_empty(&surface->children_list)) {
192 struct weston_desktop_surface *child;
193
194 wl_list_for_each(child, &surface->children_list, children_link)
195 weston_desktop_surface_update_view_position(child);
196 }
197
198 surface->buffer_move.x = 0;
199 surface->buffer_move.y = 0;
Quentin Glidic248dd102016-08-12 10:41:34 +0200200}
201
202static void
203weston_desktop_surface_surface_destroyed(struct wl_listener *listener,
204 void *data)
205{
206 struct weston_desktop_surface *surface =
207 wl_container_of(listener, surface, surface_destroy_listener);
208
209 weston_desktop_surface_destroy(surface);
210}
211
212void
213weston_desktop_surface_resource_destroy(struct wl_resource *resource)
214{
215 struct weston_desktop_surface *surface =
216 wl_resource_get_user_data(resource);
217
218 if (surface != NULL)
219 weston_desktop_surface_destroy(surface);
220}
221
222static void
Bryce Harringtone7069bc2016-08-23 13:40:30 -0700223weston_desktop_surface_drop_idle_inhibitor(struct wl_listener *listener,
224 void *data)
225{
226 struct weston_desktop_surface *surface =
227 wl_container_of(listener, surface, surface_drop_idle_inhibitor_listener);
228 struct weston_desktop *desktop = surface->desktop;
229
230 printf("weston_desktop_surface_drop_idle_inhibitor\n");
231 weston_desktop_api_surface_drop_idle_inhibitor(desktop, surface);
232 // TODO: Need to call shell.c's desktop_surface_drop_idle_inhibitor
233 //shell_desktop_api.surface_drop_idle_inhibitor(surface, NULL /*data?*/);
234}
235
236static void
Quentin Glidic248dd102016-08-12 10:41:34 +0200237weston_desktop_surface_committed(struct weston_surface *wsurface,
238 int32_t sx, int32_t sy)
239{
240 struct weston_desktop_surface *surface = wsurface->committed_private;
241
Quentin Glidic003da882016-08-15 12:21:39 +0200242 surface->buffer_move.x = sx;
243 surface->buffer_move.y = sy;
Quentin Glidic248dd102016-08-12 10:41:34 +0200244}
245
246static void
247weston_desktop_surface_client_destroyed(struct wl_listener *listener,
248 void *data)
249{
250 struct weston_desktop_surface *surface =
251 wl_container_of(listener, surface, client_destroy_listener);
252
253 weston_desktop_surface_destroy(surface);
254}
255
256struct weston_desktop_surface *
257weston_desktop_surface_create(struct weston_desktop *desktop,
258 struct weston_desktop_client *client,
259 struct weston_surface *wsurface,
260 const struct weston_desktop_surface_implementation *implementation,
261 void *implementation_data)
262{
263 assert(implementation->destroy != NULL);
264
265 struct weston_desktop_surface *surface;
266
267 surface = zalloc(sizeof(struct weston_desktop_surface));
268 if (surface == NULL) {
269 if (client != NULL)
270 wl_client_post_no_memory(weston_desktop_client_get_client(client));
271 return NULL;
272 }
273
274 surface->desktop = desktop;
275 surface->implementation = implementation;
276 surface->implementation_data = implementation_data;
277 surface->surface = wsurface;
278
279 surface->client = client;
280 surface->client_destroy_listener.notify =
281 weston_desktop_surface_client_destroyed;
282 weston_desktop_client_add_destroy_listener(
283 client, &surface->client_destroy_listener);
284
285 wsurface->committed = weston_desktop_surface_committed;
286 wsurface->committed_private = surface;
287
288 surface->surface_commit_listener.notify =
289 weston_desktop_surface_surface_committed;
290 wl_signal_add(&surface->surface->commit_signal,
291 &surface->surface_commit_listener);
292 surface->surface_destroy_listener.notify =
293 weston_desktop_surface_surface_destroyed;
294 wl_signal_add(&surface->surface->destroy_signal,
295 &surface->surface_destroy_listener);
Bryce Harringtone7069bc2016-08-23 13:40:30 -0700296 surface->surface_drop_idle_inhibitor_listener.notify =
297 weston_desktop_surface_drop_idle_inhibitor;
298 wl_signal_add(&surface->surface->drop_idle_inhibitor_signal,
299 &surface->surface_drop_idle_inhibitor_listener);
Quentin Glidic248dd102016-08-12 10:41:34 +0200300
301 wl_list_init(&surface->client_link);
302 wl_list_init(&surface->resource_list);
303 wl_list_init(&surface->children_list);
304 wl_list_init(&surface->children_link);
305 wl_list_init(&surface->view_list);
306 wl_list_init(&surface->grab_link);
307
308 return surface;
309}
310
311struct wl_resource *
312weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
313 const struct wl_interface *interface,
314 const void *implementation, uint32_t id,
315 wl_resource_destroy_func_t destroy)
316{
317 struct wl_resource *client_resource =
318 weston_desktop_client_get_resource(surface->client);
319 struct wl_client *wl_client =
320 weston_desktop_client_get_client(surface->client);
321 struct wl_resource *resource;
322
323 resource = wl_resource_create(wl_client,
324 interface,
325 wl_resource_get_version(client_resource),
326 id);
327 if (resource == NULL) {
328 wl_client_post_no_memory(wl_client);
329 weston_desktop_surface_destroy(surface);
330 return NULL;
331 }
332 if (destroy == NULL)
333 destroy = weston_desktop_surface_resource_destroy;
334 wl_resource_set_implementation(resource, implementation, surface, destroy);
335 wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
336
337 return resource;
338}
339
340struct weston_desktop_surface *
341weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
342{
343 struct weston_desktop_surface *surface =
344 wl_container_of(grab_link, surface, grab_link);
345
346 return surface;
347}
348
349WL_EXPORT bool
350weston_surface_is_desktop_surface(struct weston_surface *wsurface)
351{
352 return wsurface->committed == weston_desktop_surface_committed;
353}
354
355WL_EXPORT struct weston_desktop_surface *
356weston_surface_get_desktop_surface(struct weston_surface *wsurface)
357{
358 if (!weston_surface_is_desktop_surface(wsurface))
359 return NULL;
360 return wsurface->committed_private;
361}
362
363WL_EXPORT void
364weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
365 void *user_data)
366{
367 surface->user_data = user_data;
368}
369
370static struct weston_desktop_view *
371weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
372{
373 struct wl_client *wl_client=
374 weston_desktop_client_get_client(surface->client);
375 struct weston_desktop_view *view, *child_view;
376 struct weston_view *wview;
377 struct weston_desktop_surface *child;
378
379 wview = weston_view_create(surface->surface);
380 if (wview == NULL) {
381 if (wl_client != NULL)
382 wl_client_post_no_memory(wl_client);
383 return NULL;
384 }
385
386 view = zalloc(sizeof(struct weston_desktop_view));
387 if (view == NULL) {
388 if (wl_client != NULL)
389 wl_client_post_no_memory(wl_client);
390 return NULL;
391 }
392
393 view->view = wview;
394 wl_list_init(&view->children_list);
395 wl_list_init(&view->children_link);
396 wl_list_insert(surface->view_list.prev, &view->link);
397
398 wl_list_for_each(child, &surface->children_list, children_link) {
399 child_view =
400 weston_desktop_surface_create_desktop_view(child);
401 if (child_view == NULL) {
402 weston_desktop_view_destroy(view);
403 return NULL;
404 }
405
406 child_view->parent = view;
407 wl_list_insert(view->children_list.prev,
408 &child_view->children_link);
409 }
410
411 return view;
412}
413
414WL_EXPORT struct weston_view *
415weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
416{
417 struct weston_desktop_view *view;
418
419 view = weston_desktop_surface_create_desktop_view(surface);
420 if (view == NULL)
421 return NULL;
422
423 return view->view;
424}
425
426WL_EXPORT void
Quentin Glidicf01ecee2016-08-16 10:52:46 +0200427weston_desktop_surface_unlink_view(struct weston_view *wview)
Quentin Glidic248dd102016-08-12 10:41:34 +0200428{
429 struct weston_desktop_surface *surface;
430 struct weston_desktop_view *view;
431
432 if (!weston_surface_is_desktop_surface(wview->surface))
433 return;
434
435 surface = weston_surface_get_desktop_surface(wview->surface);
436 wl_list_for_each(view, &surface->view_list, link) {
437 if (view->view == wview) {
438 weston_desktop_view_destroy(view);
439 return;
440 }
441 }
442}
443
444static void
445weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
446{
447 struct weston_desktop_view *child;
448 struct wl_list *link = &view->view->layer_link.link;
449
450 wl_list_for_each_reverse(child, &view->children_list, children_link) {
451 struct weston_layer_entry *prev =
452 wl_container_of(link->prev, prev, link);
453
454 if (prev == &child->view->layer_link)
455 continue;
456
457 child->view->is_mapped = true;
458 weston_view_damage_below(child->view);
459 weston_view_geometry_dirty(child->view);
460 weston_layer_entry_remove(&child->view->layer_link);
461 weston_layer_entry_insert(prev, &child->view->layer_link);
462 weston_view_geometry_dirty(child->view);
463 weston_surface_damage(child->view->surface);
464 weston_view_update_transform(child->view);
465
466 weston_desktop_view_propagate_layer(child);
467 }
468}
469
470WL_EXPORT void
471weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
472{
473 struct weston_desktop_view *view;
474
475 wl_list_for_each(view, &surface->view_list, link)
476 weston_desktop_view_propagate_layer(view);
477}
478
479WL_EXPORT void
480weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
481{
482 if (surface->implementation->set_activated != NULL)
483 surface->implementation->set_activated(surface,
484 surface->implementation_data,
485 activated);
486}
487
488WL_EXPORT void
489weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
490{
491 if (surface->implementation->set_fullscreen != NULL)
492 surface->implementation->set_fullscreen(surface,
493 surface->implementation_data,
494 fullscreen);
495}
496
497WL_EXPORT void
498weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
499{
500 if (surface->implementation->set_maximized != NULL)
501 surface->implementation->set_maximized(surface,
502 surface->implementation_data,
503 maximized);
504}
505
506WL_EXPORT void
507weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
508{
509 if (surface->implementation->set_resizing != NULL)
510 surface->implementation->set_resizing(surface,
511 surface->implementation_data,
512 resizing);
513}
514
515WL_EXPORT void
516weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
517{
518 if (surface->implementation->set_size != NULL)
519 surface->implementation->set_size(surface,
520 surface->implementation_data,
521 width, height);
522}
523
524WL_EXPORT void
525weston_desktop_surface_close(struct weston_desktop_surface *surface)
526{
527 if (surface->implementation->close != NULL)
528 surface->implementation->close(surface,
529 surface->implementation_data);
530}
531
532struct weston_desktop_surface *
533weston_desktop_surface_from_client_link(struct wl_list *link)
534{
535 struct weston_desktop_surface *surface;
536
537 surface = wl_container_of(link, surface, client_link);
538 return surface;
539}
540
541struct wl_list *
542weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
543{
544 return &surface->client_link;
545}
546
547bool
548weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
549 const struct weston_desktop_surface_implementation *implementation)
550{
551 return surface->implementation == implementation;
552}
553
554const struct weston_desktop_surface_implementation *
555weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
556{
557 return surface->implementation;
558}
559
560void *
561weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
562{
563 return surface->implementation_data;
564}
565
566struct weston_desktop_surface *
567weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
568{
569 return surface->parent;
570}
571
572bool
573weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
574{
575 return !wl_list_empty(&surface->grab_link);
576}
577
578WL_EXPORT struct weston_desktop_client *
579weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
580{
581 return surface->client;
582}
583
584WL_EXPORT void *
585weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
586{
587 return surface->user_data;
588}
589
590WL_EXPORT struct weston_surface *
591weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
592{
593 return surface->surface;
594}
595
596WL_EXPORT const char *
597weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
598{
599 return surface->title;
600}
601
602WL_EXPORT const char *
603weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
604{
605 return surface->app_id;
606}
607
608WL_EXPORT pid_t
609weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
610{
611 pid_t pid;
612
613 if (surface->pid != 0) {
614 pid = surface->pid;
615 } else {
616 struct weston_desktop_client *client =
617 weston_desktop_surface_get_client(surface);
618 struct wl_client *wl_client =
619 weston_desktop_client_get_client(client);
620
621 wl_client_get_credentials(wl_client, &pid, NULL, NULL);
622 }
623 return pid;
624}
625
626WL_EXPORT bool
627weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
628{
629 if (surface->implementation->get_activated == NULL)
630 return false;
631 return surface->implementation->get_activated(surface,
632 surface->implementation_data);
633}
634
635WL_EXPORT bool
636weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
637{
638 if (surface->implementation->get_resizing == NULL)
639 return false;
640 return surface->implementation->get_resizing(surface,
641 surface->implementation_data);
642}
643
644WL_EXPORT bool
645weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
646{
647 if (surface->implementation->get_maximized == NULL)
648 return false;
649 return surface->implementation->get_maximized(surface,
650 surface->implementation_data);
651}
652
653WL_EXPORT bool
654weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
655{
656 if (surface->implementation->get_fullscreen == NULL)
657 return false;
658 return surface->implementation->get_fullscreen(surface,
659 surface->implementation_data);
660}
661
662WL_EXPORT struct weston_geometry
663weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface)
664{
665 if (surface->has_geometry)
666 return surface->geometry;
667 return weston_surface_get_bounding_box(surface->surface);
668}
669
670WL_EXPORT struct weston_size
671weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface)
672{
673 struct weston_size size = { 0, 0 };
674
675 if (surface->implementation->get_max_size == NULL)
676 return size;
677 return surface->implementation->get_max_size(surface,
678 surface->implementation_data);
679}
680
681WL_EXPORT struct weston_size
682weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
683{
684 struct weston_size size = { 0, 0 };
685
686 if (surface->implementation->get_min_size == NULL)
687 return size;
688 return surface->implementation->get_min_size(surface,
689 surface->implementation_data);
690}
691
692void
693weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
694 const char *title)
695{
696 char *tmp;
697
698 tmp = strdup(title);
699 if (tmp == NULL)
700 return;
701
702 free(surface->title);
703 surface->title = tmp;
704}
705
706void
707weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
708 const char *app_id)
709{
710 char *tmp;
711
712 tmp = strdup(app_id);
713 if (tmp == NULL)
714 return;
715
716 free(surface->app_id);
717 surface->app_id = tmp;
718}
719
720void
721weston_desktop_surface_set_pid(struct weston_desktop_surface *surface,
722 pid_t pid)
723{
724 surface->pid = pid;
725}
726
727void
728weston_desktop_surface_set_geometry(struct weston_desktop_surface *surface,
729 struct weston_geometry geometry)
730{
731 surface->has_geometry = true;
732 surface->geometry = geometry;
733}
734
735void
736weston_desktop_surface_set_relative_to(struct weston_desktop_surface *surface,
737 struct weston_desktop_surface *parent,
738 int32_t x, int32_t y, bool use_geometry)
739{
740 struct weston_desktop_view *view, *parent_view;
741 struct wl_list *link, *tmp;
742
743 assert(parent);
744
745 surface->position.x = x;
746 surface->position.y = y;
747 surface->use_geometry = use_geometry;
748
749 if (surface->parent == parent)
750 return;
751
752 surface->parent = parent;
753 wl_list_remove(&surface->children_link);
754 wl_list_insert(surface->parent->children_list.prev,
755 &surface->children_link);
756
757 link = surface->view_list.next;
758 tmp = link->next;
759 wl_list_for_each(parent_view, &parent->view_list, link) {
760 if (link == &surface->view_list) {
761 view = weston_desktop_surface_create_desktop_view(surface);
762 if (view == NULL)
763 return;
764 tmp = &surface->view_list;
765 } else {
766 view = wl_container_of(link, view, link);
767 wl_list_remove(&view->children_link);
768 }
769
770 view->parent = parent_view;
771 wl_list_insert(parent_view->children_list.prev,
772 &view->children_link);
773 weston_desktop_view_propagate_layer(view);
774
775 link = tmp;
776 tmp = link->next;
777 }
778 for (; link != &surface->view_list; link = tmp, tmp = link->next) {
779 view = wl_container_of(link, view, link);
780 weston_desktop_view_destroy(view);
781 }
782}
783
784void
785weston_desktop_surface_unset_relative_to(struct weston_desktop_surface *surface)
786{
787 struct weston_desktop_view *view, *tmp;
788
789 if (surface->parent == NULL)
790 return;
791
792 surface->parent = NULL;
793 wl_list_remove(&surface->children_link);
794 wl_list_init(&surface->children_link);
795
796 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
797 weston_desktop_view_destroy(view);
798}
799
800void
801weston_desktop_surface_popup_grab(struct weston_desktop_surface *surface,
802 struct weston_desktop_seat *seat,
803 uint32_t serial)
804{
805 struct wl_client *wl_client =
806 weston_desktop_client_get_client(surface->client);
807 if (weston_desktop_seat_popup_grab_start(seat, wl_client, serial))
808 weston_desktop_seat_popup_grab_add_surface(seat, &surface->grab_link);
809 else
810 weston_desktop_surface_popup_dismiss(surface);
811}
812
813void
814weston_desktop_surface_popup_ungrab(struct weston_desktop_surface *surface,
815 struct weston_desktop_seat *seat)
816{
817 weston_desktop_seat_popup_grab_remove_surface(seat, &surface->grab_link);
818}
819
820void
821weston_desktop_surface_popup_dismiss(struct weston_desktop_surface *surface)
822{
823 struct weston_desktop_view *view, *tmp;
824
825 wl_list_for_each_safe(view, tmp, &surface->view_list, link)
826 weston_desktop_view_destroy(view);
827 wl_list_remove(&surface->grab_link);
828 wl_list_init(&surface->grab_link);
829 weston_desktop_surface_close(surface);
830}