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);
641 role_pending_list = &ivi->popup_pending_apps;
642 wl_list_for_each(p_popup, role_pending_list, link) {
643 if (!strcmp(app_id, p_popup->app_id)) {
644 *role = IVI_SURFACE_ROLE_POPUP;
649 role_pending_list = &ivi->split_pending_apps;
650 wl_list_for_each(p_split, role_pending_list, link) {
651 if (!strcmp(app_id, p_split->app_id)) {
652 *role = IVI_SURFACE_ROLE_SPLIT_V;
657 role_pending_list = &ivi->fullscreen_pending_apps;
658 wl_list_for_each(p_fullscreen, role_pending_list, link) {
659 if (!strcmp(app_id, p_fullscreen->app_id)) {
660 *role = IVI_SURFACE_ROLE_FULLSCREEN;
665 role_pending_list = &ivi->remote_pending_apps;
666 wl_list_for_each(p_remote, role_pending_list, link) {
667 if (!strcmp(app_id, p_remote->app_id)) {
668 *role = IVI_SURFACE_ROLE_REMOTE;
673 /* else, we are a regular desktop surface */
674 *role = IVI_SURFACE_ROLE_DESKTOP;
679 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
683 ret = ivi_check_pending_desktop_surface_popup(surface);
685 ivi_set_desktop_surface_popup(surface);
686 ivi_layout_popup_committed(surface);
690 ret = ivi_check_pending_desktop_surface_split(surface);
692 ivi_set_desktop_surface_split(surface);
693 ivi_layout_split_committed(surface);
697 ret = ivi_check_pending_desktop_surface_fullscreen(surface);
699 ivi_set_desktop_surface_fullscreen(surface);
700 ivi_layout_fullscreen_committed(surface);
704 ret = ivi_check_pending_desktop_surface_remote(surface);
706 ivi_set_desktop_surface_remote(surface);
707 ivi_layout_desktop_committed(surface);
711 /* if we end up here means we have a regular desktop app and
712 * try to activate it */
713 ivi_set_desktop_surface(surface);
714 ivi_layout_desktop_committed(surface);
718 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
720 struct ivi_output *out;
722 wl_list_for_each(out, &ivi->outputs, link) {
723 create_black_surface_view(out);
724 insert_black_surface(out);
729 ivi_shell_init(struct ivi_compositor *ivi)
731 weston_layer_init(&ivi->hidden, ivi->compositor);
732 weston_layer_init(&ivi->background, ivi->compositor);
733 weston_layer_init(&ivi->normal, ivi->compositor);
734 weston_layer_init(&ivi->panel, ivi->compositor);
735 weston_layer_init(&ivi->popup, ivi->compositor);
736 weston_layer_init(&ivi->fullscreen, ivi->compositor);
738 weston_layer_set_position(&ivi->hidden,
739 WESTON_LAYER_POSITION_HIDDEN);
740 weston_layer_set_position(&ivi->background,
741 WESTON_LAYER_POSITION_BACKGROUND);
742 weston_layer_set_position(&ivi->normal,
743 WESTON_LAYER_POSITION_NORMAL);
744 weston_layer_set_position(&ivi->panel,
745 WESTON_LAYER_POSITION_UI);
746 weston_layer_set_position(&ivi->popup,
747 WESTON_LAYER_POSITION_TOP_UI);
748 weston_layer_set_position(&ivi->fullscreen,
749 WESTON_LAYER_POSITION_FULLSCREEN);
756 ivi_surf_destroy(struct ivi_surface *surf)
758 struct weston_surface *wsurface = surf->view->surface;
760 if (weston_surface_is_mapped(wsurface)) {
761 weston_desktop_surface_unlink_view(surf->view);
762 weston_view_destroy(surf->view);
765 wl_list_remove(&surf->link);
770 ivi_shell_destroy_views_on_layer(struct weston_layer *layer)
772 struct weston_view *view, *view_next;
774 wl_list_for_each_safe(view, view_next, &layer->view_list.link, layer_link.link) {
775 struct ivi_surface *ivi_surf =
776 get_ivi_shell_surface(view->surface);
778 ivi_surf_destroy(ivi_surf);
783 ivi_shell_finalize(struct ivi_compositor *ivi)
785 struct ivi_output *output;
787 ivi_shell_destroy_views_on_layer(&ivi->hidden);
788 weston_layer_fini(&ivi->hidden);
790 ivi_shell_destroy_views_on_layer(&ivi->background);
791 weston_layer_fini(&ivi->background);
793 ivi_shell_destroy_views_on_layer(&ivi->normal);
794 weston_layer_fini(&ivi->normal);
796 ivi_shell_destroy_views_on_layer(&ivi->panel);
797 weston_layer_fini(&ivi->panel);
799 ivi_shell_destroy_views_on_layer(&ivi->popup);
800 weston_layer_fini(&ivi->popup);
802 wl_list_for_each(output, &ivi->outputs, link) {
803 if (output->fullscreen_view.fs->view) {
804 weston_surface_destroy(output->fullscreen_view.fs->view->surface);
805 output->fullscreen_view.fs->view = NULL;
808 weston_layer_fini(&ivi->fullscreen);
812 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
814 struct ivi_surface *surface;
816 wl_list_for_each(surface, &ivi->surfaces, link) {
818 weston_desktop_surface_get_app_id(surface->dsurface);
819 if (app_id == NULL) {
820 weston_log("WARNING app_is is null, unable to advertise\n");
823 agl_shell_desktop_send_application(resource, app_id);
828 client_exec(const char *command, int fd)
833 /* Don't give the child our signal mask */
835 sigprocmask(SIG_UNBLOCK, &sig, NULL);
837 /* Launch clients as the user; don't give them the wrong euid */
838 if (seteuid(getuid()) == -1) {
839 weston_log("seteuid failed: %s\n", strerror(errno));
843 /* Duplicate fd to unset the CLOEXEC flag. We don't need to worry about
844 * clobbering fd, as we'll exit/exec either way.
848 weston_log("dup failed: %s\n", strerror(errno));
852 snprintf(s, sizeof s, "%d", fd);
853 setenv("WAYLAND_SOCKET", s, 1);
855 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
856 weston_log("executing '%s' failed: %s", command, strerror(errno));
859 static struct wl_client *
860 launch_shell_client(struct ivi_compositor *ivi, const char *command)
862 struct wl_client *client;
866 weston_log("launching' %s'\n", command);
868 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sock) < 0) {
869 weston_log("socketpair failed while launching '%s': %s\n",
870 command, strerror(errno));
878 weston_log("fork failed while launching '%s': %s\n",
879 command, strerror(errno));
884 client_exec(command, sock[1]);
889 client = wl_client_create(ivi->compositor->wl_display, sock[0]);
892 weston_log("Failed to create wayland client for '%s'",
901 ivi_launch_shell_client(struct ivi_compositor *ivi)
903 struct weston_config_section *section;
904 char *command = NULL;
906 section = weston_config_get_section(ivi->config, "shell-client",
909 weston_config_section_get_string(section, "command",
915 ivi->shell_client.client = launch_shell_client(ivi, command);
916 if (!ivi->shell_client.client)
923 destroy_black_view(struct wl_listener *listener, void *data)
925 struct fullscreen_view *fs =
926 wl_container_of(listener, fs, fs_destroy);
930 wl_list_remove(&fs->fs_destroy.link);
937 create_black_surface_view(struct ivi_output *output)
939 struct weston_surface *surface = NULL;
940 struct weston_view *view;
941 struct ivi_compositor *ivi = output->ivi;
942 struct weston_compositor *wc= ivi->compositor;
943 struct weston_output *woutput = output->output;
948 surface = weston_surface_create(wc);
951 view = weston_view_create(surface);
953 weston_surface_destroy(surface);
957 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
958 weston_surface_set_size(surface, woutput->width, woutput->height);
959 weston_view_set_position(view, woutput->x, woutput->y);
961 output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
962 if (!output->fullscreen_view.fs) {
963 weston_surface_destroy(surface);
966 output->fullscreen_view.fs->view = view;
968 output->fullscreen_view.fs_destroy.notify = destroy_black_view;
969 wl_signal_add(&woutput->destroy_signal,
970 &output->fullscreen_view.fs_destroy);
974 remove_black_surface(struct ivi_output *output)
976 struct weston_view *view;
979 !output->fullscreen_view.fs &&
980 !output->fullscreen_view.fs->view) {
981 weston_log("Output %s doesn't have a surface installed!\n", output->name);
985 view = output->fullscreen_view.fs->view;
986 assert(view->is_mapped == true ||
987 view->surface->is_mapped == true);
989 view->is_mapped = false;
990 view->surface->is_mapped = false;
992 weston_layer_entry_remove(&view->layer_link);
993 weston_view_update_transform(view);
995 weston_view_damage_below(view);
999 insert_black_surface(struct ivi_output *output)
1001 struct weston_view *view;
1004 !output->fullscreen_view.fs &&
1005 !output->fullscreen_view.fs->view) || !output->output) {
1006 weston_log("Output %s doesn't have a surface installed!\n", output->name);
1010 view = output->fullscreen_view.fs->view;
1011 if (view->is_mapped || view->surface->is_mapped)
1014 weston_layer_entry_remove(&view->layer_link);
1015 weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
1018 view->is_mapped = true;
1019 view->surface->is_mapped = true;
1021 weston_view_update_transform(view);
1022 weston_view_damage_below(view);
1026 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
1028 struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1029 struct ivi_output *output;
1030 struct ivi_surface *surface, *tmp;
1032 /* Init already finished. Do nothing */
1033 if (ivi->shell_client.ready)
1036 ivi->shell_client.ready = true;
1038 wl_list_for_each(output, &ivi->outputs, link) {
1039 if (output->background)
1040 remove_black_surface(output);
1041 ivi_layout_init(ivi, output);
1044 wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
1045 wl_list_remove(&surface->link);
1046 wl_list_init(&surface->link);
1047 ivi_check_pending_desktop_surface(surface);
1048 surface->checked_pending = true;
1053 shell_set_background(struct wl_client *client,
1054 struct wl_resource *shell_res,
1055 struct wl_resource *surface_res,
1056 struct wl_resource *output_res)
1058 struct weston_head *head = weston_head_from_resource(output_res);
1059 struct weston_output *woutput = weston_head_get_output(head);
1060 struct ivi_output *output = to_ivi_output(woutput);
1061 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1062 struct weston_desktop_surface *dsurface;
1063 struct ivi_surface *surface;
1065 dsurface = weston_surface_get_desktop_surface(wsurface);
1067 wl_resource_post_error(shell_res,
1068 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1069 "surface must be a desktop surface");
1073 surface = weston_desktop_surface_get_user_data(dsurface);
1074 if (surface->role != IVI_SURFACE_ROLE_NONE) {
1075 wl_resource_post_error(shell_res,
1076 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1077 "surface already has another ivi role");
1081 if (output->background) {
1082 wl_resource_post_error(shell_res,
1083 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1084 "output already has background");
1088 surface->checked_pending = true;
1089 surface->role = IVI_SURFACE_ROLE_BACKGROUND;
1090 surface->bg.output = output;
1091 wl_list_remove(&surface->link);
1092 wl_list_init(&surface->link);
1094 output->background = surface;
1096 weston_desktop_surface_set_maximized(dsurface, true);
1097 weston_desktop_surface_set_size(dsurface,
1098 output->output->width,
1099 output->output->height);
1103 shell_set_panel(struct wl_client *client,
1104 struct wl_resource *shell_res,
1105 struct wl_resource *surface_res,
1106 struct wl_resource *output_res,
1109 struct weston_head *head = weston_head_from_resource(output_res);
1110 struct weston_output *woutput = weston_head_get_output(head);
1111 struct ivi_output *output = to_ivi_output(woutput);
1112 struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1113 struct weston_desktop_surface *dsurface;
1114 struct ivi_surface *surface;
1115 struct ivi_surface **member;
1116 int32_t width = 0, height = 0;
1118 dsurface = weston_surface_get_desktop_surface(wsurface);
1120 wl_resource_post_error(shell_res,
1121 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1122 "surface must be a desktop surface");
1126 surface = weston_desktop_surface_get_user_data(dsurface);
1127 if (surface->role != IVI_SURFACE_ROLE_NONE) {
1128 wl_resource_post_error(shell_res,
1129 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1130 "surface already has another ivi role");
1135 case AGL_SHELL_EDGE_TOP:
1136 member = &output->top;
1138 case AGL_SHELL_EDGE_BOTTOM:
1139 member = &output->bottom;
1141 case AGL_SHELL_EDGE_LEFT:
1142 member = &output->left;
1144 case AGL_SHELL_EDGE_RIGHT:
1145 member = &output->right;
1148 wl_resource_post_error(shell_res,
1149 AGL_SHELL_ERROR_INVALID_ARGUMENT,
1150 "invalid edge for panel");
1155 wl_resource_post_error(shell_res,
1156 AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1157 "output already has panel on this edge");
1161 surface->checked_pending = true;
1162 surface->role = IVI_SURFACE_ROLE_PANEL;
1163 surface->panel.output = output;
1164 surface->panel.edge = edge;
1165 wl_list_remove(&surface->link);
1166 wl_list_init(&surface->link);
1170 switch (surface->panel.edge) {
1171 case AGL_SHELL_EDGE_TOP:
1172 case AGL_SHELL_EDGE_BOTTOM:
1173 width = woutput->width;
1175 case AGL_SHELL_EDGE_LEFT:
1176 case AGL_SHELL_EDGE_RIGHT:
1177 height = woutput->height;
1181 weston_desktop_surface_set_size(dsurface, width, height);
1185 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
1186 const char *data, uint32_t app_state)
1188 struct desktop_client *dclient;
1190 struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1191 struct ivi_policy *policy = ivi->policy;
1193 /* FIXME: should queue it here and see when binding agl-shell-desktop
1194 * if there are any to be sent */
1201 if (policy && policy->api.surface_advertise_state_change &&
1202 !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
1206 app_role = surf->role;
1207 if (app_role == IVI_SURFACE_ROLE_POPUP)
1208 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
1210 wl_list_for_each(dclient, &ivi->desktop_clients, link)
1211 agl_shell_desktop_send_state_app(dclient->resource, app_id,
1212 data, app_state, app_role);
1216 shell_activate_app(struct wl_client *client,
1217 struct wl_resource *shell_res,
1219 struct wl_resource *output_res)
1221 struct weston_head *head = weston_head_from_resource(output_res);
1222 struct weston_output *woutput = weston_head_get_output(head);
1223 struct ivi_output *output = to_ivi_output(woutput);
1225 ivi_layout_activate(output, app_id);
1229 shell_desktop_activate_app(struct wl_client *client,
1230 struct wl_resource *shell_res,
1231 const char *app_id, const char *data,
1232 struct wl_resource *output_res)
1234 struct weston_head *head = weston_head_from_resource(output_res);
1235 struct weston_output *woutput = weston_head_get_output(head);
1236 struct ivi_output *output = to_ivi_output(woutput);
1238 ivi_layout_activate(output, app_id);
1239 shell_advertise_app_state(output->ivi, app_id,
1240 data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
1244 shell_deactivate_app(struct wl_client *client,
1245 struct wl_resource *shell_res,
1248 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
1249 struct ivi_compositor *ivi = dclient->ivi;
1251 ivi_layout_deactivate(ivi, app_id);
1252 shell_advertise_app_state(ivi, app_id,
1253 NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
1256 static const struct agl_shell_interface agl_shell_implementation = {
1257 .ready = shell_ready,
1258 .set_background = shell_set_background,
1259 .set_panel = shell_set_panel,
1260 .activate_app = shell_activate_app,
1264 shell_desktop_set_app_property(struct wl_client *client,
1265 struct wl_resource *shell_res,
1266 const char *app_id, uint32_t role,
1267 int x, int y, int bx, int by,
1268 int width, int height,
1269 struct wl_resource *output_res)
1271 struct weston_head *head = weston_head_from_resource(output_res);
1272 struct weston_output *woutput = weston_head_get_output(head);
1273 struct ivi_output *output = to_ivi_output(woutput);
1276 case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
1277 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
1278 width, height, app_id);
1280 case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
1281 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
1283 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
1284 case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
1285 ivi_set_pending_desktop_surface_split(output, app_id, role);
1287 case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
1288 ivi_set_pending_desktop_surface_remote(output, app_id);
1296 ivi_compositor_destroy_pending_surfaces(struct ivi_compositor *ivi)
1298 struct pending_popup *p_popup, *next_p_popup;
1299 struct pending_split *split_surf, *next_split_surf;
1300 struct pending_fullscreen *fs_surf, *next_fs_surf;
1301 struct pending_remote *remote_surf, *next_remote_surf;
1303 wl_list_for_each_safe(p_popup, next_p_popup,
1304 &ivi->popup_pending_apps, link)
1305 ivi_remove_pending_desktop_surface_popup(p_popup);
1307 wl_list_for_each_safe(split_surf, next_split_surf,
1308 &ivi->split_pending_apps, link)
1309 ivi_remove_pending_desktop_surface_split(split_surf);
1311 wl_list_for_each_safe(fs_surf, next_fs_surf,
1312 &ivi->fullscreen_pending_apps, link)
1313 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
1315 wl_list_for_each_safe(remote_surf, next_remote_surf,
1316 &ivi->remote_pending_apps, link)
1317 ivi_remove_pending_desktop_surface_remote(remote_surf);
1321 shell_desktop_set_app_property_mode(struct wl_client *client,
1322 struct wl_resource *shell_res, uint32_t perm)
1324 struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
1326 dclient->ivi->keep_pending_surfaces = true;
1328 dclient->ivi->keep_pending_surfaces = false;
1329 /* remove any previous pending surfaces */
1330 ivi_compositor_destroy_pending_surfaces(dclient->ivi);
1334 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
1335 .activate_app = shell_desktop_activate_app,
1336 .set_app_property = shell_desktop_set_app_property,
1337 .deactivate_app = shell_deactivate_app,
1338 .set_app_property_mode = shell_desktop_set_app_property_mode,
1342 unbind_agl_shell(struct wl_resource *resource)
1344 struct ivi_compositor *ivi;
1345 struct ivi_output *output;
1346 struct ivi_surface *surf, *surf_tmp;
1348 ivi = wl_resource_get_user_data(resource);
1349 wl_list_for_each(output, &ivi->outputs, link) {
1350 /* reset the active surf if there's one present */
1351 if (output->active) {
1352 output->active->view->is_mapped = false;
1353 output->active->view->surface->is_mapped = false;
1355 weston_layer_entry_remove(&output->active->view->layer_link);
1356 output->active = NULL;
1359 insert_black_surface(output);
1362 wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
1363 wl_list_remove(&surf->link);
1364 wl_list_init(&surf->link);
1367 wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
1368 wl_list_remove(&surf->link);
1369 wl_list_init(&surf->link);
1372 wl_list_init(&ivi->surfaces);
1373 wl_list_init(&ivi->pending_surfaces);
1375 ivi->shell_client.ready = false;
1376 ivi->shell_client.resource = NULL;
1377 ivi->shell_client.client = NULL;
1381 bind_agl_shell(struct wl_client *client,
1382 void *data, uint32_t version, uint32_t id)
1384 struct ivi_compositor *ivi = data;
1385 struct wl_resource *resource;
1386 struct ivi_policy *policy;
1389 policy = ivi->policy;
1390 interface = (void *) &agl_shell_interface;
1391 if (policy && policy->api.shell_bind_interface &&
1392 !policy->api.shell_bind_interface(client, interface)) {
1393 wl_client_post_implementation_error(client,
1394 "client not authorized to use agl_shell");
1398 resource = wl_resource_create(client, &agl_shell_interface,
1401 wl_client_post_no_memory(client);
1405 if (ivi->shell_client.resource) {
1406 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1407 "agl_shell has already been bound");
1411 wl_resource_set_implementation(resource, &agl_shell_implementation,
1412 ivi, unbind_agl_shell);
1413 ivi->shell_client.resource = resource;
1417 unbind_agl_shell_desktop(struct wl_resource *resource)
1419 struct desktop_client *dclient = wl_resource_get_user_data(resource);
1421 wl_list_remove(&dclient->link);
1426 bind_agl_shell_desktop(struct wl_client *client,
1427 void *data, uint32_t version, uint32_t id)
1429 struct ivi_compositor *ivi = data;
1430 struct wl_resource *resource;
1431 struct ivi_policy *policy;
1432 struct desktop_client *dclient;
1435 policy = ivi->policy;
1436 interface = (void *) &agl_shell_desktop_interface;
1437 if (policy && policy->api.shell_bind_interface &&
1438 !policy->api.shell_bind_interface(client, interface)) {
1439 wl_client_post_implementation_error(client,
1440 "client not authorized to use agl_shell_desktop");
1444 dclient = zalloc(sizeof(*dclient));
1446 wl_client_post_no_memory(client);
1450 resource = wl_resource_create(client, &agl_shell_desktop_interface,
1454 wl_client_post_no_memory(client);
1458 wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
1459 dclient, unbind_agl_shell_desktop);
1461 dclient->resource = resource;
1462 wl_list_insert(&ivi->desktop_clients, &dclient->link);
1464 /* advertise xdg surfaces */
1465 ivi_shell_advertise_xdg_surfaces(ivi, resource);
1469 ivi_shell_create_global(struct ivi_compositor *ivi)
1471 ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
1472 &agl_shell_interface, 1,
1473 ivi, bind_agl_shell);
1474 if (!ivi->agl_shell) {
1475 weston_log("Failed to create wayland global.\n");
1479 ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
1480 &agl_shell_desktop_interface, 2,
1481 ivi, bind_agl_shell_desktop);
1482 if (!ivi->agl_shell_desktop) {
1483 weston_log("Failed to create wayland global (agl_shell_desktop).\n");