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 insert_black_surface(struct ivi_output *output);
52 ivi_set_desktop_surface(struct ivi_surface *surface)
54 struct desktop_client *dclient;
55 struct ivi_compositor *ivi = surface->ivi;
56 assert(surface->role == IVI_SURFACE_ROLE_NONE);
58 surface->role = IVI_SURFACE_ROLE_DESKTOP;
59 wl_list_insert(&surface->ivi->surfaces, &surface->link);
61 /* advertise to all desktop clients the new surface */
62 wl_list_for_each(dclient, &ivi->desktop_clients, link) {
64 weston_desktop_surface_get_app_id(surface->dsurface);
65 agl_shell_desktop_send_application(dclient->resource, app_id);
70 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
72 struct ivi_compositor *ivi = surface->ivi;
73 assert(surface->role == IVI_SURFACE_ROLE_NONE);
75 surface->role = IVI_SURFACE_ROLE_POPUP;
76 wl_list_insert(&ivi->surfaces, &surface->link);
80 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
82 struct ivi_compositor *ivi = surface->ivi;
83 assert(surface->role == IVI_SURFACE_ROLE_NONE);
85 surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
86 wl_list_insert(&ivi->surfaces, &surface->link);
90 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
92 struct ivi_compositor *ivi = surface->ivi;
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;
98 wl_list_insert(&ivi->surfaces, &surface->link);
103 ivi_set_desktop_surface_split(struct ivi_surface *surface)
105 struct ivi_compositor *ivi = surface->ivi;
106 assert(surface->role == IVI_SURFACE_ROLE_NONE);
108 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
109 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
111 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
113 wl_list_insert(&ivi->surfaces, &surface->link);
117 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput,
118 int x, int y, const char *app_id)
120 struct ivi_compositor *ivi = ioutput->ivi;
121 size_t len_app_id = strlen(app_id);
123 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
125 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
126 memcpy(p_popup->app_id, app_id, len_app_id);
127 p_popup->ioutput = ioutput;
131 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
135 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
138 struct ivi_compositor *ivi = ioutput->ivi;
139 size_t len_app_id = strlen(app_id);
141 struct pending_fullscreen *fs = zalloc(sizeof(*fs));
143 fs->app_id = zalloc(sizeof(char) * (len_app_id + 1));
144 memcpy(fs->app_id, app_id, len_app_id);
146 fs->ioutput = ioutput;
148 wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link);
152 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
153 const char *app_id, uint32_t orientation)
155 struct ivi_compositor *ivi = ioutput->ivi;
156 struct ivi_surface *surf;
157 size_t len_app_id = strlen(app_id);
158 struct pending_split *split;
160 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
161 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
164 /* more than one is un-supported, do note we need to do
165 * conversion for surface roles instead of using the protocol ones */
166 wl_list_for_each(surf, &ivi->surfaces, link)
167 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
168 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
171 split = zalloc(sizeof(*split));
172 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
173 memcpy(split->app_id, app_id, len_app_id);
175 split->ioutput = ioutput;
176 split->orientation = orientation;
178 wl_list_insert(&ivi->split_pending_apps, &split->link);
182 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
185 struct ivi_compositor *ivi = ioutput->ivi;
186 size_t len_app_id = strlen(app_id);
188 struct pending_remote *remote = zalloc(sizeof(*remote));
190 remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
191 memcpy(remote->app_id, app_id, len_app_id);
193 remote->ioutput = ioutput;
195 wl_list_insert(&ivi->remote_pending_apps, &remote->link);
200 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
203 wl_list_remove(&split->link);
208 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
211 wl_list_remove(&fs->link);
216 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
218 free(p_popup->app_id);
219 wl_list_remove(&p_popup->link);
224 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
226 free(remote->app_id);
227 wl_list_remove(&remote->link);
232 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
234 struct ivi_compositor *ivi = surface->ivi;
235 struct pending_popup *p_popup, *next_p_popup;
236 const char *_app_id =
237 weston_desktop_surface_get_app_id(surface->dsurface);
239 if (wl_list_empty(&ivi->popup_pending_apps))
242 wl_list_for_each_safe(p_popup, next_p_popup,
243 &ivi->popup_pending_apps, link) {
244 if (!strcmp(_app_id, p_popup->app_id)) {
245 surface->popup.output = p_popup->ioutput;
246 surface->popup.x = p_popup->x;
247 surface->popup.y = p_popup->y;
248 ivi_remove_pending_desktop_surface_popup(p_popup);
257 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
259 struct pending_split *split_surf, *next_split_surf;
260 struct ivi_compositor *ivi = surface->ivi;
261 const char *_app_id =
262 weston_desktop_surface_get_app_id(surface->dsurface);
264 if (wl_list_empty(&ivi->split_pending_apps))
267 wl_list_for_each_safe(split_surf, next_split_surf,
268 &ivi->split_pending_apps, link) {
269 if (!strcmp(_app_id, split_surf->app_id)) {
270 surface->split.output = split_surf->ioutput;
271 surface->split.orientation = split_surf->orientation;
272 ivi_remove_pending_desktop_surface_split(split_surf);
281 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
283 struct pending_fullscreen *fs_surf, *next_fs_surf;
284 struct ivi_compositor *ivi = surface->ivi;
285 const char *_app_id =
286 weston_desktop_surface_get_app_id(surface->dsurface);
288 if (wl_list_empty(&ivi->fullscreen_pending_apps))
291 wl_list_for_each_safe(fs_surf, next_fs_surf,
292 &ivi->fullscreen_pending_apps, link) {
293 if (!strcmp(_app_id, fs_surf->app_id)) {
294 surface->fullscreen.output = fs_surf->ioutput;
295 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
304 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
306 struct pending_remote *remote_surf, *next_remote_surf;
307 struct ivi_compositor *ivi = surface->ivi;
308 const char *_app_id =
309 weston_desktop_surface_get_app_id(surface->dsurface);
311 if (wl_list_empty(&ivi->remote_pending_apps))
314 wl_list_for_each_safe(remote_surf, next_remote_surf,
315 &ivi->remote_pending_apps, link) {
316 if (!strcmp(_app_id, remote_surf->app_id)) {
317 surface->remote.output = remote_surf->ioutput;
318 ivi_remove_pending_desktop_surface_remote(remote_surf);
328 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
332 ret = ivi_check_pending_desktop_surface_popup(surface);
334 ivi_set_desktop_surface_popup(surface);
338 ret = ivi_check_pending_desktop_surface_split(surface);
340 ivi_set_desktop_surface_split(surface);
344 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
346 ivi_set_desktop_surface_fullscreen(surface);
350 ret = ivi_check_pending_desktop_surface_remote(surface);
352 ivi_set_desktop_surface_remote(surface);
356 /* if we end up here means we have a regular desktop app and
357 * try to activate it */
358 ivi_set_desktop_surface(surface);
359 ivi_layout_desktop_committed(surface);
363 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
365 struct ivi_output *out;
367 wl_list_for_each(out, &ivi->outputs, link) {
368 create_black_surface_view(out);
369 insert_black_surface(out);
374 ivi_shell_init(struct ivi_compositor *ivi)
376 weston_layer_init(&ivi->hidden, ivi->compositor);
377 weston_layer_init(&ivi->background, ivi->compositor);
378 weston_layer_init(&ivi->normal, ivi->compositor);
379 weston_layer_init(&ivi->panel, ivi->compositor);
380 weston_layer_init(&ivi->popup, ivi->compositor);
381 weston_layer_init(&ivi->fullscreen, ivi->compositor);
383 weston_layer_set_position(&ivi->hidden,
384 WESTON_LAYER_POSITION_HIDDEN);
385 weston_layer_set_position(&ivi->background,
386 WESTON_LAYER_POSITION_BACKGROUND);
387 weston_layer_set_position(&ivi->normal,
388 WESTON_LAYER_POSITION_NORMAL);
389 weston_layer_set_position(&ivi->panel,
390 WESTON_LAYER_POSITION_UI);
391 weston_layer_set_position(&ivi->popup,
392 WESTON_LAYER_POSITION_TOP_UI);
393 weston_layer_set_position(&ivi->fullscreen,
394 WESTON_LAYER_POSITION_FULLSCREEN);
400 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
402 struct ivi_surface *surface;
404 wl_list_for_each(surface, &ivi->surfaces, link) {
406 weston_desktop_surface_get_app_id(surface->dsurface);
407 agl_shell_desktop_send_application(resource, app_id);
412 client_exec(const char *command, int fd)
417 /* Don't give the child our signal mask */
419 sigprocmask(SIG_UNBLOCK, &sig, NULL);
421 /* Launch clients as the user; don't give them the wrong euid */
422 if (seteuid(getuid()) == -1) {
423 weston_log("seteuid failed: %s\n", strerror(errno));
427 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
428 * clobbering fd, as we'll exit/exec either way.
432 weston_log("dup failed: %s\n", strerror(errno));
436 snprintf(s, sizeof s, "%d", fd);
437 setenv("WAYLAND_SOCKET", s, 1);
439 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
440 weston_log("executing '%s' failed: %s", command, strerror(errno));
443 static struct wl_client *
444 launch_shell_client(struct ivi_compositor *ivi, const char *command)
446 struct wl_client *client;
450 weston_log("launching' %s'\n", command);
452 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
453 weston_log("socketpair failed while launching '%s': %s\n",
454 command, strerror(errno));
462 weston_log("fork failed while launching '%s': %s\n",
463 command, strerror(errno));
468 client_exec(command, sock[1]);
473 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
476 weston_log("Failed to create wayland client for '%s'",
485 ivi_launch_shell_client(struct ivi_compositor *ivi)
487 struct weston_config_section *section;
488 char *command = NULL;
490 section = weston_config_get_section(ivi->config, "shell-client",
493 weston_config_section_get_string(section, "command",
499 ivi->shell_client.client = launch_shell_client(ivi, command);
500 if (!ivi->shell_client.client)
507 destroy_black_view(struct wl_listener *listener, void *data)
509 struct fullscreen_view *fs =
510 wl_container_of(listener, fs, fs_destroy);
514 if (fs->fs->view && fs->fs->view->surface) {
515 weston_surface_destroy(fs->fs->view->surface);
520 wl_list_remove(&fs->fs_destroy.link);
526 create_black_surface_view(struct ivi_output *output)
528 struct weston_surface *surface = NULL;
529 struct weston_view *view;
530 struct ivi_compositor *ivi = output->ivi;
531 struct weston_compositor *wc= ivi->compositor;
532 struct weston_output *woutput = output->output;
534 surface = weston_surface_create(wc);
535 view = weston_view_create(surface);
537 assert(view || surface);
539 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
540 weston_surface_set_size(surface, woutput->width, woutput->height);
541 weston_view_set_position(view, woutput->x, woutput->y);
543 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
544 output->fullscreen_view.fs->view = view;
546 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
547 wl_signal_add(&woutput->destroy_signal,
548 &output->fullscreen_view.fs_destroy);
552 remove_black_surface(struct ivi_output *output)
554 struct weston_view *view = output->fullscreen_view.fs->view;
556 assert(view->is_mapped == true ||
557 view->surface->is_mapped == true);
559 view->is_mapped = false;
560 view->surface->is_mapped = false;
562 weston_layer_entry_remove(&view->layer_link);
563 weston_view_update_transform(view);
565 weston_output_damage(output->output);
569 insert_black_surface(struct ivi_output *output)
571 struct weston_view *view = output->fullscreen_view.fs->view;
573 if (view->is_mapped || view->surface->is_mapped)
576 weston_layer_entry_remove(&view->layer_link);
577 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
580 view->is_mapped = true;
581 view->surface->is_mapped = true;
583 weston_view_update_transform(view);
584 weston_output_damage(output->output);
588 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
590 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
591 struct ivi_output *output;
592 struct ivi_surface *surface, *tmp;
594 /* Init already finished. Do nothing */
595 if (ivi->shell_client.ready)
598 ivi->shell_client.ready = true;
600 wl_list_for_each(output, &ivi->outputs, link) {
601 remove_black_surface(output);
602 ivi_layout_init(ivi, output);
605 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
606 wl_list_remove(&surface->link);
607 ivi_check_pending_desktop_surface(surface);
612 shell_set_background(struct wl_client *client,
613 struct wl_resource *shell_res,
614 struct wl_resource *surface_res,
615 struct wl_resource *output_res)
617 struct weston_head *head = weston_head_from_resource(output_res);
618 struct weston_output *woutput = weston_head_get_output(head);
619 struct ivi_output *output = to_ivi_output(woutput);
620 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
621 struct weston_desktop_surface *dsurface;
622 struct ivi_surface *surface;
624 dsurface = weston_surface_get_desktop_surface(wsurface);
626 wl_resource_post_error(shell_res,
627 AGL_SHELL_ERROR_INVALID_ARGUMENT,
628 "surface must be a desktop surface");
632 surface = weston_desktop_surface_get_user_data(dsurface);
633 if (surface->role != IVI_SURFACE_ROLE_NONE) {
634 wl_resource_post_error(shell_res,
635 AGL_SHELL_ERROR_INVALID_ARGUMENT,
636 "surface already has another ivi role");
640 if (output->background) {
641 wl_resource_post_error(shell_res,
642 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
643 "output already has background");
647 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
648 surface->bg.output = output;
649 wl_list_remove(&surface->link);
650 wl_list_init(&surface->link);
652 output->background = surface;
654 weston_desktop_surface_set_maximized(dsurface, true);
655 weston_desktop_surface_set_size(dsurface,
656 output->output->width,
657 output->output->height);
661 shell_set_panel(struct wl_client *client,
662 struct wl_resource *shell_res,
663 struct wl_resource *surface_res,
664 struct wl_resource *output_res,
667 struct weston_head *head = weston_head_from_resource(output_res);
668 struct weston_output *woutput = weston_head_get_output(head);
669 struct ivi_output *output = to_ivi_output(woutput);
670 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
671 struct weston_desktop_surface *dsurface;
672 struct ivi_surface *surface;
673 struct ivi_surface **member;
674 int32_t width = 0, height = 0;
676 dsurface = weston_surface_get_desktop_surface(wsurface);
678 wl_resource_post_error(shell_res,
679 AGL_SHELL_ERROR_INVALID_ARGUMENT,
680 "surface must be a desktop surface");
684 surface = weston_desktop_surface_get_user_data(dsurface);
685 if (surface->role != IVI_SURFACE_ROLE_NONE) {
686 wl_resource_post_error(shell_res,
687 AGL_SHELL_ERROR_INVALID_ARGUMENT,
688 "surface already has another ivi role");
693 case AGL_SHELL_EDGE_TOP:
694 member = &output->top;
696 case AGL_SHELL_EDGE_BOTTOM:
697 member = &output->bottom;
699 case AGL_SHELL_EDGE_LEFT:
700 member = &output->left;
702 case AGL_SHELL_EDGE_RIGHT:
703 member = &output->right;
706 wl_resource_post_error(shell_res,
707 AGL_SHELL_ERROR_INVALID_ARGUMENT,
708 "invalid edge for panel");
713 wl_resource_post_error(shell_res,
714 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
715 "output already has panel on this edge");
719 surface->role = IVI_SURFACE_ROLE_PANEL;
720 surface->panel.output = output;
721 surface->panel.edge = edge;
722 wl_list_remove(&surface->link);
723 wl_list_init(&surface->link);
727 switch (surface->panel.edge) {
728 case AGL_SHELL_EDGE_TOP:
729 case AGL_SHELL_EDGE_BOTTOM:
730 width = woutput->width;
732 case AGL_SHELL_EDGE_LEFT:
733 case AGL_SHELL_EDGE_RIGHT:
734 height = woutput->height;
738 weston_desktop_surface_set_size(dsurface, width, height);
743 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
744 const char *data, uint32_t app_state)
746 struct desktop_client *dclient;
748 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
749 struct ivi_policy *policy = ivi->policy;
751 /* FIXME: should queue it here and see when binding agl-shell-desktop
752 * if there are any to be sent */
756 if (policy && policy->api.surface_advertise_state_change &&
757 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
761 app_role = surf->role;
762 if (app_role == IVI_SURFACE_ROLE_POPUP)
763 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
765 wl_list_for_each(dclient, &ivi->desktop_clients, link)
766 agl_shell_desktop_send_state_app(dclient->resource, app_id,
767 data, app_state, app_role);
771 shell_activate_app(struct wl_client *client,
772 struct wl_resource *shell_res,
774 struct wl_resource *output_res)
776 struct weston_head *head = weston_head_from_resource(output_res);
777 struct weston_output *woutput = weston_head_get_output(head);
778 struct ivi_output *output = to_ivi_output(woutput);
780 ivi_layout_activate(output, app_id);
784 shell_desktop_activate_app(struct wl_client *client,
785 struct wl_resource *shell_res,
786 const char *app_id, const char *data,
787 struct wl_resource *output_res)
789 struct weston_head *head = weston_head_from_resource(output_res);
790 struct weston_output *woutput = weston_head_get_output(head);
791 struct ivi_output *output = to_ivi_output(woutput);
793 ivi_layout_activate(output, app_id);
794 shell_advertise_app_state(output->ivi, app_id,
795 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
799 shell_deactivate_app(struct wl_client *client,
800 struct wl_resource *shell_res,
803 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
804 struct ivi_compositor *ivi = dclient->ivi;
806 ivi_layout_deactivate(ivi, app_id);
807 shell_advertise_app_state(ivi, app_id,
808 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
811 static const struct agl_shell_interface agl_shell_implementation = {
812 .ready = shell_ready,
813 .set_background = shell_set_background,
814 .set_panel = shell_set_panel,
815 .activate_app = shell_activate_app,
819 shell_desktop_set_app_property(struct wl_client *client,
820 struct wl_resource *shell_res,
821 const char *app_id, uint32_t role,
822 int x, int y, struct wl_resource *output_res)
824 struct weston_head *head = weston_head_from_resource(output_res);
825 struct weston_output *woutput = weston_head_get_output(head);
826 struct ivi_output *output = to_ivi_output(woutput);
829 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
830 ivi_set_pending_desktop_surface_popup(output, x, y, app_id);
832 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
833 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
835 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
836 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
837 ivi_set_pending_desktop_surface_split(output, app_id, role);
839 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
840 ivi_set_pending_desktop_surface_remote(output, app_id);
847 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
848 .activate_app = shell_desktop_activate_app,
849 .set_app_property = shell_desktop_set_app_property,
850 .deactivate_app = shell_deactivate_app,
854 unbind_agl_shell(struct wl_resource *resource)
856 struct ivi_compositor *ivi;
857 struct ivi_output *output;
858 struct ivi_surface *surf, *surf_tmp;
860 ivi = wl_resource_get_user_data(resource);
861 wl_list_for_each(output, &ivi->outputs, link) {
862 /* reset the active surf if there's one present */
863 if (output->active) {
864 output->active->view->is_mapped = false;
865 output->active->view->surface->is_mapped = false;
867 weston_layer_entry_remove(&output->active->view->layer_link);
868 output->active = NULL;
871 insert_black_surface(output);
874 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
875 wl_list_remove(&surf->link);
876 wl_list_init(&surf->link);
879 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
880 wl_list_remove(&surf->link);
881 wl_list_init(&surf->link);
884 wl_list_init(&ivi->surfaces);
885 wl_list_init(&ivi->pending_surfaces);
887 ivi->shell_client.ready = false;
888 ivi->shell_client.resource = NULL;
889 ivi->shell_client.client = NULL;
893 bind_agl_shell(struct wl_client *client,
894 void *data, uint32_t version, uint32_t id)
896 struct ivi_compositor *ivi = data;
897 struct wl_resource *resource;
899 resource = wl_resource_create(client, &agl_shell_interface,
902 wl_client_post_no_memory(client);
907 if (ivi->shell_client.client != client) {
908 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
909 "client not authorized to use agl_shell");
914 if (ivi->shell_client.resource) {
915 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
916 "agl_shell has already been bound");
920 wl_resource_set_implementation(resource, &agl_shell_implementation,
921 ivi, unbind_agl_shell);
922 ivi->shell_client.resource = resource;
926 unbind_agl_shell_desktop(struct wl_resource *resource)
928 struct desktop_client *dclient = wl_resource_get_user_data(resource);
930 wl_list_remove(&dclient->link);
935 bind_agl_shell_desktop(struct wl_client *client,
936 void *data, uint32_t version, uint32_t id)
938 struct ivi_compositor *ivi = data;
939 struct wl_resource *resource;
940 struct desktop_client *dclient = zalloc(sizeof(*dclient));
943 wl_client_post_no_memory(client);
947 resource = wl_resource_create(client, &agl_shell_desktop_interface,
951 wl_client_post_no_memory(client);
955 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
956 dclient, unbind_agl_shell_desktop);
958 dclient->resource = resource;
959 wl_list_insert(&ivi->desktop_clients, &dclient->link);
961 /* advertise xdg surfaces */
962 ivi_shell_advertise_xdg_surfaces(ivi, resource);
966 ivi_shell_create_global(struct ivi_compositor *ivi)
968 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
969 &agl_shell_interface, 1,
970 ivi, bind_agl_shell);
971 if (!ivi->agl_shell) {
972 weston_log("Failed to create wayland global.\n");
976 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
977 &agl_shell_desktop_interface, 1,
978 ivi, bind_agl_shell_desktop);
979 if (!ivi->agl_shell_desktop) {
980 weston_log("Failed to create wayland global (agl_shell_desktop).\n");