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 #include <waltham-transmitter/transmitter_api.h>
50 create_black_surface_view(struct ivi_output *output);
53 agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi,
54 struct ivi_surface *surface)
56 struct desktop_client *dclient;
58 /* advertise to all desktop clients the new surface */
59 wl_list_for_each(dclient, &ivi->desktop_clients, link) {
61 weston_desktop_surface_get_app_id(surface->dsurface);
62 agl_shell_desktop_send_application(dclient->resource, app_id);
67 ivi_set_desktop_surface(struct ivi_surface *surface)
69 struct ivi_compositor *ivi = surface->ivi;
70 assert(surface->role == IVI_SURFACE_ROLE_NONE);
72 surface->role = IVI_SURFACE_ROLE_DESKTOP;
73 wl_list_insert(&surface->ivi->surfaces, &surface->link);
75 agl_shell_desktop_advertise_application_id(ivi, surface);
79 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
81 struct ivi_compositor *ivi = surface->ivi;
82 assert(surface->role == IVI_SURFACE_ROLE_NONE);
84 surface->role = IVI_SURFACE_ROLE_POPUP;
85 wl_list_insert(&ivi->surfaces, &surface->link);
87 agl_shell_desktop_advertise_application_id(ivi, surface);
91 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
93 struct ivi_compositor *ivi = surface->ivi;
94 assert(surface->role == IVI_SURFACE_ROLE_NONE);
96 surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
97 wl_list_insert(&ivi->surfaces, &surface->link);
99 agl_shell_desktop_advertise_application_id(ivi, surface);
103 ivi_output_notify_waltham_plugin(struct ivi_surface *surface)
105 struct ivi_compositor *ivi = surface->ivi;
106 const struct weston_transmitter_api *api = ivi->waltham_transmitter_api;
107 struct weston_transmitter *transmitter;
108 struct weston_transmitter_remote *trans_remote;
109 struct weston_surface *weston_surface;
110 struct weston_output *woutput = surface->remote.output->output;
116 transmitter = api->transmitter_get(ivi->compositor);
121 trans_remote = api->get_transmitter_remote(woutput->name, transmitter);
124 weston_log("Could not find a valie weston_transmitter_remote "
125 "that matches the output %s\n", woutput->name);
129 app_id = weston_desktop_surface_get_app_id(surface->dsurface);
131 weston_desktop_surface_get_surface(surface->dsurface);
133 weston_log("Forwarding app_id %s to remote %s\n", app_id, woutput->name);
134 api->surface_push_to_remote(weston_surface, app_id, trans_remote, NULL);
138 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
140 struct ivi_compositor *ivi = surface->ivi;
141 struct weston_view *view;
142 struct ivi_output *output = surface->remote.output;
144 assert(surface->role == IVI_SURFACE_ROLE_NONE);
146 /* remote type are the same as desktop just that client can tell
147 * the compositor to start on another output */
148 surface->role = IVI_SURFACE_ROLE_REMOTE;
150 /* if thew black surface view is mapped on the mean we need
151 * to remove it in order to start showing the 'remote' surface
152 * just being added */
153 view = output->fullscreen_view.fs->view;
154 if (view->is_mapped || view->surface->is_mapped)
155 remove_black_surface(output);
157 if (output->type == OUTPUT_WALTHAM)
158 ivi_output_notify_waltham_plugin(surface);
160 wl_list_insert(&ivi->surfaces, &surface->link);
165 ivi_set_desktop_surface_split(struct ivi_surface *surface)
167 struct ivi_compositor *ivi = surface->ivi;
168 assert(surface->role == IVI_SURFACE_ROLE_NONE);
170 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
171 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
173 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
175 wl_list_insert(&ivi->surfaces, &surface->link);
177 agl_shell_desktop_advertise_application_id(ivi, surface);
181 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput,
182 int x, int y, int bx, int by, int width, int height,
185 struct ivi_compositor *ivi = ioutput->ivi;
186 size_t len_app_id = strlen(app_id);
188 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
190 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
191 memcpy(p_popup->app_id, app_id, len_app_id);
192 p_popup->ioutput = ioutput;
198 p_popup->bb.width = width;
199 p_popup->bb.height = height;
201 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
205 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
208 struct ivi_compositor *ivi = ioutput->ivi;
209 size_t len_app_id = strlen(app_id);
211 struct pending_fullscreen *fs = zalloc(sizeof(*fs));
213 fs->app_id = zalloc(sizeof(char) * (len_app_id + 1));
214 memcpy(fs->app_id, app_id, len_app_id);
216 fs->ioutput = ioutput;
218 wl_list_insert(&ivi->fullscreen_pending_apps, &fs->link);
222 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
223 const char *app_id, uint32_t orientation)
225 struct ivi_compositor *ivi = ioutput->ivi;
226 struct ivi_surface *surf;
227 size_t len_app_id = strlen(app_id);
228 struct pending_split *split;
230 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
231 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
234 /* more than one is un-supported, do note we need to do
235 * conversion for surface roles instead of using the protocol ones */
236 wl_list_for_each(surf, &ivi->surfaces, link)
237 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
238 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
241 split = zalloc(sizeof(*split));
242 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
243 memcpy(split->app_id, app_id, len_app_id);
245 split->ioutput = ioutput;
246 split->orientation = orientation;
248 wl_list_insert(&ivi->split_pending_apps, &split->link);
252 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
255 struct ivi_compositor *ivi = ioutput->ivi;
256 size_t len_app_id = strlen(app_id);
258 struct pending_remote *remote = zalloc(sizeof(*remote));
260 remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
261 memcpy(remote->app_id, app_id, len_app_id);
263 remote->ioutput = ioutput;
265 wl_list_insert(&ivi->remote_pending_apps, &remote->link);
270 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
273 wl_list_remove(&split->link);
278 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
281 wl_list_remove(&fs->link);
286 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
288 free(p_popup->app_id);
289 wl_list_remove(&p_popup->link);
294 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
296 free(remote->app_id);
297 wl_list_remove(&remote->link);
302 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
304 struct ivi_compositor *ivi = surface->ivi;
305 struct pending_popup *p_popup, *next_p_popup;
306 const char *_app_id =
307 weston_desktop_surface_get_app_id(surface->dsurface);
309 if (wl_list_empty(&ivi->popup_pending_apps) || !_app_id)
312 wl_list_for_each_safe(p_popup, next_p_popup,
313 &ivi->popup_pending_apps, link) {
314 if (!strcmp(_app_id, p_popup->app_id)) {
315 surface->popup.output = p_popup->ioutput;
316 surface->popup.x = p_popup->x;
317 surface->popup.y = p_popup->y;
319 surface->popup.bb.x = p_popup->bb.x;
320 surface->popup.bb.y = p_popup->bb.y;
321 surface->popup.bb.width = p_popup->bb.width;
322 surface->popup.bb.height = p_popup->bb.height;
324 ivi_remove_pending_desktop_surface_popup(p_popup);
333 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
335 struct pending_split *split_surf, *next_split_surf;
336 struct ivi_compositor *ivi = surface->ivi;
337 const char *_app_id =
338 weston_desktop_surface_get_app_id(surface->dsurface);
340 if (wl_list_empty(&ivi->split_pending_apps) || !_app_id)
343 wl_list_for_each_safe(split_surf, next_split_surf,
344 &ivi->split_pending_apps, link) {
345 if (!strcmp(_app_id, split_surf->app_id)) {
346 surface->split.output = split_surf->ioutput;
347 surface->split.orientation = split_surf->orientation;
348 ivi_remove_pending_desktop_surface_split(split_surf);
357 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
359 struct pending_fullscreen *fs_surf, *next_fs_surf;
360 struct ivi_compositor *ivi = surface->ivi;
361 const char *_app_id =
362 weston_desktop_surface_get_app_id(surface->dsurface);
364 if (wl_list_empty(&ivi->fullscreen_pending_apps) || !_app_id)
367 wl_list_for_each_safe(fs_surf, next_fs_surf,
368 &ivi->fullscreen_pending_apps, link) {
369 if (!strcmp(_app_id, fs_surf->app_id)) {
370 surface->fullscreen.output = fs_surf->ioutput;
371 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
380 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
382 struct pending_remote *remote_surf, *next_remote_surf;
383 struct ivi_compositor *ivi = surface->ivi;
384 const char *_app_id =
385 weston_desktop_surface_get_app_id(surface->dsurface);
387 if (wl_list_empty(&ivi->remote_pending_apps) || !_app_id)
390 wl_list_for_each_safe(remote_surf, next_remote_surf,
391 &ivi->remote_pending_apps, link) {
392 if (!strcmp(_app_id, remote_surf->app_id)) {
393 surface->remote.output = remote_surf->ioutput;
394 ivi_remove_pending_desktop_surface_remote(remote_surf);
404 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
408 ret = ivi_check_pending_desktop_surface_popup(surface);
410 ivi_set_desktop_surface_popup(surface);
411 ivi_layout_popup_committed(surface);
415 ret = ivi_check_pending_desktop_surface_split(surface);
417 ivi_set_desktop_surface_split(surface);
418 ivi_layout_split_committed(surface);
422 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
424 ivi_set_desktop_surface_fullscreen(surface);
425 ivi_layout_fullscreen_committed(surface);
429 ret = ivi_check_pending_desktop_surface_remote(surface);
431 ivi_set_desktop_surface_remote(surface);
432 ivi_layout_desktop_committed(surface);
436 /* if we end up here means we have a regular desktop app and
437 * try to activate it */
438 ivi_set_desktop_surface(surface);
439 ivi_layout_desktop_committed(surface);
443 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
445 struct ivi_output *out;
447 wl_list_for_each(out, &ivi->outputs, link) {
448 create_black_surface_view(out);
449 insert_black_surface(out);
454 ivi_shell_init(struct ivi_compositor *ivi)
456 weston_layer_init(&ivi->hidden, ivi->compositor);
457 weston_layer_init(&ivi->background, ivi->compositor);
458 weston_layer_init(&ivi->normal, ivi->compositor);
459 weston_layer_init(&ivi->panel, ivi->compositor);
460 weston_layer_init(&ivi->popup, ivi->compositor);
461 weston_layer_init(&ivi->fullscreen, ivi->compositor);
463 weston_layer_set_position(&ivi->hidden,
464 WESTON_LAYER_POSITION_HIDDEN);
465 weston_layer_set_position(&ivi->background,
466 WESTON_LAYER_POSITION_BACKGROUND);
467 weston_layer_set_position(&ivi->normal,
468 WESTON_LAYER_POSITION_NORMAL);
469 weston_layer_set_position(&ivi->panel,
470 WESTON_LAYER_POSITION_UI);
471 weston_layer_set_position(&ivi->popup,
472 WESTON_LAYER_POSITION_TOP_UI);
473 weston_layer_set_position(&ivi->fullscreen,
474 WESTON_LAYER_POSITION_FULLSCREEN);
480 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
482 struct ivi_surface *surface;
484 wl_list_for_each(surface, &ivi->surfaces, link) {
486 weston_desktop_surface_get_app_id(surface->dsurface);
487 agl_shell_desktop_send_application(resource, app_id);
492 client_exec(const char *command, int fd)
497 /* Don't give the child our signal mask */
499 sigprocmask(SIG_UNBLOCK, &sig, NULL);
501 /* Launch clients as the user; don't give them the wrong euid */
502 if (seteuid(getuid()) == -1) {
503 weston_log("seteuid failed: %s\n", strerror(errno));
507 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
508 * clobbering fd, as we'll exit/exec either way.
512 weston_log("dup failed: %s\n", strerror(errno));
516 snprintf(s, sizeof s, "%d", fd);
517 setenv("WAYLAND_SOCKET", s, 1);
519 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
520 weston_log("executing '%s' failed: %s", command, strerror(errno));
523 static struct wl_client *
524 launch_shell_client(struct ivi_compositor *ivi, const char *command)
526 struct wl_client *client;
530 weston_log("launching' %s'\n", command);
532 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
533 weston_log("socketpair failed while launching '%s': %s\n",
534 command, strerror(errno));
542 weston_log("fork failed while launching '%s': %s\n",
543 command, strerror(errno));
548 client_exec(command, sock[1]);
553 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
556 weston_log("Failed to create wayland client for '%s'",
565 ivi_launch_shell_client(struct ivi_compositor *ivi)
567 struct weston_config_section *section;
568 char *command = NULL;
570 section = weston_config_get_section(ivi->config, "shell-client",
573 weston_config_section_get_string(section, "command",
579 ivi->shell_client.client = launch_shell_client(ivi, command);
580 if (!ivi->shell_client.client)
587 destroy_black_view(struct wl_listener *listener, void *data)
589 struct fullscreen_view *fs =
590 wl_container_of(listener, fs, fs_destroy);
594 if (fs->fs->view && fs->fs->view->surface) {
595 weston_surface_destroy(fs->fs->view->surface);
600 wl_list_remove(&fs->fs_destroy.link);
606 create_black_surface_view(struct ivi_output *output)
608 struct weston_surface *surface = NULL;
609 struct weston_view *view;
610 struct ivi_compositor *ivi = output->ivi;
611 struct weston_compositor *wc= ivi->compositor;
612 struct weston_output *woutput = output->output;
617 surface = weston_surface_create(wc);
618 view = weston_view_create(surface);
620 assert(view || surface);
622 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
623 weston_surface_set_size(surface, woutput->width, woutput->height);
624 weston_view_set_position(view, woutput->x, woutput->y);
626 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
627 output->fullscreen_view.fs->view = view;
629 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
630 wl_signal_add(&woutput->destroy_signal,
631 &output->fullscreen_view.fs_destroy);
635 remove_black_surface(struct ivi_output *output)
637 struct weston_view *view;
640 !output->fullscreen_view.fs &&
641 !output->fullscreen_view.fs->view) {
642 weston_log("Output %s doesn't have a surface installed!\n", output->name);
646 view = output->fullscreen_view.fs->view;
647 assert(view->is_mapped == true ||
648 view->surface->is_mapped == true);
650 view->is_mapped = false;
651 view->surface->is_mapped = false;
653 weston_layer_entry_remove(&view->layer_link);
654 weston_view_update_transform(view);
656 weston_output_damage(output->output);
660 insert_black_surface(struct ivi_output *output)
662 struct weston_view *view;
665 !output->fullscreen_view.fs &&
666 !output->fullscreen_view.fs->view) || !output->output) {
667 weston_log("Output %s doesn't have a surface installed!\n", output->name);
671 view = output->fullscreen_view.fs->view;
672 if (view->is_mapped || view->surface->is_mapped)
675 weston_layer_entry_remove(&view->layer_link);
676 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
679 view->is_mapped = true;
680 view->surface->is_mapped = true;
682 weston_view_update_transform(view);
683 weston_output_damage(output->output);
687 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
689 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
690 struct ivi_output *output;
691 struct ivi_surface *surface, *tmp;
693 /* Init already finished. Do nothing */
694 if (ivi->shell_client.ready)
697 ivi->shell_client.ready = true;
699 wl_list_for_each(output, &ivi->outputs, link) {
700 if (output->background)
701 remove_black_surface(output);
702 ivi_layout_init(ivi, output);
705 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
706 wl_list_remove(&surface->link);
707 ivi_check_pending_desktop_surface(surface);
712 shell_set_background(struct wl_client *client,
713 struct wl_resource *shell_res,
714 struct wl_resource *surface_res,
715 struct wl_resource *output_res)
717 struct weston_head *head = weston_head_from_resource(output_res);
718 struct weston_output *woutput = weston_head_get_output(head);
719 struct ivi_output *output = to_ivi_output(woutput);
720 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
721 struct weston_desktop_surface *dsurface;
722 struct ivi_surface *surface;
724 dsurface = weston_surface_get_desktop_surface(wsurface);
726 wl_resource_post_error(shell_res,
727 AGL_SHELL_ERROR_INVALID_ARGUMENT,
728 "surface must be a desktop surface");
732 surface = weston_desktop_surface_get_user_data(dsurface);
733 if (surface->role != IVI_SURFACE_ROLE_NONE) {
734 wl_resource_post_error(shell_res,
735 AGL_SHELL_ERROR_INVALID_ARGUMENT,
736 "surface already has another ivi role");
740 if (output->background) {
741 wl_resource_post_error(shell_res,
742 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
743 "output already has background");
747 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
748 surface->bg.output = output;
749 wl_list_remove(&surface->link);
750 wl_list_init(&surface->link);
752 output->background = surface;
754 weston_desktop_surface_set_maximized(dsurface, true);
755 weston_desktop_surface_set_size(dsurface,
756 output->output->width,
757 output->output->height);
761 shell_set_panel(struct wl_client *client,
762 struct wl_resource *shell_res,
763 struct wl_resource *surface_res,
764 struct wl_resource *output_res,
767 struct weston_head *head = weston_head_from_resource(output_res);
768 struct weston_output *woutput = weston_head_get_output(head);
769 struct ivi_output *output = to_ivi_output(woutput);
770 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
771 struct weston_desktop_surface *dsurface;
772 struct ivi_surface *surface;
773 struct ivi_surface **member;
774 int32_t width = 0, height = 0;
776 dsurface = weston_surface_get_desktop_surface(wsurface);
778 wl_resource_post_error(shell_res,
779 AGL_SHELL_ERROR_INVALID_ARGUMENT,
780 "surface must be a desktop surface");
784 surface = weston_desktop_surface_get_user_data(dsurface);
785 if (surface->role != IVI_SURFACE_ROLE_NONE) {
786 wl_resource_post_error(shell_res,
787 AGL_SHELL_ERROR_INVALID_ARGUMENT,
788 "surface already has another ivi role");
793 case AGL_SHELL_EDGE_TOP:
794 member = &output->top;
796 case AGL_SHELL_EDGE_BOTTOM:
797 member = &output->bottom;
799 case AGL_SHELL_EDGE_LEFT:
800 member = &output->left;
802 case AGL_SHELL_EDGE_RIGHT:
803 member = &output->right;
806 wl_resource_post_error(shell_res,
807 AGL_SHELL_ERROR_INVALID_ARGUMENT,
808 "invalid edge for panel");
813 wl_resource_post_error(shell_res,
814 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
815 "output already has panel on this edge");
819 surface->role = IVI_SURFACE_ROLE_PANEL;
820 surface->panel.output = output;
821 surface->panel.edge = edge;
822 wl_list_remove(&surface->link);
823 wl_list_init(&surface->link);
827 switch (surface->panel.edge) {
828 case AGL_SHELL_EDGE_TOP:
829 case AGL_SHELL_EDGE_BOTTOM:
830 width = woutput->width;
832 case AGL_SHELL_EDGE_LEFT:
833 case AGL_SHELL_EDGE_RIGHT:
834 height = woutput->height;
838 weston_desktop_surface_set_size(dsurface, width, height);
842 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
843 const char *data, uint32_t app_state)
845 struct desktop_client *dclient;
847 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
848 struct ivi_policy *policy = ivi->policy;
850 /* FIXME: should queue it here and see when binding agl-shell-desktop
851 * if there are any to be sent */
855 if (policy && policy->api.surface_advertise_state_change &&
856 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
860 app_role = surf->role;
861 if (app_role == IVI_SURFACE_ROLE_POPUP)
862 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
864 wl_list_for_each(dclient, &ivi->desktop_clients, link)
865 agl_shell_desktop_send_state_app(dclient->resource, app_id,
866 data, app_state, app_role);
870 shell_activate_app(struct wl_client *client,
871 struct wl_resource *shell_res,
873 struct wl_resource *output_res)
875 struct weston_head *head = weston_head_from_resource(output_res);
876 struct weston_output *woutput = weston_head_get_output(head);
877 struct ivi_output *output = to_ivi_output(woutput);
879 ivi_layout_activate(output, app_id);
883 shell_desktop_activate_app(struct wl_client *client,
884 struct wl_resource *shell_res,
885 const char *app_id, const char *data,
886 struct wl_resource *output_res)
888 struct weston_head *head = weston_head_from_resource(output_res);
889 struct weston_output *woutput = weston_head_get_output(head);
890 struct ivi_output *output = to_ivi_output(woutput);
892 ivi_layout_activate(output, app_id);
893 shell_advertise_app_state(output->ivi, app_id,
894 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
898 shell_deactivate_app(struct wl_client *client,
899 struct wl_resource *shell_res,
902 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
903 struct ivi_compositor *ivi = dclient->ivi;
905 ivi_layout_deactivate(ivi, app_id);
906 shell_advertise_app_state(ivi, app_id,
907 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
910 static const struct agl_shell_interface agl_shell_implementation = {
911 .ready = shell_ready,
912 .set_background = shell_set_background,
913 .set_panel = shell_set_panel,
914 .activate_app = shell_activate_app,
918 shell_desktop_set_app_property(struct wl_client *client,
919 struct wl_resource *shell_res,
920 const char *app_id, uint32_t role,
921 int x, int y, int bx, int by,
922 int width, int height,
923 struct wl_resource *output_res)
925 struct weston_head *head = weston_head_from_resource(output_res);
926 struct weston_output *woutput = weston_head_get_output(head);
927 struct ivi_output *output = to_ivi_output(woutput);
930 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
931 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
932 width, height, app_id);
934 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
935 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
937 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
938 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
939 ivi_set_pending_desktop_surface_split(output, app_id, role);
941 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
942 ivi_set_pending_desktop_surface_remote(output, app_id);
949 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
950 .activate_app = shell_desktop_activate_app,
951 .set_app_property = shell_desktop_set_app_property,
952 .deactivate_app = shell_deactivate_app,
956 unbind_agl_shell(struct wl_resource *resource)
958 struct ivi_compositor *ivi;
959 struct ivi_output *output;
960 struct ivi_surface *surf, *surf_tmp;
962 ivi = wl_resource_get_user_data(resource);
963 wl_list_for_each(output, &ivi->outputs, link) {
964 /* reset the active surf if there's one present */
965 if (output->active) {
966 output->active->view->is_mapped = false;
967 output->active->view->surface->is_mapped = false;
969 weston_layer_entry_remove(&output->active->view->layer_link);
970 output->active = NULL;
973 insert_black_surface(output);
976 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
977 wl_list_remove(&surf->link);
978 wl_list_init(&surf->link);
981 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
982 wl_list_remove(&surf->link);
983 wl_list_init(&surf->link);
986 wl_list_init(&ivi->surfaces);
987 wl_list_init(&ivi->pending_surfaces);
989 ivi->shell_client.ready = false;
990 ivi->shell_client.resource = NULL;
991 ivi->shell_client.client = NULL;
995 bind_agl_shell(struct wl_client *client,
996 void *data, uint32_t version, uint32_t id)
998 struct ivi_compositor *ivi = data;
999 struct wl_resource *resource;
1000 struct ivi_policy *policy;
1003 policy = ivi->policy;
1004 interface = (void *) &agl_shell_interface;
1005 if (policy && policy->api.shell_bind_interface &&
1006 !policy->api.shell_bind_interface(client, interface)) {
1007 wl_client_post_implementation_error(client,
1008 "client not authorized to use agl_shell");
1012 resource = wl_resource_create(client, &agl_shell_interface,
1015 wl_client_post_no_memory(client);
1020 if (ivi->shell_client.client != client) {
1021 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1022 "client not authorized to use agl_shell");
1027 if (ivi->shell_client.resource) {
1028 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1029 "agl_shell has already been bound");
1033 wl_resource_set_implementation(resource, &agl_shell_implementation,
1034 ivi, unbind_agl_shell);
1035 ivi->shell_client.resource = resource;
1039 unbind_agl_shell_desktop(struct wl_resource *resource)
1041 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1043 wl_list_remove(&dclient->link);
1048 bind_agl_shell_desktop(struct wl_client *client,
1049 void *data, uint32_t version, uint32_t id)
1051 struct ivi_compositor *ivi = data;
1052 struct wl_resource *resource;
1053 struct ivi_policy *policy;
1054 struct desktop_client *dclient;
1057 policy = ivi->policy;
1058 interface = (void *) &agl_shell_desktop_interface;
1059 if (policy && policy->api.shell_bind_interface &&
1060 !policy->api.shell_bind_interface(client, interface)) {
1061 wl_client_post_implementation_error(client,
1062 "client not authorized to use agl_shell_desktop");
1066 dclient = zalloc(sizeof(*dclient));
1068 wl_client_post_no_memory(client);
1072 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1076 wl_client_post_no_memory(client);
1080 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1081 dclient, unbind_agl_shell_desktop);
1083 dclient->resource = resource;
1084 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1086 /* advertise xdg surfaces */
1087 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1091 ivi_shell_create_global(struct ivi_compositor *ivi)
1093 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1094 &agl_shell_interface, 1,
1095 ivi, bind_agl_shell);
1096 if (!ivi->agl_shell) {
1097 weston_log("Failed to create wayland global.\n");
1101 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1102 &agl_shell_desktop_interface, 1,
1103 ivi, bind_agl_shell_desktop);
1104 if (!ivi->agl_shell_desktop) {
1105 weston_log("Failed to create wayland global (agl_shell_desktop).\n");