• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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