2 * Copyright © 2019 Collabora, Ltd.
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #include "ivi-compositor.h"
34 #include <sys/socket.h>
35 #include <sys/types.h>
37 #include <libweston/libweston.h>
38 #include <libweston/config-parser.h>
40 #include "shared/os-compatibility.h"
42 #include "agl-shell-server-protocol.h"
43 #include "agl-shell-desktop-server-protocol.h"
46 create_black_surface_view(struct ivi_output *output);
49 ivi_set_desktop_surface(struct ivi_surface *surface)
51 struct desktop_client *dclient;
52 struct ivi_compositor *ivi = surface->ivi;
53 assert(surface->role == IVI_SURFACE_ROLE_NONE);
55 surface->role = IVI_SURFACE_ROLE_DESKTOP;
56 wl_list_insert(&surface->ivi->surfaces, &surface->link);
58 /* advertise to all desktop clients the new surface */
59 wl_list_for_each(dclient, &ivi->desktop_clients, link) {
61 weston_desktop_surface_get_app_id(surface->dsurface);
62 agl_shell_desktop_send_application(dclient->resource, app_id);
67 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
69 struct ivi_compositor *ivi = surface->ivi;
70 assert(surface->role == IVI_SURFACE_ROLE_NONE);
72 surface->role = IVI_SURFACE_ROLE_POPUP;
73 wl_list_insert(&ivi->surfaces, &surface->link);
77 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
79 struct ivi_compositor *ivi = surface->ivi;
80 assert(surface->role == IVI_SURFACE_ROLE_NONE);
82 surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
83 wl_list_insert(&ivi->surfaces, &surface->link);
87 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
89 struct ivi_compositor *ivi = surface->ivi;
90 struct weston_view *view;
91 struct ivi_output *output = surface->remote.output;
93 assert(surface->role == IVI_SURFACE_ROLE_NONE);
95 /* remote type are the same as desktop just that client can tell
96 * the compositor to start on another output */
97 surface->role = IVI_SURFACE_ROLE_REMOTE;
99 /* if thew black surface view is mapped on the mean we need
100 * to remove it in order to start showing the 'remote' surface
101 * just being added */
102 view = output->fullscreen_view.fs->view;
103 if (view->is_mapped || view->surface->is_mapped)
104 remove_black_surface(output);
106 wl_list_insert(&ivi->surfaces, &surface->link);
111 ivi_set_desktop_surface_split(struct ivi_surface *surface)
113 struct ivi_compositor *ivi = surface->ivi;
114 assert(surface->role == IVI_SURFACE_ROLE_NONE);
116 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
117 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
119 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
121 wl_list_insert(&ivi->surfaces, &surface->link);
125 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput,
126 int x, int y, const char *app_id)
128 struct ivi_compositor *ivi = ioutput->ivi;
129 size_t len_app_id = strlen(app_id);
131 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
133 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
134 memcpy(p_popup->app_id, app_id, len_app_id);
135 p_popup->ioutput = ioutput;
139 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
143 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
146 struct ivi_compositor *ivi = ioutput->ivi;
147 size_t len_app_id = strlen(app_id);
149 struct pending_fullscreen *fs = zalloc(sizeof(*fs));
151 fs->app_id = zalloc(sizeof(char) * (len_app_id + 1));
152 memcpy(fs->app_id, app_id, len_app_id);
154 fs->ioutput = ioutput;
156 wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link);
160 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
161 const char *app_id, uint32_t orientation)
163 struct ivi_compositor *ivi = ioutput->ivi;
164 struct ivi_surface *surf;
165 size_t len_app_id = strlen(app_id);
166 struct pending_split *split;
168 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
169 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
172 /* more than one is un-supported, do note we need to do
173 * conversion for surface roles instead of using the protocol ones */
174 wl_list_for_each(surf, &ivi->surfaces, link)
175 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
176 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
179 split = zalloc(sizeof(*split));
180 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
181 memcpy(split->app_id, app_id, len_app_id);
183 split->ioutput = ioutput;
184 split->orientation = orientation;
186 wl_list_insert(&ivi->split_pending_apps, &split->link);
190 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
193 struct ivi_compositor *ivi = ioutput->ivi;
194 size_t len_app_id = strlen(app_id);
196 struct pending_remote *remote = zalloc(sizeof(*remote));
198 remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
199 memcpy(remote->app_id, app_id, len_app_id);
201 remote->ioutput = ioutput;
203 wl_list_insert(&ivi->remote_pending_apps, &remote->link);
208 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
211 wl_list_remove(&split->link);
216 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
219 wl_list_remove(&fs->link);
224 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
226 free(p_popup->app_id);
227 wl_list_remove(&p_popup->link);
232 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
234 free(remote->app_id);
235 wl_list_remove(&remote->link);
240 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
242 struct ivi_compositor *ivi = surface->ivi;
243 struct pending_popup *p_popup, *next_p_popup;
244 const char *_app_id =
245 weston_desktop_surface_get_app_id(surface->dsurface);
247 if (wl_list_empty(&ivi->popup_pending_apps))
250 wl_list_for_each_safe(p_popup, next_p_popup,
251 &ivi->popup_pending_apps, link) {
252 if (!strcmp(_app_id, p_popup->app_id)) {
253 surface->popup.output = p_popup->ioutput;
254 surface->popup.x = p_popup->x;
255 surface->popup.y = p_popup->y;
256 ivi_remove_pending_desktop_surface_popup(p_popup);
265 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
267 struct pending_split *split_surf, *next_split_surf;
268 struct ivi_compositor *ivi = surface->ivi;
269 const char *_app_id =
270 weston_desktop_surface_get_app_id(surface->dsurface);
272 if (wl_list_empty(&ivi->split_pending_apps))
275 wl_list_for_each_safe(split_surf, next_split_surf,
276 &ivi->split_pending_apps, link) {
277 if (!strcmp(_app_id, split_surf->app_id)) {
278 surface->split.output = split_surf->ioutput;
279 surface->split.orientation = split_surf->orientation;
280 ivi_remove_pending_desktop_surface_split(split_surf);
289 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
291 struct pending_fullscreen *fs_surf, *next_fs_surf;
292 struct ivi_compositor *ivi = surface->ivi;
293 const char *_app_id =
294 weston_desktop_surface_get_app_id(surface->dsurface);
296 if (wl_list_empty(&ivi->fullscreen_pending_apps))
299 wl_list_for_each_safe(fs_surf, next_fs_surf,
300 &ivi->fullscreen_pending_apps, link) {
301 if (!strcmp(_app_id, fs_surf->app_id)) {
302 surface->fullscreen.output = fs_surf->ioutput;
303 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
312 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
314 struct pending_remote *remote_surf, *next_remote_surf;
315 struct ivi_compositor *ivi = surface->ivi;
316 const char *_app_id =
317 weston_desktop_surface_get_app_id(surface->dsurface);
319 if (wl_list_empty(&ivi->remote_pending_apps))
322 wl_list_for_each_safe(remote_surf, next_remote_surf,
323 &ivi->remote_pending_apps, link) {
324 if (!strcmp(_app_id, remote_surf->app_id)) {
325 surface->remote.output = remote_surf->ioutput;
326 ivi_remove_pending_desktop_surface_remote(remote_surf);
336 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
340 ret = ivi_check_pending_desktop_surface_popup(surface);
342 ivi_set_desktop_surface_popup(surface);
346 ret = ivi_check_pending_desktop_surface_split(surface);
348 ivi_set_desktop_surface_split(surface);
352 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
354 ivi_set_desktop_surface_fullscreen(surface);
358 ret = ivi_check_pending_desktop_surface_remote(surface);
360 ivi_set_desktop_surface_remote(surface);
364 /* if we end up here means we have a regular desktop app and
365 * try to activate it */
366 ivi_set_desktop_surface(surface);
367 ivi_layout_desktop_committed(surface);
371 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
373 struct ivi_output *out;
375 wl_list_for_each(out, &ivi->outputs, link) {
376 create_black_surface_view(out);
377 insert_black_surface(out);
382 ivi_shell_init(struct ivi_compositor *ivi)
384 weston_layer_init(&ivi->hidden, ivi->compositor);
385 weston_layer_init(&ivi->background, ivi->compositor);
386 weston_layer_init(&ivi->normal, ivi->compositor);
387 weston_layer_init(&ivi->panel, ivi->compositor);
388 weston_layer_init(&ivi->popup, ivi->compositor);
389 weston_layer_init(&ivi->fullscreen, ivi->compositor);
391 weston_layer_set_position(&ivi->hidden,
392 WESTON_LAYER_POSITION_HIDDEN);
393 weston_layer_set_position(&ivi->background,
394 WESTON_LAYER_POSITION_BACKGROUND);
395 weston_layer_set_position(&ivi->normal,
396 WESTON_LAYER_POSITION_NORMAL);
397 weston_layer_set_position(&ivi->panel,
398 WESTON_LAYER_POSITION_UI);
399 weston_layer_set_position(&ivi->popup,
400 WESTON_LAYER_POSITION_TOP_UI);
401 weston_layer_set_position(&ivi->fullscreen,
402 WESTON_LAYER_POSITION_FULLSCREEN);
408 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
410 struct ivi_surface *surface;
412 wl_list_for_each(surface, &ivi->surfaces, link) {
414 weston_desktop_surface_get_app_id(surface->dsurface);
415 agl_shell_desktop_send_application(resource, app_id);
420 client_exec(const char *command, int fd)
425 /* Don't give the child our signal mask */
427 sigprocmask(SIG_UNBLOCK, &sig, NULL);
429 /* Launch clients as the user; don't give them the wrong euid */
430 if (seteuid(getuid()) == -1) {
431 weston_log("seteuid failed: %s\n", strerror(errno));
435 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
436 * clobbering fd, as we'll exit/exec either way.
440 weston_log("dup failed: %s\n", strerror(errno));
444 snprintf(s, sizeof s, "%d", fd);
445 setenv("WAYLAND_SOCKET", s, 1);
447 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
448 weston_log("executing '%s' failed: %s", command, strerror(errno));
451 static struct wl_client *
452 launch_shell_client(struct ivi_compositor *ivi, const char *command)
454 struct wl_client *client;
458 weston_log("launching' %s'\n", command);
460 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
461 weston_log("socketpair failed while launching '%s': %s\n",
462 command, strerror(errno));
470 weston_log("fork failed while launching '%s': %s\n",
471 command, strerror(errno));
476 client_exec(command, sock[1]);
481 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
484 weston_log("Failed to create wayland client for '%s'",
493 ivi_launch_shell_client(struct ivi_compositor *ivi)
495 struct weston_config_section *section;
496 char *command = NULL;
498 section = weston_config_get_section(ivi->config, "shell-client",
501 weston_config_section_get_string(section, "command",
507 ivi->shell_client.client = launch_shell_client(ivi, command);
508 if (!ivi->shell_client.client)
515 destroy_black_view(struct wl_listener *listener, void *data)
517 struct fullscreen_view *fs =
518 wl_container_of(listener, fs, fs_destroy);
522 if (fs->fs->view && fs->fs->view->surface) {
523 weston_surface_destroy(fs->fs->view->surface);
528 wl_list_remove(&fs->fs_destroy.link);
534 create_black_surface_view(struct ivi_output *output)
536 struct weston_surface *surface = NULL;
537 struct weston_view *view;
538 struct ivi_compositor *ivi = output->ivi;
539 struct weston_compositor *wc= ivi->compositor;
540 struct weston_output *woutput = output->output;
542 surface = weston_surface_create(wc);
543 view = weston_view_create(surface);
545 assert(view || surface);
547 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
548 weston_surface_set_size(surface, woutput->width, woutput->height);
549 weston_view_set_position(view, woutput->x, woutput->y);
551 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
552 output->fullscreen_view.fs->view = view;
554 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
555 wl_signal_add(&woutput->destroy_signal,
556 &output->fullscreen_view.fs_destroy);
560 remove_black_surface(struct ivi_output *output)
562 struct weston_view *view = output->fullscreen_view.fs->view;
564 assert(view->is_mapped == true ||
565 view->surface->is_mapped == true);
567 view->is_mapped = false;
568 view->surface->is_mapped = false;
570 weston_layer_entry_remove(&view->layer_link);
571 weston_view_update_transform(view);
573 weston_output_damage(output->output);
577 insert_black_surface(struct ivi_output *output)
579 struct weston_view *view = output->fullscreen_view.fs->view;
581 if (view->is_mapped || view->surface->is_mapped)
584 weston_layer_entry_remove(&view->layer_link);
585 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
588 view->is_mapped = true;
589 view->surface->is_mapped = true;
591 weston_view_update_transform(view);
592 weston_output_damage(output->output);
596 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
598 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
599 struct ivi_output *output;
600 struct ivi_surface *surface, *tmp;
602 /* Init already finished. Do nothing */
603 if (ivi->shell_client.ready)
606 ivi->shell_client.ready = true;
608 wl_list_for_each(output, &ivi->outputs, link) {
609 remove_black_surface(output);
610 ivi_layout_init(ivi, output);
613 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
614 wl_list_remove(&surface->link);
615 ivi_check_pending_desktop_surface(surface);
620 shell_set_background(struct wl_client *client,
621 struct wl_resource *shell_res,
622 struct wl_resource *surface_res,
623 struct wl_resource *output_res)
625 struct weston_head *head = weston_head_from_resource(output_res);
626 struct weston_output *woutput = weston_head_get_output(head);
627 struct ivi_output *output = to_ivi_output(woutput);
628 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
629 struct weston_desktop_surface *dsurface;
630 struct ivi_surface *surface;
632 dsurface = weston_surface_get_desktop_surface(wsurface);
634 wl_resource_post_error(shell_res,
635 AGL_SHELL_ERROR_INVALID_ARGUMENT,
636 "surface must be a desktop surface");
640 surface = weston_desktop_surface_get_user_data(dsurface);
641 if (surface->role != IVI_SURFACE_ROLE_NONE) {
642 wl_resource_post_error(shell_res,
643 AGL_SHELL_ERROR_INVALID_ARGUMENT,
644 "surface already has another ivi role");
648 if (output->background) {
649 wl_resource_post_error(shell_res,
650 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
651 "output already has background");
655 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
656 surface->bg.output = output;
657 wl_list_remove(&surface->link);
658 wl_list_init(&surface->link);
660 output->background = surface;
662 weston_desktop_surface_set_maximized(dsurface, true);
663 weston_desktop_surface_set_size(dsurface,
664 output->output->width,
665 output->output->height);
669 shell_set_panel(struct wl_client *client,
670 struct wl_resource *shell_res,
671 struct wl_resource *surface_res,
672 struct wl_resource *output_res,
675 struct weston_head *head = weston_head_from_resource(output_res);
676 struct weston_output *woutput = weston_head_get_output(head);
677 struct ivi_output *output = to_ivi_output(woutput);
678 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
679 struct weston_desktop_surface *dsurface;
680 struct ivi_surface *surface;
681 struct ivi_surface **member;
682 int32_t width = 0, height = 0;
684 dsurface = weston_surface_get_desktop_surface(wsurface);
686 wl_resource_post_error(shell_res,
687 AGL_SHELL_ERROR_INVALID_ARGUMENT,
688 "surface must be a desktop surface");
692 surface = weston_desktop_surface_get_user_data(dsurface);
693 if (surface->role != IVI_SURFACE_ROLE_NONE) {
694 wl_resource_post_error(shell_res,
695 AGL_SHELL_ERROR_INVALID_ARGUMENT,
696 "surface already has another ivi role");
701 case AGL_SHELL_EDGE_TOP:
702 member = &output->top;
704 case AGL_SHELL_EDGE_BOTTOM:
705 member = &output->bottom;
707 case AGL_SHELL_EDGE_LEFT:
708 member = &output->left;
710 case AGL_SHELL_EDGE_RIGHT:
711 member = &output->right;
714 wl_resource_post_error(shell_res,
715 AGL_SHELL_ERROR_INVALID_ARGUMENT,
716 "invalid edge for panel");
721 wl_resource_post_error(shell_res,
722 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
723 "output already has panel on this edge");
727 surface->role = IVI_SURFACE_ROLE_PANEL;
728 surface->panel.output = output;
729 surface->panel.edge = edge;
730 wl_list_remove(&surface->link);
731 wl_list_init(&surface->link);
735 switch (surface->panel.edge) {
736 case AGL_SHELL_EDGE_TOP:
737 case AGL_SHELL_EDGE_BOTTOM:
738 width = woutput->width;
740 case AGL_SHELL_EDGE_LEFT:
741 case AGL_SHELL_EDGE_RIGHT:
742 height = woutput->height;
746 weston_desktop_surface_set_size(dsurface, width, height);
751 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
752 const char *data, uint32_t app_state)
754 struct desktop_client *dclient;
756 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
757 struct ivi_policy *policy = ivi->policy;
759 /* FIXME: should queue it here and see when binding agl-shell-desktop
760 * if there are any to be sent */
764 if (policy && policy->api.surface_advertise_state_change &&
765 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
769 app_role = surf->role;
770 if (app_role == IVI_SURFACE_ROLE_POPUP)
771 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
773 wl_list_for_each(dclient, &ivi->desktop_clients, link)
774 agl_shell_desktop_send_state_app(dclient->resource, app_id,
775 data, app_state, app_role);
779 shell_activate_app(struct wl_client *client,
780 struct wl_resource *shell_res,
782 struct wl_resource *output_res)
784 struct weston_head *head = weston_head_from_resource(output_res);
785 struct weston_output *woutput = weston_head_get_output(head);
786 struct ivi_output *output = to_ivi_output(woutput);
788 ivi_layout_activate(output, app_id);
792 shell_desktop_activate_app(struct wl_client *client,
793 struct wl_resource *shell_res,
794 const char *app_id, const char *data,
795 struct wl_resource *output_res)
797 struct weston_head *head = weston_head_from_resource(output_res);
798 struct weston_output *woutput = weston_head_get_output(head);
799 struct ivi_output *output = to_ivi_output(woutput);
801 ivi_layout_activate(output, app_id);
802 shell_advertise_app_state(output->ivi, app_id,
803 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
807 shell_deactivate_app(struct wl_client *client,
808 struct wl_resource *shell_res,
811 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
812 struct ivi_compositor *ivi = dclient->ivi;
814 ivi_layout_deactivate(ivi, app_id);
815 shell_advertise_app_state(ivi, app_id,
816 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
819 static const struct agl_shell_interface agl_shell_implementation = {
820 .ready = shell_ready,
821 .set_background = shell_set_background,
822 .set_panel = shell_set_panel,
823 .activate_app = shell_activate_app,
827 shell_desktop_set_app_property(struct wl_client *client,
828 struct wl_resource *shell_res,
829 const char *app_id, uint32_t role,
830 int x, int y, struct wl_resource *output_res)
832 struct weston_head *head = weston_head_from_resource(output_res);
833 struct weston_output *woutput = weston_head_get_output(head);
834 struct ivi_output *output = to_ivi_output(woutput);
837 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
838 ivi_set_pending_desktop_surface_popup(output, x, y, app_id);
840 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
841 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
843 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
844 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
845 ivi_set_pending_desktop_surface_split(output, app_id, role);
847 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
848 ivi_set_pending_desktop_surface_remote(output, app_id);
855 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
856 .activate_app = shell_desktop_activate_app,
857 .set_app_property = shell_desktop_set_app_property,
858 .deactivate_app = shell_deactivate_app,
862 unbind_agl_shell(struct wl_resource *resource)
864 struct ivi_compositor *ivi;
865 struct ivi_output *output;
866 struct ivi_surface *surf, *surf_tmp;
868 ivi = wl_resource_get_user_data(resource);
869 wl_list_for_each(output, &ivi->outputs, link) {
870 /* reset the active surf if there's one present */
871 if (output->active) {
872 output->active->view->is_mapped = false;
873 output->active->view->surface->is_mapped = false;
875 weston_layer_entry_remove(&output->active->view->layer_link);
876 output->active = NULL;
879 insert_black_surface(output);
882 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
883 wl_list_remove(&surf->link);
884 wl_list_init(&surf->link);
887 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
888 wl_list_remove(&surf->link);
889 wl_list_init(&surf->link);
892 wl_list_init(&ivi->surfaces);
893 wl_list_init(&ivi->pending_surfaces);
895 ivi->shell_client.ready = false;
896 ivi->shell_client.resource = NULL;
897 ivi->shell_client.client = NULL;
901 bind_agl_shell(struct wl_client *client,
902 void *data, uint32_t version, uint32_t id)
904 struct ivi_compositor *ivi = data;
905 struct wl_resource *resource;
907 resource = wl_resource_create(client, &agl_shell_interface,
910 wl_client_post_no_memory(client);
915 if (ivi->shell_client.client != client) {
916 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
917 "client not authorized to use agl_shell");
922 if (ivi->shell_client.resource) {
923 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
924 "agl_shell has already been bound");
928 wl_resource_set_implementation(resource, &agl_shell_implementation,
929 ivi, unbind_agl_shell);
930 ivi->shell_client.resource = resource;
934 unbind_agl_shell_desktop(struct wl_resource *resource)
936 struct desktop_client *dclient = wl_resource_get_user_data(resource);
938 wl_list_remove(&dclient->link);
943 bind_agl_shell_desktop(struct wl_client *client,
944 void *data, uint32_t version, uint32_t id)
946 struct ivi_compositor *ivi = data;
947 struct wl_resource *resource;
948 struct desktop_client *dclient = zalloc(sizeof(*dclient));
951 wl_client_post_no_memory(client);
955 resource = wl_resource_create(client, &agl_shell_desktop_interface,
959 wl_client_post_no_memory(client);
963 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
964 dclient, unbind_agl_shell_desktop);
966 dclient->resource = resource;
967 wl_list_insert(&ivi->desktop_clients, &dclient->link);
969 /* advertise xdg surfaces */
970 ivi_shell_advertise_xdg_surfaces(ivi, resource);
974 ivi_shell_create_global(struct ivi_compositor *ivi)
976 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
977 &agl_shell_interface, 1,
978 ivi, bind_agl_shell);
979 if (!ivi->agl_shell) {
980 weston_log("Failed to create wayland global.\n");
984 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
985 &agl_shell_desktop_interface, 1,
986 ivi, bind_agl_shell_desktop);
987 if (!ivi->agl_shell_desktop) {
988 weston_log("Failed to create wayland global (agl_shell_desktop).\n");