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 if (output->background)
610 remove_black_surface(output);
611 ivi_layout_init(ivi, output);
614 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
615 wl_list_remove(&surface->link);
616 ivi_check_pending_desktop_surface(surface);
621 shell_set_background(struct wl_client *client,
622 struct wl_resource *shell_res,
623 struct wl_resource *surface_res,
624 struct wl_resource *output_res)
626 struct weston_head *head = weston_head_from_resource(output_res);
627 struct weston_output *woutput = weston_head_get_output(head);
628 struct ivi_output *output = to_ivi_output(woutput);
629 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
630 struct weston_desktop_surface *dsurface;
631 struct ivi_surface *surface;
633 dsurface = weston_surface_get_desktop_surface(wsurface);
635 wl_resource_post_error(shell_res,
636 AGL_SHELL_ERROR_INVALID_ARGUMENT,
637 "surface must be a desktop surface");
641 surface = weston_desktop_surface_get_user_data(dsurface);
642 if (surface->role != IVI_SURFACE_ROLE_NONE) {
643 wl_resource_post_error(shell_res,
644 AGL_SHELL_ERROR_INVALID_ARGUMENT,
645 "surface already has another ivi role");
649 if (output->background) {
650 wl_resource_post_error(shell_res,
651 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
652 "output already has background");
656 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
657 surface->bg.output = output;
658 wl_list_remove(&surface->link);
659 wl_list_init(&surface->link);
661 output->background = surface;
663 weston_desktop_surface_set_maximized(dsurface, true);
664 weston_desktop_surface_set_size(dsurface,
665 output->output->width,
666 output->output->height);
670 shell_set_panel(struct wl_client *client,
671 struct wl_resource *shell_res,
672 struct wl_resource *surface_res,
673 struct wl_resource *output_res,
676 struct weston_head *head = weston_head_from_resource(output_res);
677 struct weston_output *woutput = weston_head_get_output(head);
678 struct ivi_output *output = to_ivi_output(woutput);
679 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
680 struct weston_desktop_surface *dsurface;
681 struct ivi_surface *surface;
682 struct ivi_surface **member;
683 int32_t width = 0, height = 0;
685 dsurface = weston_surface_get_desktop_surface(wsurface);
687 wl_resource_post_error(shell_res,
688 AGL_SHELL_ERROR_INVALID_ARGUMENT,
689 "surface must be a desktop surface");
693 surface = weston_desktop_surface_get_user_data(dsurface);
694 if (surface->role != IVI_SURFACE_ROLE_NONE) {
695 wl_resource_post_error(shell_res,
696 AGL_SHELL_ERROR_INVALID_ARGUMENT,
697 "surface already has another ivi role");
702 case AGL_SHELL_EDGE_TOP:
703 member = &output->top;
705 case AGL_SHELL_EDGE_BOTTOM:
706 member = &output->bottom;
708 case AGL_SHELL_EDGE_LEFT:
709 member = &output->left;
711 case AGL_SHELL_EDGE_RIGHT:
712 member = &output->right;
715 wl_resource_post_error(shell_res,
716 AGL_SHELL_ERROR_INVALID_ARGUMENT,
717 "invalid edge for panel");
722 wl_resource_post_error(shell_res,
723 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
724 "output already has panel on this edge");
728 surface->role = IVI_SURFACE_ROLE_PANEL;
729 surface->panel.output = output;
730 surface->panel.edge = edge;
731 wl_list_remove(&surface->link);
732 wl_list_init(&surface->link);
736 switch (surface->panel.edge) {
737 case AGL_SHELL_EDGE_TOP:
738 case AGL_SHELL_EDGE_BOTTOM:
739 width = woutput->width;
741 case AGL_SHELL_EDGE_LEFT:
742 case AGL_SHELL_EDGE_RIGHT:
743 height = woutput->height;
747 weston_desktop_surface_set_size(dsurface, width, height);
752 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
753 const char *data, uint32_t app_state)
755 struct desktop_client *dclient;
757 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
758 struct ivi_policy *policy = ivi->policy;
760 /* FIXME: should queue it here and see when binding agl-shell-desktop
761 * if there are any to be sent */
765 if (policy && policy->api.surface_advertise_state_change &&
766 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
770 app_role = surf->role;
771 if (app_role == IVI_SURFACE_ROLE_POPUP)
772 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
774 wl_list_for_each(dclient, &ivi->desktop_clients, link)
775 agl_shell_desktop_send_state_app(dclient->resource, app_id,
776 data, app_state, app_role);
780 shell_activate_app(struct wl_client *client,
781 struct wl_resource *shell_res,
783 struct wl_resource *output_res)
785 struct weston_head *head = weston_head_from_resource(output_res);
786 struct weston_output *woutput = weston_head_get_output(head);
787 struct ivi_output *output = to_ivi_output(woutput);
789 ivi_layout_activate(output, app_id);
793 shell_desktop_activate_app(struct wl_client *client,
794 struct wl_resource *shell_res,
795 const char *app_id, const char *data,
796 struct wl_resource *output_res)
798 struct weston_head *head = weston_head_from_resource(output_res);
799 struct weston_output *woutput = weston_head_get_output(head);
800 struct ivi_output *output = to_ivi_output(woutput);
802 ivi_layout_activate(output, app_id);
803 shell_advertise_app_state(output->ivi, app_id,
804 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
808 shell_deactivate_app(struct wl_client *client,
809 struct wl_resource *shell_res,
812 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
813 struct ivi_compositor *ivi = dclient->ivi;
815 ivi_layout_deactivate(ivi, app_id);
816 shell_advertise_app_state(ivi, app_id,
817 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
820 static const struct agl_shell_interface agl_shell_implementation = {
821 .ready = shell_ready,
822 .set_background = shell_set_background,
823 .set_panel = shell_set_panel,
824 .activate_app = shell_activate_app,
828 shell_desktop_set_app_property(struct wl_client *client,
829 struct wl_resource *shell_res,
830 const char *app_id, uint32_t role,
831 int x, int y, struct wl_resource *output_res)
833 struct weston_head *head = weston_head_from_resource(output_res);
834 struct weston_output *woutput = weston_head_get_output(head);
835 struct ivi_output *output = to_ivi_output(woutput);
838 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
839 ivi_set_pending_desktop_surface_popup(output, x, y, app_id);
841 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
842 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
844 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
845 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
846 ivi_set_pending_desktop_surface_split(output, app_id, role);
848 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
849 ivi_set_pending_desktop_surface_remote(output, app_id);
856 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
857 .activate_app = shell_desktop_activate_app,
858 .set_app_property = shell_desktop_set_app_property,
859 .deactivate_app = shell_deactivate_app,
863 unbind_agl_shell(struct wl_resource *resource)
865 struct ivi_compositor *ivi;
866 struct ivi_output *output;
867 struct ivi_surface *surf, *surf_tmp;
869 ivi = wl_resource_get_user_data(resource);
870 wl_list_for_each(output, &ivi->outputs, link) {
871 /* reset the active surf if there's one present */
872 if (output->active) {
873 output->active->view->is_mapped = false;
874 output->active->view->surface->is_mapped = false;
876 weston_layer_entry_remove(&output->active->view->layer_link);
877 output->active = NULL;
880 insert_black_surface(output);
883 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
884 wl_list_remove(&surf->link);
885 wl_list_init(&surf->link);
888 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
889 wl_list_remove(&surf->link);
890 wl_list_init(&surf->link);
893 wl_list_init(&ivi->surfaces);
894 wl_list_init(&ivi->pending_surfaces);
896 ivi->shell_client.ready = false;
897 ivi->shell_client.resource = NULL;
898 ivi->shell_client.client = NULL;
902 bind_agl_shell(struct wl_client *client,
903 void *data, uint32_t version, uint32_t id)
905 struct ivi_compositor *ivi = data;
906 struct wl_resource *resource;
908 resource = wl_resource_create(client, &agl_shell_interface,
911 wl_client_post_no_memory(client);
916 if (ivi->shell_client.client != client) {
917 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
918 "client not authorized to use agl_shell");
923 if (ivi->shell_client.resource) {
924 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
925 "agl_shell has already been bound");
929 wl_resource_set_implementation(resource, &agl_shell_implementation,
930 ivi, unbind_agl_shell);
931 ivi->shell_client.resource = resource;
935 unbind_agl_shell_desktop(struct wl_resource *resource)
937 struct desktop_client *dclient = wl_resource_get_user_data(resource);
939 wl_list_remove(&dclient->link);
944 bind_agl_shell_desktop(struct wl_client *client,
945 void *data, uint32_t version, uint32_t id)
947 struct ivi_compositor *ivi = data;
948 struct wl_resource *resource;
949 struct desktop_client *dclient = zalloc(sizeof(*dclient));
952 wl_client_post_no_memory(client);
956 resource = wl_resource_create(client, &agl_shell_desktop_interface,
960 wl_client_post_no_memory(client);
964 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
965 dclient, unbind_agl_shell_desktop);
967 dclient->resource = resource;
968 wl_list_insert(&ivi->desktop_clients, &dclient->link);
970 /* advertise xdg surfaces */
971 ivi_shell_advertise_xdg_surfaces(ivi, resource);
975 ivi_shell_create_global(struct ivi_compositor *ivi)
977 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
978 &agl_shell_interface, 1,
979 ivi, bind_agl_shell);
980 if (!ivi->agl_shell) {
981 weston_log("Failed to create wayland global.\n");
985 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
986 &agl_shell_desktop_interface, 1,
987 ivi, bind_agl_shell_desktop);
988 if (!ivi->agl_shell_desktop) {
989 weston_log("Failed to create wayland global (agl_shell_desktop).\n");