diff options
-rw-r--r-- | meson.build | 7 | ||||
-rw-r--r-- | meson_options.txt | 14 | ||||
-rw-r--r-- | src/compositor.c | 53 | ||||
-rw-r--r-- | src/desktop.c | 43 | ||||
-rw-r--r-- | src/ivi-compositor.h | 8 | ||||
-rw-r--r-- | src/layout.c | 9 | ||||
-rw-r--r-- | src/xwayland.c | 224 |
7 files changed, 333 insertions, 25 deletions
diff --git a/meson.build b/meson.build index 4d846d2..2f8b11f 100644 --- a/meson.build +++ b/meson.build @@ -205,6 +205,13 @@ if deps_remoting.length() == depnames.length() message('Found remoting depends, enabling remoting') endif +if get_option('xwayland') + config_h.set('BUILD_XWAYLAND', '1') + + srcs_agl_compositor += 'src/xwayland.c' + config_h.set_quoted('XSERVER_PATH', get_option('xwayland-path')) +endif + dir_module_agl_compositor = join_paths(join_paths(prefix_path, get_option('libdir')), 'agl-compositor') libexec_compositor = shared_library( diff --git a/meson_options.txt b/meson_options.txt index 1e54773..7c0e103 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -5,10 +5,22 @@ option( value: 'allow-all', description: 'Default policy when no specific policy was set' ) - option( 'grpc-proxy', type: 'boolean', value: true, description: 'Build gRPC proxy which exposes some of the agl-shell protocol over a gRPC API' ) +option( + 'xwayland', + type: 'boolean', + value: false, + description: 'Build compositor with XWayland support. Disabled by default' +) + +option( + 'xwayland-path', + type: 'string', + value: '/usr/bin/Xwayland', + description: 'Xwayland: path to installed Xwayland binary' +) diff --git a/src/compositor.c b/src/compositor.c index c0a66c8..6cb822b 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1234,27 +1234,18 @@ load_modules(struct ivi_compositor *ivi, const char *modules, snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p); if (strstr(buffer, "xwayland.so")) { - weston_log("Xwayland plug-in not supported!\n"); - p = end; - while (*p == ',') - p++; - continue; - } - - if (strstr(buffer, "systemd-notify.so")) { + *xwayland = true; + } else if (strstr(buffer, "systemd-notify.so")) { weston_log("systemd-notify plug-in already loaded!\n"); - p = end; - while (*p == ',') - p++; - continue; - } + } else { + module_init = weston_load_module(buffer, "wet_module_init"); + if (!module_init) + return -1; - module_init = weston_load_module(buffer, "wet_module_init"); - if (!module_init) - return -1; + if (module_init(ivi->compositor, *argc, argv) < 0) + return -1; - if (module_init(ivi->compositor, *argc, argv) < 0) - return -1; + } p = end; while (*p == ',') @@ -1649,6 +1640,16 @@ copy_command_line(int argc, char * const argv[]) return str; } +#if !defined(BUILD_XWAYLAND) +int +wet_load_xwayland(struct weston_compositor *comp) +{ + weston_log("Attempted to load xwayland library but compositor " + "was *not* built with xwayland support!\n"); + return -1; +} +#endif + static void weston_log_setup_scopes(struct weston_log_context *log_ctx, struct weston_log_subscriber *subscriber, @@ -1677,7 +1678,6 @@ weston_log_subscribe_to_scopes(struct weston_log_context *log_ctx, weston_log_subscribe(log_ctx, logger, "log"); } - WL_EXPORT int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data) { @@ -1840,12 +1840,23 @@ int wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_da if (load_modules(&ivi, option_modules, &argc, argv, &xwayland) < 0) goto error_compositor; - if (ivi_policy_init(&ivi) < 0) - goto error_compositor; + if (!xwayland) { + weston_config_section_get_bool(section, "xwayland", &xwayland, + false); + } if (ivi_shell_init(&ivi) < 0) goto error_compositor; + if (xwayland) { + if (wet_load_xwayland(ivi.compositor) < 0) + goto error_compositor; + } + + if (ivi_policy_init(&ivi) < 0) + goto error_compositor; + + if (list_debug_scopes) { struct weston_log_scope *nscope = NULL; diff --git a/src/desktop.c b/src/desktop.c index ed648c2..9f472c0 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -30,6 +30,7 @@ #include "shared/helpers.h" #include <libweston/libweston.h> #include <libweston-desktop/libweston-desktop.h> +#include <libweston/xwayland-api.h> #include "agl-shell-desktop-server-protocol.h" @@ -512,7 +513,12 @@ static void desktop_set_xwayland_position(struct weston_desktop_surface *dsurface, int32_t x, int32_t y, void *userdata) { - /* not supported */ + struct ivi_surface *ivisurf = + weston_desktop_surface_get_user_data(dsurface); + + ivisurf->xwayland.x = x; + ivisurf->xwayland.y = y; + ivisurf->xwayland.is_set = true; } static const struct weston_desktop_api desktop_api = { @@ -543,9 +549,39 @@ ivi_shell_destroy(struct wl_listener *listener, void *data) ivi_layout_destroy_saved_outputs(ivi); weston_desktop_destroy(ivi->desktop); + wl_list_remove(&ivi->transform_listener.link); wl_list_remove(&listener->link); } +static void +transform_handler(struct wl_listener *listener, void *data) +{ + struct weston_surface *surface = data; + struct ivi_surface *ivisurf = get_ivi_shell_surface(surface); + const struct weston_xwayland_surface_api *api; + int x, y; + + if (!ivisurf) + return; + + api = ivisurf->ivi->xwayland_surface_api; + if (!api) { + api = weston_xwayland_surface_get_api(ivisurf->ivi->compositor); + ivisurf->ivi->xwayland_surface_api = api; + } + + if (!api || !api->is_xwayland_surface(surface)) + return; + + if (!weston_view_is_mapped(ivisurf->view)) + return; + + x = ivisurf->view->geometry.x; + y = ivisurf->view->geometry.y; + + api->send_position(surface, x, y); +} + int ivi_desktop_init(struct ivi_compositor *ivi) { @@ -560,5 +596,10 @@ ivi_desktop_init(struct ivi_compositor *ivi) return -1; } + ivi->transform_listener.notify = transform_handler; + wl_signal_add(&ivi->compositor->transform_signal, + &ivi->transform_listener); + + return 0; } diff --git a/src/ivi-compositor.h b/src/ivi-compositor.h index 207fd82..c5d9fc3 100644 --- a/src/ivi-compositor.h +++ b/src/ivi-compositor.h @@ -117,6 +117,8 @@ struct ivi_compositor { struct wl_list remote_pending_apps; struct wl_listener destroy_listener; + struct wl_listener transform_listener; + const struct weston_xwayland_surface_api *xwayland_surface_api; struct weston_layer hidden; struct weston_layer background; @@ -304,6 +306,12 @@ struct ivi_surface { struct wl_listener listener_advertise_app; struct wl_signal signal_advertise_app; + + struct { + bool is_set; + int32_t x; + int32_t y; + } xwayland; }; struct ivi_shell_seat { diff --git a/src/layout.c b/src/layout.c index 082c36e..89c2097 100644 --- a/src/layout.c +++ b/src/layout.c @@ -581,7 +581,7 @@ ivi_layout_desktop_committed(struct ivi_surface *surf) return; } - if (!surf->ivi->activate_by_default) { + if (!surf->ivi->activate_by_default && !surf->xwayland.is_set) { weston_log("Refusing to activate surface role %d, app_id %s\n", surf->role, app_id); @@ -611,7 +611,12 @@ ivi_layout_desktop_committed(struct ivi_surface *surf) */ weston_log("Surface no app_id, role %s activating by default\n", ivi_layout_get_surface_role_name(surf)); - ivi_layout_activate_by_surf(r_output, surf); + if (surf->xwayland.is_set) { + ivi_layout_activate_by_surf(r_output, surf); + ivi_layout_activate_complete(r_output, surf); + } else { + ivi_layout_activate_by_surf(r_output, surf); + } } } 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 <signal.h> +#include <string.h> +#include <errno.h> +#include <sys/socket.h> + +#include <libweston/libweston.h> +#include <weston.h> +#include <libweston/xwayland-api.h> +#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; +} |