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 if (fs->fs->view && fs->fs->view->surface) {
565 weston_surface_destroy(fs->fs->view->surface);
570 wl_list_remove(&fs->fs_destroy.link);
576 create_black_surface_view(struct ivi_output *output)
578 struct weston_surface *surface = NULL;
579 struct weston_view *view;
580 struct ivi_compositor *ivi = output->ivi;
581 struct weston_compositor *wc= ivi->compositor;
582 struct weston_output *woutput = output->output;
584 surface = weston_surface_create(wc);
585 view = weston_view_create(surface);
587 assert(view || surface);
589 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
590 weston_surface_set_size(surface, woutput->width, woutput->height);
591 weston_view_set_position(view, woutput->x, woutput->y);
593 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
594 output->fullscreen_view.fs->view = view;
596 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
597 wl_signal_add(&woutput->destroy_signal,
598 &output->fullscreen_view.fs_destroy);
602 remove_black_surface(struct ivi_output *output)
604 struct weston_view *view;
607 !output->fullscreen_view.fs &&
608 !output->fullscreen_view.fs->view) {
609 weston_log("Output %s doesn't have a surface installed!\n", output->name);
613 view = output->fullscreen_view.fs->view;
614 assert(view->is_mapped == true ||
615 view->surface->is_mapped == true);
617 view->is_mapped = false;
618 view->surface->is_mapped = false;
620 weston_layer_entry_remove(&view->layer_link);
621 weston_view_update_transform(view);
623 weston_output_damage(output->output);
627 insert_black_surface(struct ivi_output *output)
629 struct weston_view *view;
632 !output->fullscreen_view.fs &&
633 !output->fullscreen_view.fs->view) {
634 weston_log("Output %s doesn't have a surface installed!\n", output->name);
638 view = output->fullscreen_view.fs->view;
639 if (view->is_mapped || view->surface->is_mapped)
642 weston_layer_entry_remove(&view->layer_link);
643 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
646 view->is_mapped = true;
647 view->surface->is_mapped = true;
649 weston_view_update_transform(view);
650 weston_output_damage(output->output);
654 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
656 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
657 struct ivi_output *output;
658 struct ivi_surface *surface, *tmp;
660 /* Init already finished. Do nothing */
661 if (ivi->shell_client.ready)
664 ivi->shell_client.ready = true;
666 wl_list_for_each(output, &ivi->outputs, link) {
667 if (output->background)
668 remove_black_surface(output);
669 ivi_layout_init(ivi, output);
672 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
673 wl_list_remove(&surface->link);
674 ivi_check_pending_desktop_surface(surface);
679 shell_set_background(struct wl_client *client,
680 struct wl_resource *shell_res,
681 struct wl_resource *surface_res,
682 struct wl_resource *output_res)
684 struct weston_head *head = weston_head_from_resource(output_res);
685 struct weston_output *woutput = weston_head_get_output(head);
686 struct ivi_output *output = to_ivi_output(woutput);
687 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
688 struct weston_desktop_surface *dsurface;
689 struct ivi_surface *surface;
691 dsurface = weston_surface_get_desktop_surface(wsurface);
693 wl_resource_post_error(shell_res,
694 AGL_SHELL_ERROR_INVALID_ARGUMENT,
695 "surface must be a desktop surface");
699 surface = weston_desktop_surface_get_user_data(dsurface);
700 if (surface->role != IVI_SURFACE_ROLE_NONE) {
701 wl_resource_post_error(shell_res,
702 AGL_SHELL_ERROR_INVALID_ARGUMENT,
703 "surface already has another ivi role");
707 if (output->background) {
708 wl_resource_post_error(shell_res,
709 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
710 "output already has background");
714 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
715 surface->bg.output = output;
716 wl_list_remove(&surface->link);
717 wl_list_init(&surface->link);
719 output->background = surface;
721 weston_desktop_surface_set_maximized(dsurface, true);
722 weston_desktop_surface_set_size(dsurface,
723 output->output->width,
724 output->output->height);
728 shell_set_panel(struct wl_client *client,
729 struct wl_resource *shell_res,
730 struct wl_resource *surface_res,
731 struct wl_resource *output_res,
734 struct weston_head *head = weston_head_from_resource(output_res);
735 struct weston_output *woutput = weston_head_get_output(head);
736 struct ivi_output *output = to_ivi_output(woutput);
737 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
738 struct weston_desktop_surface *dsurface;
739 struct ivi_surface *surface;
740 struct ivi_surface **member;
741 int32_t width = 0, height = 0;
743 dsurface = weston_surface_get_desktop_surface(wsurface);
745 wl_resource_post_error(shell_res,
746 AGL_SHELL_ERROR_INVALID_ARGUMENT,
747 "surface must be a desktop surface");
751 surface = weston_desktop_surface_get_user_data(dsurface);
752 if (surface->role != IVI_SURFACE_ROLE_NONE) {
753 wl_resource_post_error(shell_res,
754 AGL_SHELL_ERROR_INVALID_ARGUMENT,
755 "surface already has another ivi role");
760 case AGL_SHELL_EDGE_TOP:
761 member = &output->top;
763 case AGL_SHELL_EDGE_BOTTOM:
764 member = &output->bottom;
766 case AGL_SHELL_EDGE_LEFT:
767 member = &output->left;
769 case AGL_SHELL_EDGE_RIGHT:
770 member = &output->right;
773 wl_resource_post_error(shell_res,
774 AGL_SHELL_ERROR_INVALID_ARGUMENT,
775 "invalid edge for panel");
780 wl_resource_post_error(shell_res,
781 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
782 "output already has panel on this edge");
786 surface->role = IVI_SURFACE_ROLE_PANEL;
787 surface->panel.output = output;
788 surface->panel.edge = edge;
789 wl_list_remove(&surface->link);
790 wl_list_init(&surface->link);
794 switch (surface->panel.edge) {
795 case AGL_SHELL_EDGE_TOP:
796 case AGL_SHELL_EDGE_BOTTOM:
797 width = woutput->width;
799 case AGL_SHELL_EDGE_LEFT:
800 case AGL_SHELL_EDGE_RIGHT:
801 height = woutput->height;
805 weston_desktop_surface_set_size(dsurface, width, height);
809 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
810 const char *data, uint32_t app_state)
812 struct desktop_client *dclient;
814 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
815 struct ivi_policy *policy = ivi->policy;
817 /* FIXME: should queue it here and see when binding agl-shell-desktop
818 * if there are any to be sent */
825 if (policy && policy->api.surface_advertise_state_change &&
826 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
830 app_role = surf->role;
831 if (app_role == IVI_SURFACE_ROLE_POPUP)
832 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
834 wl_list_for_each(dclient, &ivi->desktop_clients, link)
835 agl_shell_desktop_send_state_app(dclient->resource, app_id,
836 data, app_state, app_role);
840 shell_activate_app(struct wl_client *client,
841 struct wl_resource *shell_res,
843 struct wl_resource *output_res)
845 struct weston_head *head = weston_head_from_resource(output_res);
846 struct weston_output *woutput = weston_head_get_output(head);
847 struct ivi_output *output = to_ivi_output(woutput);
849 ivi_layout_activate(output, app_id);
853 shell_desktop_activate_app(struct wl_client *client,
854 struct wl_resource *shell_res,
855 const char *app_id, const char *data,
856 struct wl_resource *output_res)
858 struct weston_head *head = weston_head_from_resource(output_res);
859 struct weston_output *woutput = weston_head_get_output(head);
860 struct ivi_output *output = to_ivi_output(woutput);
862 ivi_layout_activate(output, app_id);
863 shell_advertise_app_state(output->ivi, app_id,
864 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
868 shell_deactivate_app(struct wl_client *client,
869 struct wl_resource *shell_res,
872 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
873 struct ivi_compositor *ivi = dclient->ivi;
875 ivi_layout_deactivate(ivi, app_id);
876 shell_advertise_app_state(ivi, app_id,
877 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
880 static const struct agl_shell_interface agl_shell_implementation = {
881 .ready = shell_ready,
882 .set_background = shell_set_background,
883 .set_panel = shell_set_panel,
884 .activate_app = shell_activate_app,
888 shell_desktop_set_app_property(struct wl_client *client,
889 struct wl_resource *shell_res,
890 const char *app_id, uint32_t role,
891 int x, int y, int bx, int by,
892 int width, int height,
893 struct wl_resource *output_res)
895 struct weston_head *head = weston_head_from_resource(output_res);
896 struct weston_output *woutput = weston_head_get_output(head);
897 struct ivi_output *output = to_ivi_output(woutput);
900 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
901 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
902 width, height, app_id);
904 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
905 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
907 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
908 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
909 ivi_set_pending_desktop_surface_split(output, app_id, role);
911 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
912 ivi_set_pending_desktop_surface_remote(output, app_id);
919 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
920 .activate_app = shell_desktop_activate_app,
921 .set_app_property = shell_desktop_set_app_property,
922 .deactivate_app = shell_deactivate_app,
926 unbind_agl_shell(struct wl_resource *resource)
928 struct ivi_compositor *ivi;
929 struct ivi_output *output;
930 struct ivi_surface *surf, *surf_tmp;
932 ivi = wl_resource_get_user_data(resource);
933 wl_list_for_each(output, &ivi->outputs, link) {
934 /* reset the active surf if there's one present */
935 if (output->active) {
936 output->active->view->is_mapped = false;
937 output->active->view->surface->is_mapped = false;
939 weston_layer_entry_remove(&output->active->view->layer_link);
940 output->active = NULL;
943 insert_black_surface(output);
946 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
947 wl_list_remove(&surf->link);
948 wl_list_init(&surf->link);
951 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
952 wl_list_remove(&surf->link);
953 wl_list_init(&surf->link);
956 wl_list_init(&ivi->surfaces);
957 wl_list_init(&ivi->pending_surfaces);
959 ivi->shell_client.ready = false;
960 ivi->shell_client.resource = NULL;
961 ivi->shell_client.client = NULL;
965 bind_agl_shell(struct wl_client *client,
966 void *data, uint32_t version, uint32_t id)
968 struct ivi_compositor *ivi = data;
969 struct wl_resource *resource;
970 struct ivi_policy *policy;
973 policy = ivi->policy;
974 interface = (void *) &agl_shell_interface;
975 if (policy && policy->api.shell_bind_interface &&
976 !policy->api.shell_bind_interface(client, interface)) {
977 wl_client_post_implementation_error(client,
978 "client not authorized to use agl_shell");
982 resource = wl_resource_create(client, &agl_shell_interface,
985 wl_client_post_no_memory(client);
990 if (ivi->shell_client.client != client) {
991 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
992 "client not authorized to use agl_shell");
997 if (ivi->shell_client.resource) {
998 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
999 "agl_shell has already been bound");
1003 wl_resource_set_implementation(resource, &agl_shell_implementation,
1004 ivi, unbind_agl_shell);
1005 ivi->shell_client.resource = resource;
1009 unbind_agl_shell_desktop(struct wl_resource *resource)
1011 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1013 wl_list_remove(&dclient->link);
1018 bind_agl_shell_desktop(struct wl_client *client,
1019 void *data, uint32_t version, uint32_t id)
1021 struct ivi_compositor *ivi = data;
1022 struct wl_resource *resource;
1023 struct ivi_policy *policy;
1024 struct desktop_client *dclient;
1027 policy = ivi->policy;
1028 interface = (void *) &agl_shell_desktop_interface;
1029 if (policy && policy->api.shell_bind_interface &&
1030 !policy->api.shell_bind_interface(client, interface)) {
1031 wl_client_post_implementation_error(client,
1032 "client not authorized to use agl_shell_desktop");
1036 dclient = zalloc(sizeof(*dclient));
1038 wl_client_post_no_memory(client);
1042 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1046 wl_client_post_no_memory(client);
1050 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1051 dclient, unbind_agl_shell_desktop);
1053 dclient->resource = resource;
1054 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1056 /* advertise xdg surfaces */
1057 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1061 ivi_shell_create_global(struct ivi_compositor *ivi)
1063 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1064 &agl_shell_interface, 1,
1065 ivi, bind_agl_shell);
1066 if (!ivi->agl_shell) {
1067 weston_log("Failed to create wayland global.\n");
1071 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1072 &agl_shell_desktop_interface, 1,
1073 ivi, bind_agl_shell_desktop);
1074 if (!ivi->agl_shell_desktop) {
1075 weston_log("Failed to create wayland global (agl_shell_desktop).\n");