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 agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi,
50 struct ivi_surface *surface)
52 struct desktop_client *dclient;
54 if (surface->advertised_on_launch)
57 /* advertise to all desktop clients the new surface */
58 wl_list_for_each(dclient, &ivi->desktop_clients, link) {
60 weston_desktop_surface_get_app_id(surface->dsurface);
62 weston_log("WARNING app_is is null, unable to advertise\n");
65 agl_shell_desktop_send_application(dclient->resource, app_id);
66 surface->advertised_on_launch = true;
71 ivi_set_desktop_surface(struct ivi_surface *surface)
73 struct ivi_compositor *ivi = surface->ivi;
74 assert(surface->role == IVI_SURFACE_ROLE_NONE);
76 surface->role = IVI_SURFACE_ROLE_DESKTOP;
77 wl_list_insert(&surface->ivi->surfaces, &surface->link);
79 agl_shell_desktop_advertise_application_id(ivi, surface);
83 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
85 struct ivi_compositor *ivi = surface->ivi;
86 assert(surface->role == IVI_SURFACE_ROLE_NONE);
88 surface->role = IVI_SURFACE_ROLE_POPUP;
89 wl_list_insert(&ivi->surfaces, &surface->link);
91 agl_shell_desktop_advertise_application_id(ivi, surface);
95 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
97 struct ivi_compositor *ivi = surface->ivi;
98 assert(surface->role == IVI_SURFACE_ROLE_NONE);
100 surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
101 wl_list_insert(&ivi->surfaces, &surface->link);
103 agl_shell_desktop_advertise_application_id(ivi, surface);
107 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
109 struct ivi_compositor *ivi = surface->ivi;
110 struct weston_view *view;
111 struct ivi_output *output = surface->remote.output;
113 assert(surface->role == IVI_SURFACE_ROLE_NONE);
115 /* remote type are the same as desktop just that client can tell
116 * the compositor to start on another output */
117 surface->role = IVI_SURFACE_ROLE_REMOTE;
119 /* if thew black surface view is mapped on the mean we need
120 * to remove it in order to start showing the 'remote' surface
121 * just being added */
122 view = output->fullscreen_view.fs->view;
123 if (view->is_mapped || view->surface->is_mapped)
124 remove_black_surface(output);
126 wl_list_insert(&ivi->surfaces, &surface->link);
131 ivi_set_desktop_surface_split(struct ivi_surface *surface)
133 struct ivi_compositor *ivi = surface->ivi;
134 assert(surface->role == IVI_SURFACE_ROLE_NONE);
136 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
137 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
139 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
141 wl_list_insert(&ivi->surfaces, &surface->link);
143 agl_shell_desktop_advertise_application_id(ivi, surface);
147 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput,
148 int x, int y, int bx, int by, int width, int height,
151 struct ivi_compositor *ivi = ioutput->ivi;
152 size_t len_app_id = strlen(app_id);
154 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
156 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
157 memcpy(p_popup->app_id, app_id, len_app_id);
158 p_popup->ioutput = ioutput;
164 p_popup->bb.width = width;
165 p_popup->bb.height = height;
167 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
171 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
174 struct ivi_compositor *ivi = ioutput->ivi;
175 size_t len_app_id = strlen(app_id);
177 struct pending_fullscreen *fs = zalloc(sizeof(*fs));
179 fs->app_id = zalloc(sizeof(char) * (len_app_id + 1));
180 memcpy(fs->app_id, app_id, len_app_id);
182 fs->ioutput = ioutput;
184 wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link);
188 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
189 const char *app_id, uint32_t orientation)
191 struct ivi_compositor *ivi = ioutput->ivi;
192 struct ivi_surface *surf;
193 size_t len_app_id = strlen(app_id);
194 struct pending_split *split;
196 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
197 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
200 /* more than one is un-supported, do note we need to do
201 * conversion for surface roles instead of using the protocol ones */
202 wl_list_for_each(surf, &ivi->surfaces, link)
203 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
204 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
207 split = zalloc(sizeof(*split));
208 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
209 memcpy(split->app_id, app_id, len_app_id);
211 split->ioutput = ioutput;
212 split->orientation = orientation;
214 wl_list_insert(&ivi->split_pending_apps, &split->link);
218 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
221 struct ivi_compositor *ivi = ioutput->ivi;
222 size_t len_app_id = strlen(app_id);
224 struct pending_remote *remote = zalloc(sizeof(*remote));
226 remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
227 memcpy(remote->app_id, app_id, len_app_id);
229 remote->ioutput = ioutput;
231 wl_list_insert(&ivi->remote_pending_apps, &remote->link);
236 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
239 wl_list_remove(&split->link);
244 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
247 wl_list_remove(&fs->link);
252 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
254 free(p_popup->app_id);
255 wl_list_remove(&p_popup->link);
260 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
262 free(remote->app_id);
263 wl_list_remove(&remote->link);
268 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
270 struct ivi_compositor *ivi = surface->ivi;
271 struct pending_popup *p_popup, *next_p_popup;
272 const char *_app_id =
273 weston_desktop_surface_get_app_id(surface->dsurface);
275 if (wl_list_empty(&ivi->popup_pending_apps) || !_app_id)
278 wl_list_for_each_safe(p_popup, next_p_popup,
279 &ivi->popup_pending_apps, link) {
280 if (!strcmp(_app_id, p_popup->app_id)) {
281 surface->popup.output = p_popup->ioutput;
282 surface->popup.x = p_popup->x;
283 surface->popup.y = p_popup->y;
285 surface->popup.bb.x = p_popup->bb.x;
286 surface->popup.bb.y = p_popup->bb.y;
287 surface->popup.bb.width = p_popup->bb.width;
288 surface->popup.bb.height = p_popup->bb.height;
290 ivi_remove_pending_desktop_surface_popup(p_popup);
299 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
301 struct pending_split *split_surf, *next_split_surf;
302 struct ivi_compositor *ivi = surface->ivi;
303 const char *_app_id =
304 weston_desktop_surface_get_app_id(surface->dsurface);
306 if (wl_list_empty(&ivi->split_pending_apps) || !_app_id)
309 wl_list_for_each_safe(split_surf, next_split_surf,
310 &ivi->split_pending_apps, link) {
311 if (!strcmp(_app_id, split_surf->app_id)) {
312 surface->split.output = split_surf->ioutput;
313 surface->split.orientation = split_surf->orientation;
314 ivi_remove_pending_desktop_surface_split(split_surf);
323 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
325 struct pending_fullscreen *fs_surf, *next_fs_surf;
326 struct ivi_compositor *ivi = surface->ivi;
327 const char *_app_id =
328 weston_desktop_surface_get_app_id(surface->dsurface);
330 if (wl_list_empty(&ivi->fullscreen_pending_apps) || !_app_id)
333 wl_list_for_each_safe(fs_surf, next_fs_surf,
334 &ivi->fullscreen_pending_apps, link) {
335 if (!strcmp(_app_id, fs_surf->app_id)) {
336 surface->fullscreen.output = fs_surf->ioutput;
337 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
346 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
348 struct pending_remote *remote_surf, *next_remote_surf;
349 struct ivi_compositor *ivi = surface->ivi;
350 const char *_app_id =
351 weston_desktop_surface_get_app_id(surface->dsurface);
353 if (wl_list_empty(&ivi->remote_pending_apps) || !_app_id)
356 wl_list_for_each_safe(remote_surf, next_remote_surf,
357 &ivi->remote_pending_apps, link) {
358 if (!strcmp(_app_id, remote_surf->app_id)) {
359 surface->remote.output = remote_surf->ioutput;
360 ivi_remove_pending_desktop_surface_remote(remote_surf);
370 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
374 ret = ivi_check_pending_desktop_surface_popup(surface);
376 ivi_set_desktop_surface_popup(surface);
377 ivi_layout_popup_committed(surface);
381 ret = ivi_check_pending_desktop_surface_split(surface);
383 ivi_set_desktop_surface_split(surface);
384 ivi_layout_split_committed(surface);
388 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
390 ivi_set_desktop_surface_fullscreen(surface);
391 ivi_layout_fullscreen_committed(surface);
395 ret = ivi_check_pending_desktop_surface_remote(surface);
397 ivi_set_desktop_surface_remote(surface);
398 ivi_layout_desktop_committed(surface);
402 /* if we end up here means we have a regular desktop app and
403 * try to activate it */
404 ivi_set_desktop_surface(surface);
405 ivi_layout_desktop_committed(surface);
409 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
411 struct ivi_output *out;
413 wl_list_for_each(out, &ivi->outputs, link) {
414 create_black_surface_view(out);
415 insert_black_surface(out);
420 ivi_shell_init(struct ivi_compositor *ivi)
422 weston_layer_init(&ivi->hidden, ivi->compositor);
423 weston_layer_init(&ivi->background, ivi->compositor);
424 weston_layer_init(&ivi->normal, ivi->compositor);
425 weston_layer_init(&ivi->panel, ivi->compositor);
426 weston_layer_init(&ivi->popup, ivi->compositor);
427 weston_layer_init(&ivi->fullscreen, ivi->compositor);
429 weston_layer_set_position(&ivi->hidden,
430 WESTON_LAYER_POSITION_HIDDEN);
431 weston_layer_set_position(&ivi->background,
432 WESTON_LAYER_POSITION_BACKGROUND);
433 weston_layer_set_position(&ivi->normal,
434 WESTON_LAYER_POSITION_NORMAL);
435 weston_layer_set_position(&ivi->panel,
436 WESTON_LAYER_POSITION_UI);
437 weston_layer_set_position(&ivi->popup,
438 WESTON_LAYER_POSITION_TOP_UI);
439 weston_layer_set_position(&ivi->fullscreen,
440 WESTON_LAYER_POSITION_FULLSCREEN);
446 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
448 struct ivi_surface *surface;
450 wl_list_for_each(surface, &ivi->surfaces, link) {
452 weston_desktop_surface_get_app_id(surface->dsurface);
453 if (app_id == NULL) {
454 weston_log("WARNING app_is is null, unable to advertise\n");
457 agl_shell_desktop_send_application(resource, app_id);
462 client_exec(const char *command, int fd)
467 /* Don't give the child our signal mask */
469 sigprocmask(SIG_UNBLOCK, &sig, NULL);
471 /* Launch clients as the user; don't give them the wrong euid */
472 if (seteuid(getuid()) == -1) {
473 weston_log("seteuid failed: %s\n", strerror(errno));
477 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
478 * clobbering fd, as we'll exit/exec either way.
482 weston_log("dup failed: %s\n", strerror(errno));
486 snprintf(s, sizeof s, "%d", fd);
487 setenv("WAYLAND_SOCKET", s, 1);
489 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
490 weston_log("executing '%s' failed: %s", command, strerror(errno));
493 static struct wl_client *
494 launch_shell_client(struct ivi_compositor *ivi, const char *command)
496 struct wl_client *client;
500 weston_log("launching' %s'\n", command);
502 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
503 weston_log("socketpair failed while launching '%s': %s\n",
504 command, strerror(errno));
512 weston_log("fork failed while launching '%s': %s\n",
513 command, strerror(errno));
518 client_exec(command, sock[1]);
523 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
526 weston_log("Failed to create wayland client for '%s'",
535 ivi_launch_shell_client(struct ivi_compositor *ivi)
537 struct weston_config_section *section;
538 char *command = NULL;
540 section = weston_config_get_section(ivi->config, "shell-client",
543 weston_config_section_get_string(section, "command",
549 ivi->shell_client.client = launch_shell_client(ivi, command);
550 if (!ivi->shell_client.client)
557 destroy_black_view(struct wl_listener *listener, void *data)
559 struct fullscreen_view *fs =
560 wl_container_of(listener, fs, fs_destroy);
564 wl_list_remove(&fs->fs_destroy.link);
571 create_black_surface_view(struct ivi_output *output)
573 struct weston_surface *surface = NULL;
574 struct weston_view *view;
575 struct ivi_compositor *ivi = output->ivi;
576 struct weston_compositor *wc= ivi->compositor;
577 struct weston_output *woutput = output->output;
582 surface = weston_surface_create(wc);
583 view = weston_view_create(surface);
585 assert(view || surface);
587 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
588 weston_surface_set_size(surface, woutput->width, woutput->height);
589 weston_view_set_position(view, woutput->x, woutput->y);
591 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
592 output->fullscreen_view.fs->view = view;
594 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
595 wl_signal_add(&woutput->destroy_signal,
596 &output->fullscreen_view.fs_destroy);
600 remove_black_surface(struct ivi_output *output)
602 struct weston_view *view;
605 !output->fullscreen_view.fs &&
606 !output->fullscreen_view.fs->view) {
607 weston_log("Output %s doesn't have a surface installed!\n", output->name);
611 view = output->fullscreen_view.fs->view;
612 assert(view->is_mapped == true ||
613 view->surface->is_mapped == true);
615 view->is_mapped = false;
616 view->surface->is_mapped = false;
618 weston_layer_entry_remove(&view->layer_link);
619 weston_view_update_transform(view);
621 weston_output_damage(output->output);
625 insert_black_surface(struct ivi_output *output)
627 struct weston_view *view;
630 !output->fullscreen_view.fs &&
631 !output->fullscreen_view.fs->view) || !output->output) {
632 weston_log("Output %s doesn't have a surface installed!\n", output->name);
636 view = output->fullscreen_view.fs->view;
637 if (view->is_mapped || view->surface->is_mapped)
640 weston_layer_entry_remove(&view->layer_link);
641 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
644 view->is_mapped = true;
645 view->surface->is_mapped = true;
647 weston_view_update_transform(view);
648 weston_output_damage(output->output);
652 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
654 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
655 struct ivi_output *output;
656 struct ivi_surface *surface, *tmp;
658 /* Init already finished. Do nothing */
659 if (ivi->shell_client.ready)
662 ivi->shell_client.ready = true;
664 wl_list_for_each(output, &ivi->outputs, link) {
665 if (output->background)
666 remove_black_surface(output);
667 ivi_layout_init(ivi, output);
670 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
671 wl_list_remove(&surface->link);
672 ivi_check_pending_desktop_surface(surface);
677 shell_set_background(struct wl_client *client,
678 struct wl_resource *shell_res,
679 struct wl_resource *surface_res,
680 struct wl_resource *output_res)
682 struct weston_head *head = weston_head_from_resource(output_res);
683 struct weston_output *woutput = weston_head_get_output(head);
684 struct ivi_output *output = to_ivi_output(woutput);
685 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
686 struct weston_desktop_surface *dsurface;
687 struct ivi_surface *surface;
689 dsurface = weston_surface_get_desktop_surface(wsurface);
691 wl_resource_post_error(shell_res,
692 AGL_SHELL_ERROR_INVALID_ARGUMENT,
693 "surface must be a desktop surface");
697 surface = weston_desktop_surface_get_user_data(dsurface);
698 if (surface->role != IVI_SURFACE_ROLE_NONE) {
699 wl_resource_post_error(shell_res,
700 AGL_SHELL_ERROR_INVALID_ARGUMENT,
701 "surface already has another ivi role");
705 if (output->background) {
706 wl_resource_post_error(shell_res,
707 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
708 "output already has background");
712 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
713 surface->bg.output = output;
714 wl_list_remove(&surface->link);
715 wl_list_init(&surface->link);
717 output->background = surface;
719 weston_desktop_surface_set_maximized(dsurface, true);
720 weston_desktop_surface_set_size(dsurface,
721 output->output->width,
722 output->output->height);
726 shell_set_panel(struct wl_client *client,
727 struct wl_resource *shell_res,
728 struct wl_resource *surface_res,
729 struct wl_resource *output_res,
732 struct weston_head *head = weston_head_from_resource(output_res);
733 struct weston_output *woutput = weston_head_get_output(head);
734 struct ivi_output *output = to_ivi_output(woutput);
735 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
736 struct weston_desktop_surface *dsurface;
737 struct ivi_surface *surface;
738 struct ivi_surface **member;
739 int32_t width = 0, height = 0;
741 dsurface = weston_surface_get_desktop_surface(wsurface);
743 wl_resource_post_error(shell_res,
744 AGL_SHELL_ERROR_INVALID_ARGUMENT,
745 "surface must be a desktop surface");
749 surface = weston_desktop_surface_get_user_data(dsurface);
750 if (surface->role != IVI_SURFACE_ROLE_NONE) {
751 wl_resource_post_error(shell_res,
752 AGL_SHELL_ERROR_INVALID_ARGUMENT,
753 "surface already has another ivi role");
758 case AGL_SHELL_EDGE_TOP:
759 member = &output->top;
761 case AGL_SHELL_EDGE_BOTTOM:
762 member = &output->bottom;
764 case AGL_SHELL_EDGE_LEFT:
765 member = &output->left;
767 case AGL_SHELL_EDGE_RIGHT:
768 member = &output->right;
771 wl_resource_post_error(shell_res,
772 AGL_SHELL_ERROR_INVALID_ARGUMENT,
773 "invalid edge for panel");
778 wl_resource_post_error(shell_res,
779 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
780 "output already has panel on this edge");
784 surface->role = IVI_SURFACE_ROLE_PANEL;
785 surface->panel.output = output;
786 surface->panel.edge = edge;
787 wl_list_remove(&surface->link);
788 wl_list_init(&surface->link);
792 switch (surface->panel.edge) {
793 case AGL_SHELL_EDGE_TOP:
794 case AGL_SHELL_EDGE_BOTTOM:
795 width = woutput->width;
797 case AGL_SHELL_EDGE_LEFT:
798 case AGL_SHELL_EDGE_RIGHT:
799 height = woutput->height;
803 weston_desktop_surface_set_size(dsurface, width, height);
807 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
808 const char *data, uint32_t app_state)
810 struct desktop_client *dclient;
812 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
813 struct ivi_policy *policy = ivi->policy;
815 /* FIXME: should queue it here and see when binding agl-shell-desktop
816 * if there are any to be sent */
823 if (policy && policy->api.surface_advertise_state_change &&
824 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
828 app_role = surf->role;
829 if (app_role == IVI_SURFACE_ROLE_POPUP)
830 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
832 wl_list_for_each(dclient, &ivi->desktop_clients, link)
833 agl_shell_desktop_send_state_app(dclient->resource, app_id,
834 data, app_state, app_role);
838 shell_activate_app(struct wl_client *client,
839 struct wl_resource *shell_res,
841 struct wl_resource *output_res)
843 struct weston_head *head = weston_head_from_resource(output_res);
844 struct weston_output *woutput = weston_head_get_output(head);
845 struct ivi_output *output = to_ivi_output(woutput);
847 ivi_layout_activate(output, app_id);
851 shell_desktop_activate_app(struct wl_client *client,
852 struct wl_resource *shell_res,
853 const char *app_id, const char *data,
854 struct wl_resource *output_res)
856 struct weston_head *head = weston_head_from_resource(output_res);
857 struct weston_output *woutput = weston_head_get_output(head);
858 struct ivi_output *output = to_ivi_output(woutput);
860 ivi_layout_activate(output, app_id);
861 shell_advertise_app_state(output->ivi, app_id,
862 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
866 shell_deactivate_app(struct wl_client *client,
867 struct wl_resource *shell_res,
870 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
871 struct ivi_compositor *ivi = dclient->ivi;
873 ivi_layout_deactivate(ivi, app_id);
874 shell_advertise_app_state(ivi, app_id,
875 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
878 static const struct agl_shell_interface agl_shell_implementation = {
879 .ready = shell_ready,
880 .set_background = shell_set_background,
881 .set_panel = shell_set_panel,
882 .activate_app = shell_activate_app,
886 shell_desktop_set_app_property(struct wl_client *client,
887 struct wl_resource *shell_res,
888 const char *app_id, uint32_t role,
889 int x, int y, int bx, int by,
890 int width, int height,
891 struct wl_resource *output_res)
893 struct weston_head *head = weston_head_from_resource(output_res);
894 struct weston_output *woutput = weston_head_get_output(head);
895 struct ivi_output *output = to_ivi_output(woutput);
898 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
899 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
900 width, height, app_id);
902 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
903 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
905 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
906 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
907 ivi_set_pending_desktop_surface_split(output, app_id, role);
909 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
910 ivi_set_pending_desktop_surface_remote(output, app_id);
917 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
918 .activate_app = shell_desktop_activate_app,
919 .set_app_property = shell_desktop_set_app_property,
920 .deactivate_app = shell_deactivate_app,
924 unbind_agl_shell(struct wl_resource *resource)
926 struct ivi_compositor *ivi;
927 struct ivi_output *output;
928 struct ivi_surface *surf, *surf_tmp;
930 ivi = wl_resource_get_user_data(resource);
931 wl_list_for_each(output, &ivi->outputs, link) {
932 /* reset the active surf if there's one present */
933 if (output->active) {
934 output->active->view->is_mapped = false;
935 output->active->view->surface->is_mapped = false;
937 weston_layer_entry_remove(&output->active->view->layer_link);
938 output->active = NULL;
941 insert_black_surface(output);
944 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
945 wl_list_remove(&surf->link);
946 wl_list_init(&surf->link);
949 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
950 wl_list_remove(&surf->link);
951 wl_list_init(&surf->link);
954 wl_list_init(&ivi->surfaces);
955 wl_list_init(&ivi->pending_surfaces);
957 ivi->shell_client.ready = false;
958 ivi->shell_client.resource = NULL;
959 ivi->shell_client.client = NULL;
963 bind_agl_shell(struct wl_client *client,
964 void *data, uint32_t version, uint32_t id)
966 struct ivi_compositor *ivi = data;
967 struct wl_resource *resource;
968 struct ivi_policy *policy;
971 policy = ivi->policy;
972 interface = (void *) &agl_shell_interface;
973 if (policy && policy->api.shell_bind_interface &&
974 !policy->api.shell_bind_interface(client, interface)) {
975 wl_client_post_implementation_error(client,
976 "client not authorized to use agl_shell");
980 resource = wl_resource_create(client, &agl_shell_interface,
983 wl_client_post_no_memory(client);
988 if (ivi->shell_client.client != client) {
989 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
990 "client not authorized to use agl_shell");
995 if (ivi->shell_client.resource) {
996 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
997 "agl_shell has already been bound");
1001 wl_resource_set_implementation(resource, &agl_shell_implementation,
1002 ivi, unbind_agl_shell);
1003 ivi->shell_client.resource = resource;
1007 unbind_agl_shell_desktop(struct wl_resource *resource)
1009 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1011 wl_list_remove(&dclient->link);
1016 bind_agl_shell_desktop(struct wl_client *client,
1017 void *data, uint32_t version, uint32_t id)
1019 struct ivi_compositor *ivi = data;
1020 struct wl_resource *resource;
1021 struct ivi_policy *policy;
1022 struct desktop_client *dclient;
1025 policy = ivi->policy;
1026 interface = (void *) &agl_shell_desktop_interface;
1027 if (policy && policy->api.shell_bind_interface &&
1028 !policy->api.shell_bind_interface(client, interface)) {
1029 wl_client_post_implementation_error(client,
1030 "client not authorized to use agl_shell_desktop");
1034 dclient = zalloc(sizeof(*dclient));
1036 wl_client_post_no_memory(client);
1040 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1044 wl_client_post_no_memory(client);
1048 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1049 dclient, unbind_agl_shell_desktop);
1051 dclient->resource = resource;
1052 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1054 /* advertise xdg surfaces */
1055 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1059 ivi_shell_create_global(struct ivi_compositor *ivi)
1061 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1062 &agl_shell_interface, 1,
1063 ivi, bind_agl_shell);
1064 if (!ivi->agl_shell) {
1065 weston_log("Failed to create wayland global.\n");
1069 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1070 &agl_shell_desktop_interface, 1,
1071 ivi, bind_agl_shell_desktop);
1072 if (!ivi->agl_shell_desktop) {
1073 weston_log("Failed to create wayland global (agl_shell_desktop).\n");