X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fxwayland.c;fp=src%2Fxwayland.c;h=8ac5edc105b5959be3b81e853d338d351ff8c11c;hb=8033c46081b93f19843d140e58b527af7abf7a4f;hp=0000000000000000000000000000000000000000;hpb=ffdbb335ee72a5b5cba198800c5537b89d7755a0;p=src%2Fagl-compositor.git diff --git a/src/xwayland.c b/src/xwayland.c new file mode 100644 index 0000000..8ac5edc --- /dev/null +++ b/src/xwayland.c @@ -0,0 +1,224 @@ +/* + * Copyright © 2011 Intel Corporation + * Copyright © 2016 Giulio Camuffo + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "config.h" +#include "ivi-compositor.h" + +#include +#include +#include +#include + +#include +#include +#include +#include "shared/helpers.h" + +struct wet_xwayland { + struct ivi_compositor *ivi_compositor; + const struct weston_xwayland_api *api; + struct weston_xwayland *xwayland; + struct wl_event_source *sigusr1_source; + struct wl_client *client; + int wm_fd; + struct weston_process process; +}; + +static int +handle_sigusr1(int signal_number, void *data) +{ + struct wet_xwayland *wxw = data; + + /* We'd be safer if we actually had the struct + * signalfd_siginfo from the signalfd data and could verify + * this came from Xwayland.*/ + wxw->api->xserver_loaded(wxw->xwayland, wxw->client, wxw->wm_fd); + wl_event_source_remove(wxw->sigusr1_source); + + return 1; +} + +static pid_t +spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd) +{ + struct wet_xwayland *wxw = user_data; + pid_t pid; + char s[12], abstract_fd_str[12], unix_fd_str[12], wm_fd_str[12]; + int sv[2], wm[2], fd; + char *xserver = NULL; + struct weston_config *config = wxw->ivi_compositor->config; + struct weston_config_section *section; + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) { + weston_log("wl connection socketpair failed\n"); + return 1; + } + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wm) < 0) { + weston_log("X wm connection socketpair failed\n"); + return 1; + } + + pid = fork(); + switch (pid) { + case 0: + /* SOCK_CLOEXEC closes both ends, so we need to unset + * the flag on the client fd. */ + fd = dup(sv[1]); + if (fd < 0) + goto fail; + snprintf(s, sizeof s, "%d", fd); + setenv("WAYLAND_SOCKET", s, 1); + + fd = dup(abstract_fd); + if (fd < 0) + goto fail; + snprintf(abstract_fd_str, sizeof abstract_fd_str, "%d", fd); + fd = dup(unix_fd); + if (fd < 0) + goto fail; + snprintf(unix_fd_str, sizeof unix_fd_str, "%d", fd); + fd = dup(wm[1]); + if (fd < 0) + goto fail; + snprintf(wm_fd_str, sizeof wm_fd_str, "%d", fd); + + section = weston_config_get_section(config, + "xwayland", NULL, NULL); + weston_config_section_get_string(section, "path", + &xserver, XSERVER_PATH); + + /* Ignore SIGUSR1 in the child, which will make the X + * server send SIGUSR1 to the parent (weston) when + * it's done with initialization. During + * initialization the X server will round trip and + * block on the wayland compositor, so avoid making + * blocking requests (like xcb_connect_to_fd) until + * it's done with that. */ + signal(SIGUSR1, SIG_IGN); + + if (execl(xserver, + xserver, + display, + "-rootless", +#ifdef HAVE_XWAYLAND_LISTENFD + "-listenfd", abstract_fd_str, + "-listenfd", unix_fd_str, +#else + "-listen", abstract_fd_str, + "-listen", unix_fd_str, +#endif + "-wm", wm_fd_str, + "-terminate", + NULL) < 0) + weston_log("exec of '%s %s -rootless " +#ifdef HAVE_XWAYLAND_LISTENFD + "-listenfd %s -listenfd %s " +#else + "-listen %s -listen %s " +#endif + "-wm %s -terminate' failed: %s\n", + xserver, display, + abstract_fd_str, unix_fd_str, wm_fd_str, + strerror(errno)); + fail: + _exit(EXIT_FAILURE); + + default: + close(sv[1]); + wxw->client = wl_client_create(wxw->ivi_compositor->compositor->wl_display, sv[0]); + + close(wm[1]); + wxw->wm_fd = wm[0]; + + wxw->process.pid = pid; + wl_list_insert(&wxw->ivi_compositor->child_process_list, + &wxw->process.link); + break; + + case -1: + weston_log("Failed to fork to spawn xserver process\n"); + break; + } + + return pid; +} + +static void +xserver_cleanup(struct weston_process *process, int status) +{ + struct wet_xwayland *wxw = + container_of(process, struct wet_xwayland, process); + struct wl_event_loop *loop = + wl_display_get_event_loop(wxw->ivi_compositor->compositor->wl_display); + + wxw->api->xserver_exited(wxw->xwayland, status); + wxw->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1, + handle_sigusr1, wxw); + wxw->client = NULL; +} + +int +wet_load_xwayland(struct weston_compositor *comp) +{ + const struct weston_xwayland_api *api; + struct weston_xwayland *xwayland; + struct wet_xwayland *wxw; + struct wl_event_loop *loop; + struct ivi_compositor *ivi = to_ivi_compositor(comp); + + if (weston_compositor_load_xwayland(comp) < 0) + return -1; + + api = weston_xwayland_get_api(comp); + if (!api) { + weston_log("Failed to get the xwayland module API.\n"); + return -1; + } + + xwayland = api->get(comp); + if (!xwayland) { + weston_log("Failed to get the xwayland object.\n"); + return -1; + } + + wxw = zalloc(sizeof *wxw); + if (!wxw) + return -1; + + wxw->ivi_compositor = ivi; + wxw->api = api; + wxw->xwayland = xwayland; + wxw->process.cleanup = xserver_cleanup; + if (api->listen(xwayland, wxw, spawn_xserver) < 0) + return -1; + + loop = wl_display_get_event_loop(comp->wl_display); + wxw->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1, + handle_sigusr1, wxw); + + return 0; +}