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);
52 static struct ivi_surface *
53 get_ivi_shell_surface(struct weston_surface *wsurface)
55 if (weston_surface_is_desktop_surface(wsurface)) {
56 struct weston_desktop_surface *dsurface =
57 weston_surface_get_desktop_surface(wsurface);
58 return weston_desktop_surface_get_user_data(dsurface);
65 agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi,
66 struct ivi_surface *surface)
68 struct desktop_client *dclient;
69 static bool display_adv = false;
71 if (surface->advertised_on_launch)
74 /* advertise to all desktop clients the new surface */
75 wl_list_for_each(dclient, &ivi->desktop_clients, link) {
77 weston_desktop_surface_get_app_id(surface->dsurface);
80 weston_log("WARNING app_is is null, unable to advertise\n");
85 agl_shell_desktop_send_application(dclient->resource, app_id);
86 surface->advertised_on_launch = true;
91 ivi_set_desktop_surface(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_DESKTOP;
97 wl_list_insert(&surface->ivi->surfaces, &surface->link);
99 agl_shell_desktop_advertise_application_id(ivi, surface);
103 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
105 struct ivi_compositor *ivi = surface->ivi;
106 assert(surface->role == IVI_SURFACE_ROLE_NONE);
108 surface->role = IVI_SURFACE_ROLE_POPUP;
109 wl_list_insert(&ivi->surfaces, &surface->link);
111 agl_shell_desktop_advertise_application_id(ivi, surface);
115 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
117 struct ivi_compositor *ivi = surface->ivi;
118 assert(surface->role == IVI_SURFACE_ROLE_NONE);
120 surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
121 wl_list_insert(&ivi->surfaces, &surface->link);
123 agl_shell_desktop_advertise_application_id(ivi, surface);
128 ivi_destroy_waltham_destroy(struct ivi_surface *surface)
130 struct ivi_compositor *ivi = surface->ivi;
131 const struct weston_transmitter_api *api =
132 ivi->waltham_transmitter_api;
137 if (surface->waltham_surface.transmitter_surface)
138 api->surface_destroy(surface->waltham_surface.transmitter_surface);
142 ivi_output_notify_waltham_plugin(struct ivi_surface *surface)
144 struct ivi_compositor *ivi = surface->ivi;
145 const struct weston_transmitter_api *api = ivi->waltham_transmitter_api;
146 struct weston_transmitter *transmitter;
147 struct weston_transmitter_remote *trans_remote;
148 struct weston_surface *weston_surface;
149 struct weston_output *woutput = surface->remote.output->output;
155 transmitter = api->transmitter_get(ivi->compositor);
159 trans_remote = api->get_transmitter_remote(woutput->name, transmitter);
161 weston_log("Could not find a valie weston_transmitter_remote "
162 "that matches the output %s\n", woutput->name);
166 app_id = weston_desktop_surface_get_app_id(surface->dsurface);
168 weston_desktop_surface_get_surface(surface->dsurface);
170 weston_log("Forwarding app_id %s to remote %s\n", app_id, woutput->name);
172 /* this will have the effect of informing the remote side to create a
173 * surface with the name app_id. W/ xdg-shell the following happens:
175 * compositor (server):
176 * surface_push_to_remote():
177 * waltham-transmitter plug-in
178 * -> wthp_ivi_app_id_surface_create()
180 * client -- on the receiver side:
181 * -> wthp_ivi_app_id_surface_create()
182 * -> wth_receiver_weston_main()
183 * -> wl_compositor_create_surface()
184 * -> xdg_wm_base_get_xdg_surface
185 * -> xdg_toplevel_set_app_id()
187 * -> gst_parse_launch()
189 * wth_receiver_weston_main() will be invoked from the handler of
190 * wthp_ivi_app_id_surface_create() and is responsible for setting-up
191 * the gstreamer pipeline as well.
193 surface->waltham_surface.transmitter_surface =
194 api->surface_push_to_remote(weston_surface, app_id, trans_remote, NULL);
199 ivi_destroy_waltham_destroy(struct ivi_surface *surface)
203 ivi_output_notify_waltham_plugin(struct ivi_surface *surface)
209 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
211 struct ivi_compositor *ivi = surface->ivi;
212 struct weston_view *view;
213 struct ivi_output *output = surface->remote.output;
215 assert(surface->role == IVI_SURFACE_ROLE_NONE);
217 /* remote type are the same as desktop just that client can tell
218 * the compositor to start on another output */
219 surface->role = IVI_SURFACE_ROLE_REMOTE;
221 /* if thew black surface view is mapped on the mean we need
222 * to remove it in order to start showing the 'remote' surface
223 * just being added */
224 view = output->fullscreen_view.fs->view;
225 if (view->is_mapped || view->surface->is_mapped)
226 remove_black_surface(output);
228 if (output->type == OUTPUT_WALTHAM)
229 ivi_output_notify_waltham_plugin(surface);
231 wl_list_insert(&ivi->surfaces, &surface->link);
236 ivi_set_desktop_surface_split(struct ivi_surface *surface)
238 struct ivi_compositor *ivi = surface->ivi;
239 assert(surface->role == IVI_SURFACE_ROLE_NONE);
241 if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
242 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
244 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
246 wl_list_insert(&ivi->surfaces, &surface->link);
248 agl_shell_desktop_advertise_application_id(ivi, surface);
251 static struct pending_popup *
252 ivi_ensure_popup(struct ivi_output *ioutput, int x, int y, int bx, int by,
253 int width, int height, const char *app_id)
255 struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
256 size_t len_app_id = strlen(app_id);
260 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
261 if (!p_popup->app_id) {
265 memcpy(p_popup->app_id, app_id, len_app_id);
266 p_popup->ioutput = ioutput;
272 p_popup->bb.width = width;
273 p_popup->bb.height = height;
279 ivi_update_popup(struct ivi_output *ioutput, int x, int y, int bx, int by,
280 int width, int height, const char *app_id, struct pending_popup *p_popup)
282 size_t len_app_id = strlen(app_id);
284 wl_list_remove(&p_popup->link);
285 wl_list_init(&p_popup->link);
287 memset(p_popup->app_id, 0, strlen(app_id) + 1);
288 free(p_popup->app_id);
290 p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
291 if (!p_popup->app_id)
293 memcpy(p_popup->app_id, app_id, len_app_id);
295 p_popup->ioutput = ioutput;
301 p_popup->bb.width = width;
302 p_popup->bb.height = height;
305 static struct pending_fullscreen *
306 ivi_ensure_fullscreen(struct ivi_output *ioutput, const char *app_id)
308 struct pending_fullscreen *p_fullscreen = zalloc(sizeof(*p_fullscreen));
309 size_t len_app_id = strlen(app_id);
313 p_fullscreen->app_id = zalloc(sizeof(char) * (len_app_id + 1));
314 if (!p_fullscreen->app_id) {
318 memcpy(p_fullscreen->app_id, app_id, len_app_id);
320 p_fullscreen->ioutput = ioutput;
325 ivi_update_fullscreen(struct ivi_output *ioutput, const char *app_id,
326 struct pending_fullscreen *p_fullscreen)
328 size_t len_app_id = strlen(app_id);
330 wl_list_remove(&p_fullscreen->link);
331 wl_list_init(&p_fullscreen->link);
333 memset(p_fullscreen->app_id, 0, strlen(app_id) + 1);
334 free(p_fullscreen->app_id);
336 p_fullscreen->app_id = zalloc(sizeof(char) * (len_app_id + 1));
337 if (!p_fullscreen->app_id)
339 memcpy(p_fullscreen->app_id, app_id, len_app_id);
341 p_fullscreen->ioutput = ioutput;
344 static struct pending_remote *
345 ivi_ensure_remote(struct ivi_output *ioutput, const char *app_id)
347 struct pending_remote *p_remote = zalloc(sizeof(*p_remote));
348 size_t len_app_id = strlen(app_id);
352 p_remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
353 if (!p_remote->app_id) {
357 memcpy(p_remote->app_id, app_id, len_app_id);
359 p_remote->ioutput = ioutput;
364 ivi_update_remote(struct ivi_output *ioutput, const char *app_id,
365 struct pending_remote *p_remote)
367 size_t len_app_id = strlen(app_id);
369 wl_list_remove(&p_remote->link);
370 wl_list_init(&p_remote->link);
372 memset(p_remote->app_id, 0, strlen(app_id) + 1);
373 free(p_remote->app_id);
375 p_remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
376 if (!p_remote->app_id)
378 memcpy(p_remote->app_id, app_id, len_app_id);
380 p_remote->ioutput = ioutput;
384 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput, int x, int y, int bx,
385 int by, int width, int height, const char *app_id)
387 struct ivi_compositor *ivi = ioutput->ivi;
388 struct pending_popup *p_popup = NULL;
389 struct pending_popup *popup;
391 wl_list_for_each(popup, &ivi->popup_pending_apps, link)
392 if (!strcmp(app_id, popup->app_id))
396 p_popup = ivi_ensure_popup(ioutput, x, y, bx, by, width, height, app_id);
398 ivi_update_popup(ioutput, x, y, bx, by, width, height, app_id, p_popup);
402 wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
406 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
409 struct ivi_compositor *ivi = ioutput->ivi;
410 struct pending_fullscreen *p_fullscreen = NULL;
411 struct pending_fullscreen *fullscreen;
413 wl_list_for_each(fullscreen, &ivi->fullscreen_pending_apps, link)
414 if (!strcmp(app_id, fullscreen->app_id))
415 p_fullscreen = fullscreen;
418 p_fullscreen = ivi_ensure_fullscreen(ioutput, app_id);
420 ivi_update_fullscreen(ioutput, app_id, p_fullscreen);
424 wl_list_insert(&ivi->fullscreen_pending_apps, &p_fullscreen->link);
428 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
429 const char *app_id, uint32_t orientation)
431 struct ivi_compositor *ivi = ioutput->ivi;
432 struct ivi_surface *surf;
433 size_t len_app_id = strlen(app_id);
434 struct pending_split *split;
436 if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
437 orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
440 /* more than one is un-supported, do note we need to do
441 * conversion for surface roles instead of using the protocol ones */
442 wl_list_for_each(surf, &ivi->surfaces, link)
443 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
444 surf->role == IVI_SURFACE_ROLE_SPLIT_H)
447 split = zalloc(sizeof(*split));
450 split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
451 if (!split->app_id) {
455 memcpy(split->app_id, app_id, len_app_id);
457 split->ioutput = ioutput;
458 split->orientation = orientation;
460 wl_list_insert(&ivi->split_pending_apps, &split->link);
464 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
467 struct ivi_compositor *ivi = ioutput->ivi;
468 struct pending_remote *remote;
469 struct pending_remote *p_remote = NULL;
471 wl_list_for_each(remote, &ivi->remote_pending_apps, link)
472 if (!strcmp(app_id, remote->app_id))
476 p_remote = ivi_ensure_remote(ioutput, app_id);
478 ivi_update_remote(ioutput, app_id, p_remote);
482 wl_list_insert(&ivi->remote_pending_apps, &remote->link);
487 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
490 wl_list_remove(&split->link);
495 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
498 wl_list_remove(&fs->link);
503 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
505 free(p_popup->app_id);
506 wl_list_remove(&p_popup->link);
511 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
513 free(remote->app_id);
514 wl_list_remove(&remote->link);
519 ivi_compositor_keep_pending_surfaces(struct ivi_surface *surface)
521 return surface->ivi->keep_pending_surfaces;
525 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
527 struct ivi_compositor *ivi = surface->ivi;
528 struct pending_popup *p_popup, *next_p_popup;
529 const char *_app_id =
530 weston_desktop_surface_get_app_id(surface->dsurface);
532 if (wl_list_empty(&ivi->popup_pending_apps) || !_app_id)
535 wl_list_for_each_safe(p_popup, next_p_popup,
536 &ivi->popup_pending_apps, link) {
537 if (!strcmp(_app_id, p_popup->app_id)) {
538 surface->popup.output = p_popup->ioutput;
539 surface->popup.x = p_popup->x;
540 surface->popup.y = p_popup->y;
542 surface->popup.bb.x = p_popup->bb.x;
543 surface->popup.bb.y = p_popup->bb.y;
544 surface->popup.bb.width = p_popup->bb.width;
545 surface->popup.bb.height = p_popup->bb.height;
547 if (!ivi_compositor_keep_pending_surfaces(surface))
548 ivi_remove_pending_desktop_surface_popup(p_popup);
557 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
559 struct pending_split *split_surf, *next_split_surf;
560 struct ivi_compositor *ivi = surface->ivi;
561 const char *_app_id =
562 weston_desktop_surface_get_app_id(surface->dsurface);
564 if (wl_list_empty(&ivi->split_pending_apps) || !_app_id)
567 wl_list_for_each_safe(split_surf, next_split_surf,
568 &ivi->split_pending_apps, link) {
569 if (!strcmp(_app_id, split_surf->app_id)) {
570 surface->split.output = split_surf->ioutput;
571 surface->split.orientation = split_surf->orientation;
572 if (!ivi_compositor_keep_pending_surfaces(surface))
573 ivi_remove_pending_desktop_surface_split(split_surf);
582 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
584 struct pending_fullscreen *fs_surf, *next_fs_surf;
585 struct ivi_compositor *ivi = surface->ivi;
586 const char *_app_id =
587 weston_desktop_surface_get_app_id(surface->dsurface);
589 if (wl_list_empty(&ivi->fullscreen_pending_apps) || !_app_id)
592 wl_list_for_each_safe(fs_surf, next_fs_surf,
593 &ivi->fullscreen_pending_apps, link) {
594 if (!strcmp(_app_id, fs_surf->app_id)) {
595 surface->fullscreen.output = fs_surf->ioutput;
596 if (!ivi_compositor_keep_pending_surfaces(surface))
597 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
606 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
608 struct pending_remote *remote_surf, *next_remote_surf;
609 struct ivi_compositor *ivi = surface->ivi;
610 const char *_app_id =
611 weston_desktop_surface_get_app_id(surface->dsurface);
613 if (wl_list_empty(&ivi->remote_pending_apps) || !_app_id)
616 wl_list_for_each_safe(remote_surf, next_remote_surf,
617 &ivi->remote_pending_apps, link) {
618 if (!strcmp(_app_id, remote_surf->app_id)) {
619 surface->remote.output = remote_surf->ioutput;
620 if (!ivi_compositor_keep_pending_surfaces(surface))
621 ivi_remove_pending_desktop_surface_remote(remote_surf);
629 ivi_check_pending_surface_desktop(struct ivi_surface *surface,
630 enum ivi_surface_role *role)
632 struct ivi_compositor *ivi = surface->ivi;
633 struct wl_list *role_pending_list;
634 struct pending_popup *p_popup;
635 struct pending_split *p_split;
636 struct pending_fullscreen *p_fullscreen;
637 struct pending_remote *p_remote;
639 weston_desktop_surface_get_app_id(surface->dsurface);
642 *role = IVI_SURFACE_ROLE_NONE;
646 role_pending_list = &ivi->popup_pending_apps;
647 wl_list_for_each(p_popup, role_pending_list, link) {
648 if (!strcmp(app_id, p_popup->app_id)) {
649 *role = IVI_SURFACE_ROLE_POPUP;
654 role_pending_list = &ivi->split_pending_apps;
655 wl_list_for_each(p_split, role_pending_list, link) {
656 if (!strcmp(app_id, p_split->app_id)) {
657 *role = IVI_SURFACE_ROLE_SPLIT_V;
662 role_pending_list = &ivi->fullscreen_pending_apps;
663 wl_list_for_each(p_fullscreen, role_pending_list, link) {
664 if (!strcmp(app_id, p_fullscreen->app_id)) {
665 *role = IVI_SURFACE_ROLE_FULLSCREEN;
670 role_pending_list = &ivi->remote_pending_apps;
671 wl_list_for_each(p_remote, role_pending_list, link) {
672 if (!strcmp(app_id, p_remote->app_id)) {
673 *role = IVI_SURFACE_ROLE_REMOTE;
678 /* else, we are a regular desktop surface */
679 *role = IVI_SURFACE_ROLE_DESKTOP;
684 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
688 ret = ivi_check_pending_desktop_surface_popup(surface);
690 ivi_set_desktop_surface_popup(surface);
691 ivi_layout_popup_committed(surface);
695 ret = ivi_check_pending_desktop_surface_split(surface);
697 ivi_set_desktop_surface_split(surface);
698 ivi_layout_split_committed(surface);
702 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
704 ivi_set_desktop_surface_fullscreen(surface);
705 ivi_layout_fullscreen_committed(surface);
709 ret = ivi_check_pending_desktop_surface_remote(surface);
711 ivi_set_desktop_surface_remote(surface);
712 ivi_layout_desktop_committed(surface);
716 /* if we end up here means we have a regular desktop app and
717 * try to activate it */
718 ivi_set_desktop_surface(surface);
719 ivi_layout_desktop_committed(surface);
723 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
725 struct ivi_output *out;
727 wl_list_for_each(out, &ivi->outputs, link) {
728 create_black_surface_view(out);
729 insert_black_surface(out);
734 ivi_shell_init(struct ivi_compositor *ivi)
736 weston_layer_init(&ivi->hidden, ivi->compositor);
737 weston_layer_init(&ivi->background, ivi->compositor);
738 weston_layer_init(&ivi->normal, ivi->compositor);
739 weston_layer_init(&ivi->panel, ivi->compositor);
740 weston_layer_init(&ivi->popup, ivi->compositor);
741 weston_layer_init(&ivi->fullscreen, ivi->compositor);
743 weston_layer_set_position(&ivi->hidden,
744 WESTON_LAYER_POSITION_HIDDEN);
745 weston_layer_set_position(&ivi->background,
746 WESTON_LAYER_POSITION_BACKGROUND);
747 weston_layer_set_position(&ivi->normal,
748 WESTON_LAYER_POSITION_NORMAL);
749 weston_layer_set_position(&ivi->panel,
750 WESTON_LAYER_POSITION_UI);
751 weston_layer_set_position(&ivi->popup,
752 WESTON_LAYER_POSITION_TOP_UI);
753 weston_layer_set_position(&ivi->fullscreen,
754 WESTON_LAYER_POSITION_FULLSCREEN);
761 ivi_surf_destroy(struct ivi_surface *surf)
763 struct weston_surface *wsurface = surf->view->surface;
765 if (weston_surface_is_mapped(wsurface)) {
766 weston_desktop_surface_unlink_view(surf->view);
767 weston_view_destroy(surf->view);
770 wl_list_remove(&surf->link);
775 ivi_shell_destroy_views_on_layer(struct weston_layer *layer)
777 struct weston_view *view, *view_next;
779 wl_list_for_each_safe(view, view_next, &layer->view_list.link, layer_link.link) {
780 struct ivi_surface *ivi_surf =
781 get_ivi_shell_surface(view->surface);
783 ivi_surf_destroy(ivi_surf);
788 ivi_shell_destroy_views_on_fullscreen_layer(struct ivi_compositor *ivi)
790 struct ivi_output *ivi_output;
792 wl_list_for_each(ivi_output, &ivi->outputs, link)
793 weston_surface_destroy(ivi_output->fullscreen_view.fs->view->surface);
797 ivi_shell_finalize(struct ivi_compositor *ivi)
799 ivi_shell_destroy_views_on_layer(&ivi->hidden);
800 weston_layer_fini(&ivi->hidden);
802 ivi_shell_destroy_views_on_layer(&ivi->background);
803 weston_layer_fini(&ivi->background);
805 ivi_shell_destroy_views_on_layer(&ivi->normal);
806 weston_layer_fini(&ivi->normal);
808 ivi_shell_destroy_views_on_layer(&ivi->panel);
809 weston_layer_fini(&ivi->panel);
811 ivi_shell_destroy_views_on_layer(&ivi->popup);
812 weston_layer_fini(&ivi->popup);
814 ivi_shell_destroy_views_on_fullscreen_layer(ivi);
815 weston_layer_fini(&ivi->fullscreen);
819 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
821 struct ivi_surface *surface;
823 wl_list_for_each(surface, &ivi->surfaces, link) {
825 weston_desktop_surface_get_app_id(surface->dsurface);
826 if (app_id == NULL) {
827 weston_log("WARNING app_is is null, unable to advertise\n");
830 agl_shell_desktop_send_application(resource, app_id);
835 client_exec(const char *command, int fd)
840 /* Don't give the child our signal mask */
842 sigprocmask(SIG_UNBLOCK, &sig, NULL);
844 /* Launch clients as the user; don't give them the wrong euid */
845 if (seteuid(getuid()) == -1) {
846 weston_log("seteuid failed: %s\n", strerror(errno));
850 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
851 * clobbering fd, as we'll exit/exec either way.
855 weston_log("dup failed: %s\n", strerror(errno));
859 snprintf(s, sizeof s, "%d", fd);
860 setenv("WAYLAND_SOCKET", s, 1);
862 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
863 weston_log("executing '%s' failed: %s", command, strerror(errno));
866 static struct wl_client *
867 launch_shell_client(struct ivi_compositor *ivi, const char *command)
869 struct wl_client *client;
873 weston_log("launching' %s'\n", command);
875 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
876 weston_log("socketpair failed while launching '%s': %s\n",
877 command, strerror(errno));
885 weston_log("fork failed while launching '%s': %s\n",
886 command, strerror(errno));
891 client_exec(command, sock[1]);
896 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
899 weston_log("Failed to create wayland client for '%s'",
908 ivi_launch_shell_client(struct ivi_compositor *ivi)
910 struct weston_config_section *section;
911 char *command = NULL;
913 section = weston_config_get_section(ivi->config, "shell-client",
916 weston_config_section_get_string(section, "command",
922 ivi->shell_client.client = launch_shell_client(ivi, command);
923 if (!ivi->shell_client.client)
930 destroy_black_view(struct wl_listener *listener, void *data)
932 struct fullscreen_view *fs =
933 wl_container_of(listener, fs, fs_destroy);
937 wl_list_remove(&fs->fs_destroy.link);
944 create_black_surface_view(struct ivi_output *output)
946 struct weston_surface *surface = NULL;
947 struct weston_view *view;
948 struct ivi_compositor *ivi = output->ivi;
949 struct weston_compositor *wc= ivi->compositor;
950 struct weston_output *woutput = output->output;
955 surface = weston_surface_create(wc);
958 view = weston_view_create(surface);
960 weston_surface_destroy(surface);
964 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
965 weston_surface_set_size(surface, woutput->width, woutput->height);
966 weston_view_set_position(view, woutput->x, woutput->y);
968 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
969 if (!output->fullscreen_view.fs) {
970 weston_surface_destroy(surface);
973 output->fullscreen_view.fs->view = view;
975 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
976 wl_signal_add(&woutput->destroy_signal,
977 &output->fullscreen_view.fs_destroy);
981 remove_black_surface(struct ivi_output *output)
983 struct weston_view *view;
986 !output->fullscreen_view.fs &&
987 !output->fullscreen_view.fs->view) {
988 weston_log("Output %s doesn't have a surface installed!\n", output->name);
992 view = output->fullscreen_view.fs->view;
993 assert(view->is_mapped == true ||
994 view->surface->is_mapped == true);
996 view->is_mapped = false;
997 view->surface->is_mapped = false;
999 weston_layer_entry_remove(&view->layer_link);
1000 weston_view_update_transform(view);
1002 weston_view_damage_below(view);
1006 insert_black_surface(struct ivi_output *output)
1008 struct weston_view *view;
1011 !output->fullscreen_view.fs &&
1012 !output->fullscreen_view.fs->view) || !output->output) {
1013 weston_log("Output %s doesn't have a surface installed!\n", output->name);
1017 view = output->fullscreen_view.fs->view;
1018 if (view->is_mapped || view->surface->is_mapped)
1021 weston_layer_entry_remove(&view->layer_link);
1022 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
1025 view->is_mapped = true;
1026 view->surface->is_mapped = true;
1028 weston_view_update_transform(view);
1029 weston_view_damage_below(view);
1033 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
1035 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1036 struct ivi_output *output;
1037 struct ivi_surface *surface, *tmp;
1039 /* Init already finished. Do nothing */
1040 if (ivi->shell_client.ready)
1043 ivi->shell_client.ready = true;
1045 wl_list_for_each(output, &ivi->outputs, link) {
1046 if (output->background)
1047 remove_black_surface(output);
1048 ivi_layout_init(ivi, output);
1051 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
1052 wl_list_remove(&surface->link);
1053 wl_list_init(&surface->link);
1054 ivi_check_pending_desktop_surface(surface);
1055 surface->checked_pending = true;
1060 shell_set_background(struct wl_client *client,
1061 struct wl_resource *shell_res,
1062 struct wl_resource *surface_res,
1063 struct wl_resource *output_res)
1065 struct weston_head *head = weston_head_from_resource(output_res);
1066 struct weston_output *woutput = weston_head_get_output(head);
1067 struct ivi_output *output = to_ivi_output(woutput);
1068 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1069 struct weston_desktop_surface *dsurface;
1070 struct ivi_surface *surface;
1072 dsurface = weston_surface_get_desktop_surface(wsurface);
1074 wl_resource_post_error(shell_res,
1075 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1076 "surface must be a desktop surface");
1080 surface = weston_desktop_surface_get_user_data(dsurface);
1081 if (surface->role != IVI_SURFACE_ROLE_NONE) {
1082 wl_resource_post_error(shell_res,
1083 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1084 "surface already has another ivi role");
1088 if (output->background) {
1089 wl_resource_post_error(shell_res,
1090 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1091 "output already has background");
1095 surface->checked_pending = true;
1096 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
1097 surface->bg.output = output;
1098 wl_list_remove(&surface->link);
1099 wl_list_init(&surface->link);
1101 output->background = surface;
1103 weston_desktop_surface_set_maximized(dsurface, true);
1104 weston_desktop_surface_set_size(dsurface,
1105 output->output->width,
1106 output->output->height);
1110 shell_set_panel(struct wl_client *client,
1111 struct wl_resource *shell_res,
1112 struct wl_resource *surface_res,
1113 struct wl_resource *output_res,
1116 struct weston_head *head = weston_head_from_resource(output_res);
1117 struct weston_output *woutput = weston_head_get_output(head);
1118 struct ivi_output *output = to_ivi_output(woutput);
1119 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1120 struct weston_desktop_surface *dsurface;
1121 struct ivi_surface *surface;
1122 struct ivi_surface **member;
1123 int32_t width = 0, height = 0;
1125 dsurface = weston_surface_get_desktop_surface(wsurface);
1127 wl_resource_post_error(shell_res,
1128 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1129 "surface must be a desktop surface");
1133 surface = weston_desktop_surface_get_user_data(dsurface);
1134 if (surface->role != IVI_SURFACE_ROLE_NONE) {
1135 wl_resource_post_error(shell_res,
1136 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1137 "surface already has another ivi role");
1142 case AGL_SHELL_EDGE_TOP:
1143 member = &output->top;
1145 case AGL_SHELL_EDGE_BOTTOM:
1146 member = &output->bottom;
1148 case AGL_SHELL_EDGE_LEFT:
1149 member = &output->left;
1151 case AGL_SHELL_EDGE_RIGHT:
1152 member = &output->right;
1155 wl_resource_post_error(shell_res,
1156 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1157 "invalid edge for panel");
1162 wl_resource_post_error(shell_res,
1163 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1164 "output already has panel on this edge");
1168 surface->checked_pending = true;
1169 surface->role = IVI_SURFACE_ROLE_PANEL;
1170 surface->panel.output = output;
1171 surface->panel.edge = edge;
1172 wl_list_remove(&surface->link);
1173 wl_list_init(&surface->link);
1177 switch (surface->panel.edge) {
1178 case AGL_SHELL_EDGE_TOP:
1179 case AGL_SHELL_EDGE_BOTTOM:
1180 width = woutput->width;
1182 case AGL_SHELL_EDGE_LEFT:
1183 case AGL_SHELL_EDGE_RIGHT:
1184 height = woutput->height;
1188 weston_desktop_surface_set_size(dsurface, width, height);
1192 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
1193 const char *data, uint32_t app_state)
1195 struct desktop_client *dclient;
1197 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1198 struct ivi_policy *policy = ivi->policy;
1200 /* FIXME: should queue it here and see when binding agl-shell-desktop
1201 * if there are any to be sent */
1208 if (policy && policy->api.surface_advertise_state_change &&
1209 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
1213 app_role = surf->role;
1214 if (app_role == IVI_SURFACE_ROLE_POPUP)
1215 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
1217 wl_list_for_each(dclient, &ivi->desktop_clients, link)
1218 agl_shell_desktop_send_state_app(dclient->resource, app_id,
1219 data, app_state, app_role);
1223 shell_activate_app(struct wl_client *client,
1224 struct wl_resource *shell_res,
1226 struct wl_resource *output_res)
1228 struct weston_head *head = weston_head_from_resource(output_res);
1229 struct weston_output *woutput = weston_head_get_output(head);
1230 struct ivi_output *output = to_ivi_output(woutput);
1232 ivi_layout_activate(output, app_id);
1236 shell_desktop_activate_app(struct wl_client *client,
1237 struct wl_resource *shell_res,
1238 const char *app_id, const char *data,
1239 struct wl_resource *output_res)
1241 struct weston_head *head = weston_head_from_resource(output_res);
1242 struct weston_output *woutput = weston_head_get_output(head);
1243 struct ivi_output *output = to_ivi_output(woutput);
1245 ivi_layout_activate(output, app_id);
1246 shell_advertise_app_state(output->ivi, app_id,
1247 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
1251 shell_deactivate_app(struct wl_client *client,
1252 struct wl_resource *shell_res,
1255 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
1256 struct ivi_compositor *ivi = dclient->ivi;
1258 ivi_layout_deactivate(ivi, app_id);
1259 shell_advertise_app_state(ivi, app_id,
1260 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
1263 static const struct agl_shell_interface agl_shell_implementation = {
1264 .ready = shell_ready,
1265 .set_background = shell_set_background,
1266 .set_panel = shell_set_panel,
1267 .activate_app = shell_activate_app,
1271 shell_desktop_set_app_property(struct wl_client *client,
1272 struct wl_resource *shell_res,
1273 const char *app_id, uint32_t role,
1274 int x, int y, int bx, int by,
1275 int width, int height,
1276 struct wl_resource *output_res)
1278 struct weston_head *head = weston_head_from_resource(output_res);
1279 struct weston_output *woutput = weston_head_get_output(head);
1280 struct ivi_output *output = to_ivi_output(woutput);
1283 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
1284 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
1285 width, height, app_id);
1287 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
1288 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
1290 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
1291 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
1292 ivi_set_pending_desktop_surface_split(output, app_id, role);
1294 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
1295 ivi_set_pending_desktop_surface_remote(output, app_id);
1303 ivi_compositor_destroy_pending_surfaces(struct ivi_compositor *ivi)
1305 struct pending_popup *p_popup, *next_p_popup;
1306 struct pending_split *split_surf, *next_split_surf;
1307 struct pending_fullscreen *fs_surf, *next_fs_surf;
1308 struct pending_remote *remote_surf, *next_remote_surf;
1310 wl_list_for_each_safe(p_popup, next_p_popup,
1311 &ivi->popup_pending_apps, link)
1312 ivi_remove_pending_desktop_surface_popup(p_popup);
1314 wl_list_for_each_safe(split_surf, next_split_surf,
1315 &ivi->split_pending_apps, link)
1316 ivi_remove_pending_desktop_surface_split(split_surf);
1318 wl_list_for_each_safe(fs_surf, next_fs_surf,
1319 &ivi->fullscreen_pending_apps, link)
1320 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
1322 wl_list_for_each_safe(remote_surf, next_remote_surf,
1323 &ivi->remote_pending_apps, link)
1324 ivi_remove_pending_desktop_surface_remote(remote_surf);
1328 shell_desktop_set_app_property_mode(struct wl_client *client,
1329 struct wl_resource *shell_res, uint32_t perm)
1331 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
1333 dclient->ivi->keep_pending_surfaces = true;
1335 dclient->ivi->keep_pending_surfaces = false;
1336 /* remove any previous pending surfaces */
1337 ivi_compositor_destroy_pending_surfaces(dclient->ivi);
1341 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
1342 .activate_app = shell_desktop_activate_app,
1343 .set_app_property = shell_desktop_set_app_property,
1344 .deactivate_app = shell_deactivate_app,
1345 .set_app_property_mode = shell_desktop_set_app_property_mode,
1349 unbind_agl_shell(struct wl_resource *resource)
1351 struct ivi_compositor *ivi;
1352 struct ivi_output *output;
1353 struct ivi_surface *surf, *surf_tmp;
1355 ivi = wl_resource_get_user_data(resource);
1356 wl_list_for_each(output, &ivi->outputs, link) {
1357 /* reset the active surf if there's one present */
1358 if (output->active) {
1359 output->active->view->is_mapped = false;
1360 output->active->view->surface->is_mapped = false;
1362 weston_layer_entry_remove(&output->active->view->layer_link);
1363 output->active = NULL;
1366 insert_black_surface(output);
1369 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
1370 wl_list_remove(&surf->link);
1371 wl_list_init(&surf->link);
1374 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
1375 wl_list_remove(&surf->link);
1376 wl_list_init(&surf->link);
1379 wl_list_init(&ivi->surfaces);
1380 wl_list_init(&ivi->pending_surfaces);
1382 ivi->shell_client.ready = false;
1383 ivi->shell_client.resource = NULL;
1384 ivi->shell_client.client = NULL;
1388 bind_agl_shell(struct wl_client *client,
1389 void *data, uint32_t version, uint32_t id)
1391 struct ivi_compositor *ivi = data;
1392 struct wl_resource *resource;
1393 struct ivi_policy *policy;
1396 policy = ivi->policy;
1397 interface = (void *) &agl_shell_interface;
1398 if (policy && policy->api.shell_bind_interface &&
1399 !policy->api.shell_bind_interface(client, interface)) {
1400 wl_client_post_implementation_error(client,
1401 "client not authorized to use agl_shell");
1405 resource = wl_resource_create(client, &agl_shell_interface,
1408 wl_client_post_no_memory(client);
1412 if (ivi->shell_client.resource) {
1413 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1414 "agl_shell has already been bound");
1418 wl_resource_set_implementation(resource, &agl_shell_implementation,
1419 ivi, unbind_agl_shell);
1420 ivi->shell_client.resource = resource;
1424 unbind_agl_shell_desktop(struct wl_resource *resource)
1426 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1428 wl_list_remove(&dclient->link);
1433 bind_agl_shell_desktop(struct wl_client *client,
1434 void *data, uint32_t version, uint32_t id)
1436 struct ivi_compositor *ivi = data;
1437 struct wl_resource *resource;
1438 struct ivi_policy *policy;
1439 struct desktop_client *dclient;
1442 policy = ivi->policy;
1443 interface = (void *) &agl_shell_desktop_interface;
1444 if (policy && policy->api.shell_bind_interface &&
1445 !policy->api.shell_bind_interface(client, interface)) {
1446 wl_client_post_implementation_error(client,
1447 "client not authorized to use agl_shell_desktop");
1451 dclient = zalloc(sizeof(*dclient));
1453 wl_client_post_no_memory(client);
1457 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1461 wl_client_post_no_memory(client);
1465 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1466 dclient, unbind_agl_shell_desktop);
1468 dclient->resource = resource;
1469 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1471 /* advertise xdg surfaces */
1472 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1476 ivi_shell_create_global(struct ivi_compositor *ivi)
1478 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1479 &agl_shell_interface, 1,
1480 ivi, bind_agl_shell);
1481 if (!ivi->agl_shell) {
1482 weston_log("Failed to create wayland global.\n");
1486 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1487 &agl_shell_desktop_interface, 2,
1488 ivi, bind_agl_shell_desktop);
1489 if (!ivi->agl_shell_desktop) {
1490 weston_log("Failed to create wayland global (agl_shell_desktop).\n");