1 /*
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 <libweston/libweston.h>
32 #include <libweston/zalloc.h>
33
34 #include <libweston-desktop/libweston-desktop.h>
35 #include "internal.h"
36
37 struct 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
45 struct 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 struct weston_position buffer_move;
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 struct wl_signal metadata_signal;
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
80 static void
weston_desktop_surface_update_view_position(struct weston_desktop_surface * surface)81 weston_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
105 static void
106 weston_desktop_view_propagate_layer(struct weston_desktop_view *view);
107
108 static void
weston_desktop_view_destroy(struct weston_desktop_view * view)109 weston_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
126 void
weston_desktop_surface_destroy(struct weston_desktop_surface * surface)127 weston_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);
134 wl_list_remove(&surface->client_destroy_listener.link);
135
136 if (!wl_list_empty(&surface->resource_list)) {
137 struct wl_resource *resource, *tmp;
138 wl_resource_for_each_safe(resource, tmp, &surface->resource_list) {
139 wl_resource_set_user_data(resource, NULL);
140 wl_list_remove(wl_resource_get_link(resource));
141 }
142 }
143
144 surface->implementation->destroy(surface, surface->implementation_data);
145
146 surface->surface->committed = NULL;
147 surface->surface->committed_private = NULL;
148
149 weston_desktop_surface_unset_relative_to(surface);
150 wl_list_remove(&surface->client_link);
151
152 wl_list_for_each_safe(child, next_child,
153 &surface->children_list,
154 children_link)
155 weston_desktop_surface_unset_relative_to(child);
156
157 wl_list_for_each_safe(view, next_view, &surface->view_list, link)
158 weston_desktop_view_destroy(view);
159
160 free(surface->title);
161 free(surface->app_id);
162
163 free(surface);
164 }
165
166 static void
weston_desktop_surface_surface_committed(struct wl_listener * listener,void * data)167 weston_desktop_surface_surface_committed(struct wl_listener *listener,
168 void *data)
169 {
170 struct weston_desktop_surface *surface =
171 wl_container_of(listener, surface, surface_commit_listener);
172
173 if (surface->implementation->committed != NULL)
174 surface->implementation->committed(surface,
175 surface->implementation_data,
176 surface->buffer_move.x,
177 surface->buffer_move.y);
178
179 if (surface->parent != NULL) {
180 struct weston_desktop_view *view;
181
182 wl_list_for_each(view, &surface->view_list, link) {
183 weston_view_set_transform_parent(view->view,
184 view->parent->view);
185 weston_desktop_view_propagate_layer(view->parent);
186 }
187 weston_desktop_surface_update_view_position(surface);
188 }
189
190 if (!wl_list_empty(&surface->children_list)) {
191 struct weston_desktop_surface *child;
192
193 wl_list_for_each(child, &surface->children_list, children_link)
194 weston_desktop_surface_update_view_position(child);
195 }
196
197 surface->buffer_move.x = 0;
198 surface->buffer_move.y = 0;
199 }
200
201 static void
weston_desktop_surface_surface_destroyed(struct wl_listener * listener,void * data)202 weston_desktop_surface_surface_destroyed(struct wl_listener *listener,
203 void *data)
204 {
205 struct weston_desktop_surface *surface =
206 wl_container_of(listener, surface, surface_destroy_listener);
207
208 weston_desktop_surface_destroy(surface);
209 }
210
211 void
weston_desktop_surface_resource_destroy(struct wl_resource * resource)212 weston_desktop_surface_resource_destroy(struct wl_resource *resource)
213 {
214 struct weston_desktop_surface *surface =
215 wl_resource_get_user_data(resource);
216
217 if (surface != NULL)
218 weston_desktop_surface_destroy(surface);
219 }
220
221 static void
weston_desktop_surface_committed(struct weston_surface * wsurface,int32_t sx,int32_t sy)222 weston_desktop_surface_committed(struct weston_surface *wsurface,
223 int32_t sx, int32_t sy)
224 {
225 struct weston_desktop_surface *surface = wsurface->committed_private;
226
227 surface->buffer_move.x = sx;
228 surface->buffer_move.y = sy;
229 }
230
231 static void
weston_desktop_surface_client_destroyed(struct wl_listener * listener,void * data)232 weston_desktop_surface_client_destroyed(struct wl_listener *listener,
233 void *data)
234 {
235 struct weston_desktop_surface *surface =
236 wl_container_of(listener, surface, client_destroy_listener);
237
238 weston_desktop_surface_destroy(surface);
239 }
240
241 struct weston_desktop_surface *
weston_desktop_surface_create(struct weston_desktop * desktop,struct weston_desktop_client * client,struct weston_surface * wsurface,const struct weston_desktop_surface_implementation * implementation,void * implementation_data)242 weston_desktop_surface_create(struct weston_desktop *desktop,
243 struct weston_desktop_client *client,
244 struct weston_surface *wsurface,
245 const struct weston_desktop_surface_implementation *implementation,
246 void *implementation_data)
247 {
248 assert(implementation->destroy != NULL);
249
250 struct weston_desktop_surface *surface;
251
252 surface = zalloc(sizeof(struct weston_desktop_surface));
253 if (surface == NULL) {
254 if (client != NULL)
255 wl_client_post_no_memory(weston_desktop_client_get_client(client));
256 return NULL;
257 }
258
259 surface->desktop = desktop;
260 surface->implementation = implementation;
261 surface->implementation_data = implementation_data;
262 surface->surface = wsurface;
263
264 surface->client = client;
265 surface->client_destroy_listener.notify =
266 weston_desktop_surface_client_destroyed;
267 weston_desktop_client_add_destroy_listener(
268 client, &surface->client_destroy_listener);
269
270 wsurface->committed = weston_desktop_surface_committed;
271 wsurface->committed_private = surface;
272
273 surface->pid = -1;
274
275 surface->surface_commit_listener.notify =
276 weston_desktop_surface_surface_committed;
277 wl_signal_add(&surface->surface->commit_signal,
278 &surface->surface_commit_listener);
279 surface->surface_destroy_listener.notify =
280 weston_desktop_surface_surface_destroyed;
281 wl_signal_add(&surface->surface->destroy_signal,
282 &surface->surface_destroy_listener);
283
284 wl_list_init(&surface->client_link);
285 wl_list_init(&surface->resource_list);
286 wl_list_init(&surface->children_list);
287 wl_list_init(&surface->children_link);
288 wl_list_init(&surface->view_list);
289 wl_list_init(&surface->grab_link);
290
291 wl_signal_init(&surface->metadata_signal);
292
293 return surface;
294 }
295
296 struct wl_resource *
weston_desktop_surface_add_resource(struct weston_desktop_surface * surface,const struct wl_interface * interface,const void * implementation,uint32_t id,wl_resource_destroy_func_t destroy)297 weston_desktop_surface_add_resource(struct weston_desktop_surface *surface,
298 const struct wl_interface *interface,
299 const void *implementation, uint32_t id,
300 wl_resource_destroy_func_t destroy)
301 {
302 struct wl_resource *client_resource =
303 weston_desktop_client_get_resource(surface->client);
304 struct wl_client *wl_client =
305 weston_desktop_client_get_client(surface->client);
306 struct wl_resource *resource;
307
308 resource = wl_resource_create(wl_client,
309 interface,
310 wl_resource_get_version(client_resource),
311 id);
312 if (resource == NULL) {
313 wl_client_post_no_memory(wl_client);
314 weston_desktop_surface_destroy(surface);
315 return NULL;
316 }
317 if (destroy == NULL)
318 destroy = weston_desktop_surface_resource_destroy;
319 wl_resource_set_implementation(resource, implementation, surface, destroy);
320 wl_list_insert(&surface->resource_list, wl_resource_get_link(resource));
321
322 return resource;
323 }
324
325 struct weston_desktop_surface *
weston_desktop_surface_from_grab_link(struct wl_list * grab_link)326 weston_desktop_surface_from_grab_link(struct wl_list *grab_link)
327 {
328 struct weston_desktop_surface *surface =
329 wl_container_of(grab_link, surface, grab_link);
330
331 return surface;
332 }
333
334 WL_EXPORT bool
weston_surface_is_desktop_surface(struct weston_surface * wsurface)335 weston_surface_is_desktop_surface(struct weston_surface *wsurface)
336 {
337 return wsurface->committed == weston_desktop_surface_committed;
338 }
339
340 WL_EXPORT struct weston_desktop_surface *
weston_surface_get_desktop_surface(struct weston_surface * wsurface)341 weston_surface_get_desktop_surface(struct weston_surface *wsurface)
342 {
343 if (!weston_surface_is_desktop_surface(wsurface))
344 return NULL;
345 return wsurface->committed_private;
346 }
347
348 WL_EXPORT void
weston_desktop_surface_set_user_data(struct weston_desktop_surface * surface,void * user_data)349 weston_desktop_surface_set_user_data(struct weston_desktop_surface *surface,
350 void *user_data)
351 {
352 surface->user_data = user_data;
353 }
354
355 static struct weston_desktop_view *
weston_desktop_surface_create_desktop_view(struct weston_desktop_surface * surface)356 weston_desktop_surface_create_desktop_view(struct weston_desktop_surface *surface)
357 {
358 struct wl_client *wl_client=
359 weston_desktop_client_get_client(surface->client);
360 struct weston_desktop_view *view, *child_view;
361 struct weston_view *wview;
362 struct weston_desktop_surface *child;
363
364 wview = weston_view_create(surface->surface);
365 if (wview == NULL) {
366 if (wl_client != NULL)
367 wl_client_post_no_memory(wl_client);
368 return NULL;
369 }
370
371 view = zalloc(sizeof(struct weston_desktop_view));
372 if (view == NULL) {
373 if (wl_client != NULL)
374 wl_client_post_no_memory(wl_client);
375 return NULL;
376 }
377
378 view->view = wview;
379 wl_list_init(&view->children_list);
380 wl_list_init(&view->children_link);
381 wl_list_insert(surface->view_list.prev, &view->link);
382
383 wl_list_for_each(child, &surface->children_list, children_link) {
384 child_view =
385 weston_desktop_surface_create_desktop_view(child);
386 if (child_view == NULL) {
387 weston_desktop_view_destroy(view);
388 return NULL;
389 }
390
391 child_view->parent = view;
392 wl_list_insert(view->children_list.prev,
393 &child_view->children_link);
394 }
395
396 return view;
397 }
398
399 WL_EXPORT struct weston_view *
weston_desktop_surface_create_view(struct weston_desktop_surface * surface)400 weston_desktop_surface_create_view(struct weston_desktop_surface *surface)
401 {
402 struct weston_desktop_view *view;
403
404 view = weston_desktop_surface_create_desktop_view(surface);
405 if (view == NULL)
406 return NULL;
407
408 return view->view;
409 }
410
411 WL_EXPORT void
weston_desktop_surface_unlink_view(struct weston_view * wview)412 weston_desktop_surface_unlink_view(struct weston_view *wview)
413 {
414 struct weston_desktop_surface *surface;
415 struct weston_desktop_view *view;
416
417 if (!weston_surface_is_desktop_surface(wview->surface))
418 return;
419
420 surface = weston_surface_get_desktop_surface(wview->surface);
421 wl_list_for_each(view, &surface->view_list, link) {
422 if (view->view == wview) {
423 weston_desktop_view_destroy(view);
424 return;
425 }
426 }
427 }
428
429 static void
weston_desktop_view_propagate_layer(struct weston_desktop_view * view)430 weston_desktop_view_propagate_layer(struct weston_desktop_view *view)
431 {
432 struct weston_desktop_view *child;
433 struct wl_list *link = &view->view->layer_link.link;
434
435 wl_list_for_each_reverse(child, &view->children_list, children_link) {
436 struct weston_layer_entry *prev =
437 wl_container_of(link->prev, prev, link);
438
439 if (prev == &child->view->layer_link)
440 continue;
441
442 child->view->is_mapped = true;
443 weston_view_damage_below(child->view);
444 weston_view_geometry_dirty(child->view);
445 weston_layer_entry_remove(&child->view->layer_link);
446 weston_layer_entry_insert(prev, &child->view->layer_link);
447 weston_view_geometry_dirty(child->view);
448 weston_surface_damage(child->view->surface);
449 weston_view_update_transform(child->view);
450
451 weston_desktop_view_propagate_layer(child);
452 }
453 }
454
455 WL_EXPORT void
weston_desktop_surface_propagate_layer(struct weston_desktop_surface * surface)456 weston_desktop_surface_propagate_layer(struct weston_desktop_surface *surface)
457 {
458 struct weston_desktop_view *view;
459
460 wl_list_for_each(view, &surface->view_list, link)
461 weston_desktop_view_propagate_layer(view);
462 }
463
464 WL_EXPORT void
weston_desktop_surface_set_activated(struct weston_desktop_surface * surface,bool activated)465 weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, bool activated)
466 {
467 if (surface->implementation->set_activated != NULL)
468 surface->implementation->set_activated(surface,
469 surface->implementation_data,
470 activated);
471 }
472
473 WL_EXPORT void
weston_desktop_surface_set_fullscreen(struct weston_desktop_surface * surface,bool fullscreen)474 weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, bool fullscreen)
475 {
476 if (surface->implementation->set_fullscreen != NULL)
477 surface->implementation->set_fullscreen(surface,
478 surface->implementation_data,
479 fullscreen);
480 }
481
482 WL_EXPORT void
weston_desktop_surface_set_maximized(struct weston_desktop_surface * surface,bool maximized)483 weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, bool maximized)
484 {
485 if (surface->implementation->set_maximized != NULL)
486 surface->implementation->set_maximized(surface,
487 surface->implementation_data,
488 maximized);
489 }
490
491 WL_EXPORT void
weston_desktop_surface_set_resizing(struct weston_desktop_surface * surface,bool resizing)492 weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, bool resizing)
493 {
494 if (surface->implementation->set_resizing != NULL)
495 surface->implementation->set_resizing(surface,
496 surface->implementation_data,
497 resizing);
498 }
499
500 WL_EXPORT void
weston_desktop_surface_set_size(struct weston_desktop_surface * surface,int32_t width,int32_t height)501 weston_desktop_surface_set_size(struct weston_desktop_surface *surface, int32_t width, int32_t height)
502 {
503 if (surface->implementation->set_size != NULL)
504 surface->implementation->set_size(surface,
505 surface->implementation_data,
506 width, height);
507 }
508
509 WL_EXPORT void
weston_desktop_surface_close(struct weston_desktop_surface * surface)510 weston_desktop_surface_close(struct weston_desktop_surface *surface)
511 {
512 if (surface->implementation->close != NULL)
513 surface->implementation->close(surface,
514 surface->implementation_data);
515 }
516
517 WL_EXPORT void
weston_desktop_surface_add_metadata_listener(struct weston_desktop_surface * surface,struct wl_listener * listener)518 weston_desktop_surface_add_metadata_listener(struct weston_desktop_surface *surface,
519 struct wl_listener *listener)
520 {
521 wl_signal_add(&surface->metadata_signal, listener);
522 }
523
524 struct weston_desktop_surface *
weston_desktop_surface_from_client_link(struct wl_list * link)525 weston_desktop_surface_from_client_link(struct wl_list *link)
526 {
527 struct weston_desktop_surface *surface;
528
529 surface = wl_container_of(link, surface, client_link);
530 return surface;
531 }
532
533 struct wl_list *
weston_desktop_surface_get_client_link(struct weston_desktop_surface * surface)534 weston_desktop_surface_get_client_link(struct weston_desktop_surface *surface)
535 {
536 return &surface->client_link;
537 }
538
539 bool
weston_desktop_surface_has_implementation(struct weston_desktop_surface * surface,const struct weston_desktop_surface_implementation * implementation)540 weston_desktop_surface_has_implementation(struct weston_desktop_surface *surface,
541 const struct weston_desktop_surface_implementation *implementation)
542 {
543 return surface->implementation == implementation;
544 }
545
546 const struct weston_desktop_surface_implementation *
weston_desktop_surface_get_implementation(struct weston_desktop_surface * surface)547 weston_desktop_surface_get_implementation(struct weston_desktop_surface *surface)
548 {
549 return surface->implementation;
550 }
551
552 void *
weston_desktop_surface_get_implementation_data(struct weston_desktop_surface * surface)553 weston_desktop_surface_get_implementation_data(struct weston_desktop_surface *surface)
554 {
555 return surface->implementation_data;
556 }
557
558 struct weston_desktop_surface *
weston_desktop_surface_get_parent(struct weston_desktop_surface * surface)559 weston_desktop_surface_get_parent(struct weston_desktop_surface *surface)
560 {
561 return surface->parent;
562 }
563
564 bool
weston_desktop_surface_get_grab(struct weston_desktop_surface * surface)565 weston_desktop_surface_get_grab(struct weston_desktop_surface *surface)
566 {
567 return !wl_list_empty(&surface->grab_link);
568 }
569
570 WL_EXPORT struct weston_desktop_client *
weston_desktop_surface_get_client(struct weston_desktop_surface * surface)571 weston_desktop_surface_get_client(struct weston_desktop_surface *surface)
572 {
573 return surface->client;
574 }
575
576 WL_EXPORT void *
weston_desktop_surface_get_user_data(struct weston_desktop_surface * surface)577 weston_desktop_surface_get_user_data(struct weston_desktop_surface *surface)
578 {
579 return surface->user_data;
580 }
581
582 WL_EXPORT struct weston_surface *
weston_desktop_surface_get_surface(struct weston_desktop_surface * surface)583 weston_desktop_surface_get_surface(struct weston_desktop_surface *surface)
584 {
585 return surface->surface;
586 }
587
588 WL_EXPORT const char *
weston_desktop_surface_get_title(struct weston_desktop_surface * surface)589 weston_desktop_surface_get_title(struct weston_desktop_surface *surface)
590 {
591 return surface->title;
592 }
593
594 WL_EXPORT const char *
weston_desktop_surface_get_app_id(struct weston_desktop_surface * surface)595 weston_desktop_surface_get_app_id(struct weston_desktop_surface *surface)
596 {
597 return surface->app_id;
598 }
599
600 WL_EXPORT pid_t
weston_desktop_surface_get_pid(struct weston_desktop_surface * surface)601 weston_desktop_surface_get_pid(struct weston_desktop_surface *surface)
602 {
603 pid_t pid;
604
605 if (surface->pid != -1) {
606 pid = surface->pid;
607 } else {
608 struct weston_desktop_client *client =
609 weston_desktop_surface_get_client(surface);
610 struct wl_client *wl_client =
611 weston_desktop_client_get_client(client);
612
613 /* wl_client should always be valid, because only in the
614 * xwayland case it wouldn't be, but in that case we won't
615 * reach here, as the pid is initialized to 0. */
616 assert(wl_client);
617 wl_client_get_credentials(wl_client, &pid, NULL, NULL);
618 }
619 return pid;
620 }
621
622 WL_EXPORT bool
weston_desktop_surface_get_activated(struct weston_desktop_surface * surface)623 weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
624 {
625 if (surface->implementation->get_activated == NULL)
626 return false;
627 return surface->implementation->get_activated(surface,
628 surface->implementation_data);
629 }
630
631 WL_EXPORT bool
weston_desktop_surface_get_resizing(struct weston_desktop_surface * surface)632 weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
633 {
634 if (surface->implementation->get_resizing == NULL)
635 return false;
636 return surface->implementation->get_resizing(surface,
637 surface->implementation_data);
638 }
639
640 WL_EXPORT bool
weston_desktop_surface_get_maximized(struct weston_desktop_surface * surface)641 weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
642 {
643 if (surface->implementation->get_maximized == NULL)
644 return false;
645 return surface->implementation->get_maximized(surface,
646 surface->implementation_data);
647 }
648
649 WL_EXPORT bool
weston_desktop_surface_get_fullscreen(struct weston_desktop_surface * surface)650 weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
651 {
652 if (surface->implementation->get_fullscreen == NULL)
653 return false;
654 return surface->implementation->get_fullscreen(surface,
655 surface->implementation_data);
656 }
657
658 WL_EXPORT struct weston_geometry
weston_desktop_surface_get_geometry(struct weston_desktop_surface * surface)659 weston_desktop_surface_get_geometry(struct weston_desktop_surface *surface)
660 {
661 if (surface->has_geometry)
662 return surface->geometry;
663 return weston_surface_get_bounding_box(surface->surface);
664 }
665
666 WL_EXPORT struct weston_size
weston_desktop_surface_get_max_size(struct weston_desktop_surface * surface)667 weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface)
668 {
669 struct weston_size size = { 0, 0 };
670
671 if (surface->implementation->get_max_size == NULL)
672 return size;
673 return surface->implementation->get_max_size(surface,
674 surface->implementation_data);
675 }
676
677 WL_EXPORT struct weston_size
weston_desktop_surface_get_min_size(struct weston_desktop_surface * surface)678 weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface)
679 {
680 struct weston_size size = { 0, 0 };
681
682 if (surface->implementation->get_min_size == NULL)
683 return size;
684 return surface->implementation->get_min_size(surface,
685 surface->implementation_data);
686 }
687
688 void
weston_desktop_surface_set_title(struct weston_desktop_surface * surface,const char * title)689 weston_desktop_surface_set_title(struct weston_desktop_surface *surface,
690 const char *title)
691 {
692 char *tmp, *old;
693
694 tmp = strdup(title);
695 if (tmp == NULL)
696 return;
697
698 old = surface->title;
699 surface->title = tmp;
700 wl_signal_emit(&surface->metadata_signal, surface);
701 free(old);
702 }
703
704 void
weston_desktop_surface_set_app_id(struct weston_desktop_surface * surface,const char * app_id)705 weston_desktop_surface_set_app_id(struct weston_desktop_surface *surface,
706 const char *app_id)
707 {
708 char *tmp, *old;
709
710 tmp = strdup(app_id);
711 if (tmp == NULL)
712 return;
713
714 old = surface->app_id;
715 surface->app_id = tmp;
716 wl_signal_emit(&surface->metadata_signal, surface);
717 free(old);
718 }
719
720 void
weston_desktop_surface_set_pid(struct weston_desktop_surface * surface,pid_t pid)721 weston_desktop_surface_set_pid(struct weston_desktop_surface *surface,
722 pid_t pid)
723 {
724 surface->pid = pid;
725 }
726
727 void
weston_desktop_surface_set_geometry(struct weston_desktop_surface * surface,struct weston_geometry geometry)728 weston_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
735 void
weston_desktop_surface_set_relative_to(struct weston_desktop_surface * surface,struct weston_desktop_surface * parent,int32_t x,int32_t y,bool use_geometry)736 weston_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
784 void
weston_desktop_surface_unset_relative_to(struct weston_desktop_surface * surface)785 weston_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
800 void
weston_desktop_surface_popup_grab(struct weston_desktop_surface * surface,struct weston_desktop_seat * seat,uint32_t serial)801 weston_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
813 void
weston_desktop_surface_popup_ungrab(struct weston_desktop_surface * surface,struct weston_desktop_seat * seat)814 weston_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
820 void
weston_desktop_surface_popup_dismiss(struct weston_desktop_surface * surface)821 weston_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 }
831