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_fs(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_FS;
86 wl_list_insert(&ivi->surfaces, &surface->link);
90 ivi_set_desktop_surface_split(struct ivi_surface *surface)
92 struct ivi_compositor *ivi = surface->ivi;
93 assert(surface->role == IVI_SURFACE_ROLE_NONE);
95 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
96 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
98 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
100 wl_list_insert(&ivi->surfaces, &surface->link);
104 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput,
105 int x, int y, const char *app_id)
107 struct ivi_compositor *ivi = ioutput->ivi;
108 size_t len_app_id = strlen(app_id);
110 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
112 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
113 memcpy(p_popup->app_id, app_id, len_app_id);
114 p_popup->ioutput = ioutput;
118 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
122 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
125 struct ivi_compositor *ivi = ioutput->ivi;
126 size_t len_app_id = strlen(app_id);
128 struct pending_fullscreen *fs = zalloc(sizeof(*fs));
130 fs->app_id = zalloc(sizeof(char) * (len_app_id + 1));
131 memcpy(fs->app_id, app_id, len_app_id);
133 fs->ioutput = ioutput;
135 wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link);
139 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
140 const char *app_id, uint32_t orientation)
142 struct ivi_compositor *ivi = ioutput->ivi;
143 struct ivi_surface *surf;
144 size_t len_app_id = strlen(app_id);
145 struct pending_split *split;
147 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
148 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
151 /* more than one is un-supported, do note we need to do
152 * conversion for surface roles instead of using the protocol ones */
153 wl_list_for_each(surf, &ivi->surfaces, link)
154 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
155 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
158 split = zalloc(sizeof(*split));
159 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
160 memcpy(split->app_id, app_id, len_app_id);
162 split->ioutput = ioutput;
163 split->orientation = orientation;
165 wl_list_insert(&ivi->split_pending_apps, &split->link);
169 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
172 wl_list_remove(&split->link);
177 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
180 wl_list_remove(&fs->link);
185 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
187 free(p_popup->app_id);
188 wl_list_remove(&p_popup->link);
193 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
195 struct ivi_compositor *ivi = surface->ivi;
196 struct pending_popup *p_popup, *next_p_popup;
197 const char *_app_id =
198 weston_desktop_surface_get_app_id(surface->dsurface);
200 if (wl_list_empty(&ivi->popup_pending_apps))
203 wl_list_for_each_safe(p_popup, next_p_popup,
204 &ivi->popup_pending_apps, link) {
205 if (!strcmp(_app_id, p_popup->app_id)) {
206 surface->popup.output = p_popup->ioutput;
207 surface->popup.x = p_popup->x;
208 surface->popup.y = p_popup->y;
209 ivi_remove_pending_desktop_surface_popup(p_popup);
218 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
220 struct pending_split *split_surf, *next_split_surf;
221 struct ivi_compositor *ivi = surface->ivi;
222 const char *_app_id =
223 weston_desktop_surface_get_app_id(surface->dsurface);
225 if (wl_list_empty(&ivi->split_pending_apps))
228 wl_list_for_each_safe(split_surf, next_split_surf,
229 &ivi->split_pending_apps, link) {
230 if (!strcmp(_app_id, split_surf->app_id)) {
231 surface->split.output = split_surf->ioutput;
232 surface->split.orientation = split_surf->orientation;
233 ivi_remove_pending_desktop_surface_split(split_surf);
242 ivi_check_pending_desktop_surface_fs(struct ivi_surface *surface)
244 struct pending_fullscreen *fs_surf, *next_fs_surf;
245 struct ivi_compositor *ivi = surface->ivi;
246 const char *_app_id =
247 weston_desktop_surface_get_app_id(surface->dsurface);
249 if (wl_list_empty(&ivi->fullscreen_pending_apps))
252 wl_list_for_each_safe(fs_surf, next_fs_surf,
253 &ivi->fullscreen_pending_apps, link) {
254 if (!strcmp(_app_id, fs_surf->app_id)) {
255 surface->fs.output = fs_surf->ioutput;
256 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
265 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
269 ret = ivi_check_pending_desktop_surface_popup(surface);
271 ivi_set_desktop_surface_popup(surface);
275 ret = ivi_check_pending_desktop_surface_split(surface);
277 ivi_set_desktop_surface_split(surface);
281 ret = ivi_check_pending_desktop_surface_fs(surface);
283 ivi_set_desktop_surface_fs(surface);
287 /* if we end up here means we have a regular desktop app and
288 * try to activate it */
289 ivi_set_desktop_surface(surface);
290 ivi_layout_desktop_committed(surface);
294 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
296 struct ivi_output *out;
298 wl_list_for_each(out, &ivi->outputs, link) {
299 create_black_surface_view(out);
300 insert_black_surface(out);
305 ivi_shell_init(struct ivi_compositor *ivi)
307 weston_layer_init(&ivi->hidden, ivi->compositor);
308 weston_layer_init(&ivi->background, ivi->compositor);
309 weston_layer_init(&ivi->normal, ivi->compositor);
310 weston_layer_init(&ivi->panel, ivi->compositor);
311 weston_layer_init(&ivi->popup, ivi->compositor);
312 weston_layer_init(&ivi->fullscreen, ivi->compositor);
314 weston_layer_set_position(&ivi->hidden,
315 WESTON_LAYER_POSITION_HIDDEN);
316 weston_layer_set_position(&ivi->background,
317 WESTON_LAYER_POSITION_BACKGROUND);
318 weston_layer_set_position(&ivi->normal,
319 WESTON_LAYER_POSITION_NORMAL);
320 weston_layer_set_position(&ivi->panel,
321 WESTON_LAYER_POSITION_UI);
322 weston_layer_set_position(&ivi->popup,
323 WESTON_LAYER_POSITION_TOP_UI);
324 weston_layer_set_position(&ivi->fullscreen,
325 WESTON_LAYER_POSITION_FULLSCREEN);
331 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
333 struct ivi_surface *surface;
335 wl_list_for_each(surface, &ivi->surfaces, link) {
337 weston_desktop_surface_get_app_id(surface->dsurface);
338 agl_shell_desktop_send_application(resource, app_id);
343 client_exec(const char *command, int fd)
348 /* Don't give the child our signal mask */
350 sigprocmask(SIG_UNBLOCK, &sig, NULL);
352 /* Launch clients as the user; don't give them the wrong euid */
353 if (seteuid(getuid()) == -1) {
354 weston_log("seteuid failed: %s\n", strerror(errno));
358 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
359 * clobbering fd, as we'll exit/exec either way.
363 weston_log("dup failed: %s\n", strerror(errno));
367 snprintf(s, sizeof s, "%d", fd);
368 setenv("WAYLAND_SOCKET", s, 1);
370 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
371 weston_log("executing '%s' failed: %s", command, strerror(errno));
374 static struct wl_client *
375 launch_shell_client(struct ivi_compositor *ivi, const char *command)
377 struct wl_client *client;
381 weston_log("launching' %s'\n", command);
383 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
384 weston_log("socketpair failed while launching '%s': %s\n",
385 command, strerror(errno));
393 weston_log("fork failed while launching '%s': %s\n",
394 command, strerror(errno));
399 client_exec(command, sock[1]);
404 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
407 weston_log("Failed to create wayland client for '%s'",
416 ivi_launch_shell_client(struct ivi_compositor *ivi)
418 struct weston_config_section *section;
419 char *command = NULL;
421 section = weston_config_get_section(ivi->config, "shell-client",
424 weston_config_section_get_string(section, "command",
430 ivi->shell_client.client = launch_shell_client(ivi, command);
431 if (!ivi->shell_client.client)
438 destroy_black_view(struct wl_listener *listener, void *data)
440 struct fullscreen_view *fs =
441 wl_container_of(listener, fs, fs_destroy);
445 if (fs->fs->view && fs->fs->view->surface) {
446 weston_surface_destroy(fs->fs->view->surface);
451 wl_list_remove(&fs->fs_destroy.link);
457 create_black_surface_view(struct ivi_output *output)
459 struct weston_surface *surface = NULL;
460 struct weston_view *view;
461 struct ivi_compositor *ivi = output->ivi;
462 struct weston_compositor *wc= ivi->compositor;
463 struct weston_output *woutput = output->output;
465 surface = weston_surface_create(wc);
466 view = weston_view_create(surface);
468 assert(view || surface);
470 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
471 weston_surface_set_size(surface, woutput->width, woutput->height);
472 weston_view_set_position(view, woutput->x, woutput->y);
474 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
475 output->fullscreen_view.fs->view = view;
477 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
478 wl_signal_add(&woutput->destroy_signal,
479 &output->fullscreen_view.fs_destroy);
483 remove_black_surface(struct ivi_output *output)
485 struct weston_view *view = output->fullscreen_view.fs->view;
487 assert(view->is_mapped == true ||
488 view->surface->is_mapped == true);
490 view->is_mapped = false;
491 view->surface->is_mapped = false;
493 weston_layer_entry_remove(&view->layer_link);
494 weston_view_update_transform(view);
496 weston_output_damage(output->output);
500 insert_black_surface(struct ivi_output *output)
502 struct weston_view *view = output->fullscreen_view.fs->view;
504 if (view->is_mapped || view->surface->is_mapped)
507 weston_layer_entry_remove(&view->layer_link);
508 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
511 view->is_mapped = true;
512 view->surface->is_mapped = true;
514 weston_view_update_transform(view);
515 weston_output_damage(output->output);
519 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
521 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
522 struct ivi_output *output;
523 struct ivi_surface *surface, *tmp;
525 /* Init already finished. Do nothing */
526 if (ivi->shell_client.ready)
529 ivi->shell_client.ready = true;
531 wl_list_for_each(output, &ivi->outputs, link) {
532 remove_black_surface(output);
533 ivi_layout_init(ivi, output);
536 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
537 wl_list_remove(&surface->link);
538 ivi_check_pending_desktop_surface(surface);
543 shell_set_background(struct wl_client *client,
544 struct wl_resource *shell_res,
545 struct wl_resource *surface_res,
546 struct wl_resource *output_res)
548 struct weston_head *head = weston_head_from_resource(output_res);
549 struct weston_output *woutput = weston_head_get_output(head);
550 struct ivi_output *output = to_ivi_output(woutput);
551 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
552 struct weston_desktop_surface *dsurface;
553 struct ivi_surface *surface;
555 dsurface = weston_surface_get_desktop_surface(wsurface);
557 wl_resource_post_error(shell_res,
558 AGL_SHELL_ERROR_INVALID_ARGUMENT,
559 "surface must be a desktop surface");
563 surface = weston_desktop_surface_get_user_data(dsurface);
564 if (surface->role != IVI_SURFACE_ROLE_NONE) {
565 wl_resource_post_error(shell_res,
566 AGL_SHELL_ERROR_INVALID_ARGUMENT,
567 "surface already has another ivi role");
571 if (output->background) {
572 wl_resource_post_error(shell_res,
573 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
574 "output already has background");
578 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
579 surface->bg.output = output;
580 wl_list_remove(&surface->link);
581 wl_list_init(&surface->link);
583 output->background = surface;
585 weston_desktop_surface_set_maximized(dsurface, true);
586 weston_desktop_surface_set_size(dsurface,
587 output->output->width,
588 output->output->height);
592 shell_set_panel(struct wl_client *client,
593 struct wl_resource *shell_res,
594 struct wl_resource *surface_res,
595 struct wl_resource *output_res,
598 struct weston_head *head = weston_head_from_resource(output_res);
599 struct weston_output *woutput = weston_head_get_output(head);
600 struct ivi_output *output = to_ivi_output(woutput);
601 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
602 struct weston_desktop_surface *dsurface;
603 struct ivi_surface *surface;
604 struct ivi_surface **member;
605 int32_t width = 0, height = 0;
607 dsurface = weston_surface_get_desktop_surface(wsurface);
609 wl_resource_post_error(shell_res,
610 AGL_SHELL_ERROR_INVALID_ARGUMENT,
611 "surface must be a desktop surface");
615 surface = weston_desktop_surface_get_user_data(dsurface);
616 if (surface->role != IVI_SURFACE_ROLE_NONE) {
617 wl_resource_post_error(shell_res,
618 AGL_SHELL_ERROR_INVALID_ARGUMENT,
619 "surface already has another ivi role");
624 case AGL_SHELL_EDGE_TOP:
625 member = &output->top;
627 case AGL_SHELL_EDGE_BOTTOM:
628 member = &output->bottom;
630 case AGL_SHELL_EDGE_LEFT:
631 member = &output->left;
633 case AGL_SHELL_EDGE_RIGHT:
634 member = &output->right;
637 wl_resource_post_error(shell_res,
638 AGL_SHELL_ERROR_INVALID_ARGUMENT,
639 "invalid edge for panel");
644 wl_resource_post_error(shell_res,
645 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
646 "output already has panel on this edge");
650 surface->role = IVI_SURFACE_ROLE_PANEL;
651 surface->panel.output = output;
652 surface->panel.edge = edge;
653 wl_list_remove(&surface->link);
654 wl_list_init(&surface->link);
658 switch (surface->panel.edge) {
659 case AGL_SHELL_EDGE_TOP:
660 case AGL_SHELL_EDGE_BOTTOM:
661 width = woutput->width;
663 case AGL_SHELL_EDGE_LEFT:
664 case AGL_SHELL_EDGE_RIGHT:
665 height = woutput->height;
669 weston_desktop_surface_set_size(dsurface, width, height);
674 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
675 const char *data, uint32_t app_state)
677 struct desktop_client *dclient;
679 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
680 struct ivi_policy *policy = ivi->policy;
682 /* FIXME: should queue it here and see when binding agl-shell-desktop
683 * if there are any to be sent */
687 if (policy && policy->api.surface_advertise_state_change &&
688 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
692 app_role = surf->role;
693 if (app_role == IVI_SURFACE_ROLE_POPUP)
694 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
696 wl_list_for_each(dclient, &ivi->desktop_clients, link)
697 agl_shell_desktop_send_state_app(dclient->resource, app_id,
698 data, app_state, app_role);
702 shell_activate_app(struct wl_client *client,
703 struct wl_resource *shell_res,
705 struct wl_resource *output_res)
707 struct weston_head *head = weston_head_from_resource(output_res);
708 struct weston_output *woutput = weston_head_get_output(head);
709 struct ivi_output *output = to_ivi_output(woutput);
711 ivi_layout_activate(output, app_id);
715 shell_desktop_activate_app(struct wl_client *client,
716 struct wl_resource *shell_res,
717 const char *app_id, const char *data,
718 struct wl_resource *output_res)
720 struct weston_head *head = weston_head_from_resource(output_res);
721 struct weston_output *woutput = weston_head_get_output(head);
722 struct ivi_output *output = to_ivi_output(woutput);
724 ivi_layout_activate(output, app_id);
725 shell_advertise_app_state(output->ivi, app_id,
726 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
730 shell_deactivate_app(struct wl_client *client,
731 struct wl_resource *shell_res,
734 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
735 struct ivi_compositor *ivi = dclient->ivi;
737 ivi_layout_deactivate(ivi, app_id);
738 shell_advertise_app_state(ivi, app_id,
739 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
742 static const struct agl_shell_interface agl_shell_implementation = {
743 .ready = shell_ready,
744 .set_background = shell_set_background,
745 .set_panel = shell_set_panel,
746 .activate_app = shell_activate_app,
750 shell_desktop_set_app_property(struct wl_client *client,
751 struct wl_resource *shell_res,
752 const char *app_id, uint32_t role,
753 int x, int y, struct wl_resource *output_res)
755 struct weston_head *head = weston_head_from_resource(output_res);
756 struct weston_output *woutput = weston_head_get_output(head);
757 struct ivi_output *output = to_ivi_output(woutput);
760 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
761 ivi_set_pending_desktop_surface_popup(output, x, y, app_id);
763 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
764 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
766 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
767 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
768 ivi_set_pending_desktop_surface_split(output, app_id, role);
775 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
776 .activate_app = shell_desktop_activate_app,
777 .set_app_property = shell_desktop_set_app_property,
778 .deactivate_app = shell_deactivate_app,
782 unbind_agl_shell(struct wl_resource *resource)
784 struct ivi_compositor *ivi;
785 struct ivi_output *output;
786 struct ivi_surface *surf, *surf_tmp;
788 ivi = wl_resource_get_user_data(resource);
789 wl_list_for_each(output, &ivi->outputs, link) {
790 free(output->background);
791 output->background = NULL;
796 free(output->bottom);
797 output->bottom = NULL;
803 output->right = NULL;
805 /* reset the active surf if there's one present */
806 if (output->active) {
807 output->active->view->is_mapped = false;
808 output->active->view->surface->is_mapped = false;
810 weston_layer_entry_remove(&output->active->view->layer_link);
811 output->active = NULL;
814 insert_black_surface(output);
817 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
818 wl_list_remove(&surf->link);
819 wl_list_init(&surf->link);
822 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
823 wl_list_remove(&surf->link);
824 wl_list_init(&surf->link);
827 wl_list_init(&ivi->surfaces);
828 wl_list_init(&ivi->pending_surfaces);
830 ivi->shell_client.ready = false;
831 ivi->shell_client.resource = NULL;
832 ivi->shell_client.client = NULL;
836 bind_agl_shell(struct wl_client *client,
837 void *data, uint32_t version, uint32_t id)
839 struct ivi_compositor *ivi = data;
840 struct wl_resource *resource;
842 resource = wl_resource_create(client, &agl_shell_interface,
845 wl_client_post_no_memory(client);
850 if (ivi->shell_client.client != client) {
851 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
852 "client not authorized to use agl_shell");
857 if (ivi->shell_client.resource) {
858 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
859 "agl_shell has already been bound");
863 wl_resource_set_implementation(resource, &agl_shell_implementation,
864 ivi, unbind_agl_shell);
865 ivi->shell_client.resource = resource;
869 unbind_agl_shell_desktop(struct wl_resource *resource)
871 struct desktop_client *dclient = wl_resource_get_user_data(resource);
873 wl_list_remove(&dclient->link);
878 bind_agl_shell_desktop(struct wl_client *client,
879 void *data, uint32_t version, uint32_t id)
881 struct ivi_compositor *ivi = data;
882 struct wl_resource *resource;
883 struct desktop_client *dclient = zalloc(sizeof(*dclient));
886 wl_client_post_no_memory(client);
890 resource = wl_resource_create(client, &agl_shell_desktop_interface,
894 wl_client_post_no_memory(client);
898 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
899 dclient, unbind_agl_shell_desktop);
901 dclient->resource = resource;
902 wl_list_insert(&ivi->desktop_clients, &dclient->link);
904 /* advertise xdg surfaces */
905 ivi_shell_advertise_xdg_surfaces(ivi, resource);
909 ivi_shell_create_global(struct ivi_compositor *ivi)
911 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
912 &agl_shell_interface, 1,
913 ivi, bind_agl_shell);
914 if (!ivi->agl_shell) {
915 weston_log("Failed to create wayland global.\n");
919 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
920 &agl_shell_desktop_interface, 1,
921 ivi, bind_agl_shell_desktop);
922 if (!ivi->agl_shell_desktop) {
923 weston_log("Failed to create wayland global (agl_shell_desktop).\n");