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;
587 surface = weston_surface_create(wc);
588 view = weston_view_create(surface);
590 assert(view || surface);
592 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
593 weston_surface_set_size(surface, woutput->width, woutput->height);
594 weston_view_set_position(view, woutput->x, woutput->y);
596 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
597 output->fullscreen_view.fs->view = view;
599 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
600 wl_signal_add(&woutput->destroy_signal,
601 &output->fullscreen_view.fs_destroy);
605 remove_black_surface(struct ivi_output *output)
607 struct weston_view *view;
610 !output->fullscreen_view.fs &&
611 !output->fullscreen_view.fs->view) {
612 weston_log("Output %s doesn't have a surface installed!\n", output->name);
616 view = output->fullscreen_view.fs->view;
617 assert(view->is_mapped == true ||
618 view->surface->is_mapped == true);
620 view->is_mapped = false;
621 view->surface->is_mapped = false;
623 weston_layer_entry_remove(&view->layer_link);
624 weston_view_update_transform(view);
626 weston_output_damage(output->output);
630 insert_black_surface(struct ivi_output *output)
632 struct weston_view *view;
635 !output->fullscreen_view.fs &&
636 !output->fullscreen_view.fs->view) || !output->output) {
637 weston_log("Output %s doesn't have a surface installed!\n", output->name);
641 view = output->fullscreen_view.fs->view;
642 if (view->is_mapped || view->surface->is_mapped)
645 weston_layer_entry_remove(&view->layer_link);
646 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
649 view->is_mapped = true;
650 view->surface->is_mapped = true;
652 weston_view_update_transform(view);
653 weston_output_damage(output->output);
657 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
659 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
660 struct ivi_output *output;
661 struct ivi_surface *surface, *tmp;
663 /* Init already finished. Do nothing */
664 if (ivi->shell_client.ready)
667 ivi->shell_client.ready = true;
669 wl_list_for_each(output, &ivi->outputs, link) {
670 if (output->background)
671 remove_black_surface(output);
672 ivi_layout_init(ivi, output);
675 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
676 wl_list_remove(&surface->link);
677 ivi_check_pending_desktop_surface(surface);
682 shell_set_background(struct wl_client *client,
683 struct wl_resource *shell_res,
684 struct wl_resource *surface_res,
685 struct wl_resource *output_res)
687 struct weston_head *head = weston_head_from_resource(output_res);
688 struct weston_output *woutput = weston_head_get_output(head);
689 struct ivi_output *output = to_ivi_output(woutput);
690 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
691 struct weston_desktop_surface *dsurface;
692 struct ivi_surface *surface;
694 dsurface = weston_surface_get_desktop_surface(wsurface);
696 wl_resource_post_error(shell_res,
697 AGL_SHELL_ERROR_INVALID_ARGUMENT,
698 "surface must be a desktop surface");
702 surface = weston_desktop_surface_get_user_data(dsurface);
703 if (surface->role != IVI_SURFACE_ROLE_NONE) {
704 wl_resource_post_error(shell_res,
705 AGL_SHELL_ERROR_INVALID_ARGUMENT,
706 "surface already has another ivi role");
710 if (output->background) {
711 wl_resource_post_error(shell_res,
712 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
713 "output already has background");
717 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
718 surface->bg.output = output;
719 wl_list_remove(&surface->link);
720 wl_list_init(&surface->link);
722 output->background = surface;
724 weston_desktop_surface_set_maximized(dsurface, true);
725 weston_desktop_surface_set_size(dsurface,
726 output->output->width,
727 output->output->height);
731 shell_set_panel(struct wl_client *client,
732 struct wl_resource *shell_res,
733 struct wl_resource *surface_res,
734 struct wl_resource *output_res,
737 struct weston_head *head = weston_head_from_resource(output_res);
738 struct weston_output *woutput = weston_head_get_output(head);
739 struct ivi_output *output = to_ivi_output(woutput);
740 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
741 struct weston_desktop_surface *dsurface;
742 struct ivi_surface *surface;
743 struct ivi_surface **member;
744 int32_t width = 0, height = 0;
746 dsurface = weston_surface_get_desktop_surface(wsurface);
748 wl_resource_post_error(shell_res,
749 AGL_SHELL_ERROR_INVALID_ARGUMENT,
750 "surface must be a desktop surface");
754 surface = weston_desktop_surface_get_user_data(dsurface);
755 if (surface->role != IVI_SURFACE_ROLE_NONE) {
756 wl_resource_post_error(shell_res,
757 AGL_SHELL_ERROR_INVALID_ARGUMENT,
758 "surface already has another ivi role");
763 case AGL_SHELL_EDGE_TOP:
764 member = &output->top;
766 case AGL_SHELL_EDGE_BOTTOM:
767 member = &output->bottom;
769 case AGL_SHELL_EDGE_LEFT:
770 member = &output->left;
772 case AGL_SHELL_EDGE_RIGHT:
773 member = &output->right;
776 wl_resource_post_error(shell_res,
777 AGL_SHELL_ERROR_INVALID_ARGUMENT,
778 "invalid edge for panel");
783 wl_resource_post_error(shell_res,
784 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
785 "output already has panel on this edge");
789 surface->role = IVI_SURFACE_ROLE_PANEL;
790 surface->panel.output = output;
791 surface->panel.edge = edge;
792 wl_list_remove(&surface->link);
793 wl_list_init(&surface->link);
797 switch (surface->panel.edge) {
798 case AGL_SHELL_EDGE_TOP:
799 case AGL_SHELL_EDGE_BOTTOM:
800 width = woutput->width;
802 case AGL_SHELL_EDGE_LEFT:
803 case AGL_SHELL_EDGE_RIGHT:
804 height = woutput->height;
808 weston_desktop_surface_set_size(dsurface, width, height);
812 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
813 const char *data, uint32_t app_state)
815 struct desktop_client *dclient;
817 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
818 struct ivi_policy *policy = ivi->policy;
820 /* FIXME: should queue it here and see when binding agl-shell-desktop
821 * if there are any to be sent */
828 if (policy && policy->api.surface_advertise_state_change &&
829 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
833 app_role = surf->role;
834 if (app_role == IVI_SURFACE_ROLE_POPUP)
835 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
837 wl_list_for_each(dclient, &ivi->desktop_clients, link)
838 agl_shell_desktop_send_state_app(dclient->resource, app_id,
839 data, app_state, app_role);
843 shell_activate_app(struct wl_client *client,
844 struct wl_resource *shell_res,
846 struct wl_resource *output_res)
848 struct weston_head *head = weston_head_from_resource(output_res);
849 struct weston_output *woutput = weston_head_get_output(head);
850 struct ivi_output *output = to_ivi_output(woutput);
852 ivi_layout_activate(output, app_id);
856 shell_desktop_activate_app(struct wl_client *client,
857 struct wl_resource *shell_res,
858 const char *app_id, const char *data,
859 struct wl_resource *output_res)
861 struct weston_head *head = weston_head_from_resource(output_res);
862 struct weston_output *woutput = weston_head_get_output(head);
863 struct ivi_output *output = to_ivi_output(woutput);
865 ivi_layout_activate(output, app_id);
866 shell_advertise_app_state(output->ivi, app_id,
867 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
871 shell_deactivate_app(struct wl_client *client,
872 struct wl_resource *shell_res,
875 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
876 struct ivi_compositor *ivi = dclient->ivi;
878 ivi_layout_deactivate(ivi, app_id);
879 shell_advertise_app_state(ivi, app_id,
880 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
883 static const struct agl_shell_interface agl_shell_implementation = {
884 .ready = shell_ready,
885 .set_background = shell_set_background,
886 .set_panel = shell_set_panel,
887 .activate_app = shell_activate_app,
891 shell_desktop_set_app_property(struct wl_client *client,
892 struct wl_resource *shell_res,
893 const char *app_id, uint32_t role,
894 int x, int y, int bx, int by,
895 int width, int height,
896 struct wl_resource *output_res)
898 struct weston_head *head = weston_head_from_resource(output_res);
899 struct weston_output *woutput = weston_head_get_output(head);
900 struct ivi_output *output = to_ivi_output(woutput);
903 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
904 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
905 width, height, app_id);
907 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
908 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
910 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
911 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
912 ivi_set_pending_desktop_surface_split(output, app_id, role);
914 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
915 ivi_set_pending_desktop_surface_remote(output, app_id);
922 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
923 .activate_app = shell_desktop_activate_app,
924 .set_app_property = shell_desktop_set_app_property,
925 .deactivate_app = shell_deactivate_app,
929 unbind_agl_shell(struct wl_resource *resource)
931 struct ivi_compositor *ivi;
932 struct ivi_output *output;
933 struct ivi_surface *surf, *surf_tmp;
935 ivi = wl_resource_get_user_data(resource);
936 wl_list_for_each(output, &ivi->outputs, link) {
937 /* reset the active surf if there's one present */
938 if (output->active) {
939 output->active->view->is_mapped = false;
940 output->active->view->surface->is_mapped = false;
942 weston_layer_entry_remove(&output->active->view->layer_link);
943 output->active = NULL;
946 insert_black_surface(output);
949 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
950 wl_list_remove(&surf->link);
951 wl_list_init(&surf->link);
954 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
955 wl_list_remove(&surf->link);
956 wl_list_init(&surf->link);
959 wl_list_init(&ivi->surfaces);
960 wl_list_init(&ivi->pending_surfaces);
962 ivi->shell_client.ready = false;
963 ivi->shell_client.resource = NULL;
964 ivi->shell_client.client = NULL;
968 bind_agl_shell(struct wl_client *client,
969 void *data, uint32_t version, uint32_t id)
971 struct ivi_compositor *ivi = data;
972 struct wl_resource *resource;
973 struct ivi_policy *policy;
976 policy = ivi->policy;
977 interface = (void *) &agl_shell_interface;
978 if (policy && policy->api.shell_bind_interface &&
979 !policy->api.shell_bind_interface(client, interface)) {
980 wl_client_post_implementation_error(client,
981 "client not authorized to use agl_shell");
985 resource = wl_resource_create(client, &agl_shell_interface,
988 wl_client_post_no_memory(client);
993 if (ivi->shell_client.client != client) {
994 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
995 "client not authorized to use agl_shell");
1000 if (ivi->shell_client.resource) {
1001 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1002 "agl_shell has already been bound");
1006 wl_resource_set_implementation(resource, &agl_shell_implementation,
1007 ivi, unbind_agl_shell);
1008 ivi->shell_client.resource = resource;
1012 unbind_agl_shell_desktop(struct wl_resource *resource)
1014 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1016 wl_list_remove(&dclient->link);
1021 bind_agl_shell_desktop(struct wl_client *client,
1022 void *data, uint32_t version, uint32_t id)
1024 struct ivi_compositor *ivi = data;
1025 struct wl_resource *resource;
1026 struct ivi_policy *policy;
1027 struct desktop_client *dclient;
1030 policy = ivi->policy;
1031 interface = (void *) &agl_shell_desktop_interface;
1032 if (policy && policy->api.shell_bind_interface &&
1033 !policy->api.shell_bind_interface(client, interface)) {
1034 wl_client_post_implementation_error(client,
1035 "client not authorized to use agl_shell_desktop");
1039 dclient = zalloc(sizeof(*dclient));
1041 wl_client_post_no_memory(client);
1045 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1049 wl_client_post_no_memory(client);
1053 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1054 dclient, unbind_agl_shell_desktop);
1056 dclient->resource = resource;
1057 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1059 /* advertise xdg surfaces */
1060 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1064 ivi_shell_create_global(struct ivi_compositor *ivi)
1066 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1067 &agl_shell_interface, 1,
1068 ivi, bind_agl_shell);
1069 if (!ivi->agl_shell) {
1070 weston_log("Failed to create wayland global.\n");
1074 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1075 &agl_shell_desktop_interface, 1,
1076 ivi, bind_agl_shell_desktop);
1077 if (!ivi->agl_shell_desktop) {
1078 weston_log("Failed to create wayland global (agl_shell_desktop).\n");