This creates a new library, libweston-xwayland.so with the entry point to easily spawn a xwayland server. The xwayland module now links to that library. --- Makefile.am | 40 ++++++++-- xwayland/launcher.c | 157 ++++++++------------------------------ xwayland/xwayland-module.c | 185 +++++++++++++++++++++++++++++++++++++++++++++ xwayland/xwayland.h | 26 ++++++- 4 files changed, 273 insertions(+), 135 deletions(-) create mode 100644 xwayland/xwayland-module.c
diff --git a/Makefile.am b/Makefile.am index dcc0488..ef0a892 100644 --- a/Makefile.am +++ b/Makefile.am @@ -175,7 +175,8 @@ westoninclude_HEADERS = \ src/weston-launcher.h \ shared/matrix.h \ shared/config-parser.h \ - shared/zalloc.h + shared/zalloc.h \ + xwayland/xwayland.h if ENABLE_EGL module_LTLIBRARIES += gl-renderer.la @@ -780,9 +781,9 @@ endif if ENABLE_XWAYLAND -module_LTLIBRARIES += xwayland.la +lib_LTLIBRARIES += libweston-xwayland.la -xwayland_la_CPPFLAGS = \ +libweston_xwayland_la_CPPFLAGS = \ -I$(top_builddir)/protocol \ -I$(top_srcdir)/shared \ -I$(top_srcdir)/src \ @@ -792,17 +793,16 @@ xwayland_la_CPPFLAGS = \ -DMODULEDIR='"$(moduledir)"' \ -DLIBEXECDIR='"$(libexecdir)"' \ -DXSERVER_PATH='"@XSERVER_PATH@"' - -xwayland_la_LDFLAGS = -module -avoid-version -xwayland_la_LIBADD = \ +libweston_xwayland_la_LIBADD = \ $(XWAYLAND_LIBS) \ + libweston.la \ $(top_builddir)/libshared-cairo.la -xwayland_la_CFLAGS = \ +libweston_xwayland_la_CFLAGS = \ $(GCC_CFLAGS) \ $(COMPOSITOR_CFLAGS) \ $(PIXMAN_CFLAGS) \ $(CAIRO_CFLAGS) -xwayland_la_SOURCES = \ +libweston_xwayland_la_SOURCES = \ xwayland/xwayland.h \ xwayland/window-manager.c \ xwayland/selection.c \ @@ -810,6 +810,30 @@ xwayland_la_SOURCES = \ xwayland/launcher.c \ xwayland/hash.c \ xwayland/hash.h + +module_LTLIBRARIES += xwayland.la + +xwayland_la_CPPFLAGS = \ + -I$(top_builddir)/protocol \ + -I$(top_srcdir)/shared \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -I$(top_builddir)/xwayland \ + -DDATADIR='"$(datadir)"' \ + -DMODULEDIR='"$(moduledir)"' \ + -DLIBEXECDIR='"$(libexecdir)"' \ + -DXSERVER_PATH='"@XSERVER_PATH@"' + +xwayland_la_LDFLAGS = -module -avoid-version +xwayland_la_LIBADD = \ + libweston-xwayland.la +xwayland_la_CFLAGS = \ + $(GCC_CFLAGS) \ + $(COMPOSITOR_CFLAGS) \ + $(PIXMAN_CFLAGS) \ + $(CAIRO_CFLAGS) +xwayland_la_SOURCES = \ + xwayland/xwayland-module.c endif diff --git a/xwayland/launcher.c b/xwayland/launcher.c index 2a76ee3..54cff78 100644 --- a/xwayland/launcher.c +++ b/xwayland/launcher.c @@ -53,97 +53,17 @@ static int weston_xserver_handle_event(int listen_fd, uint32_t mask, void *data) { struct weston_xserver *wxs = data; - char display[8], s[8], abstract_fd[8], unix_fd[8], wm_fd[8]; - int sv[2], wm[2], fd; - char *xserver = NULL; - 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; - } + wxs->pid = wxs->spawn_xserver(wxs); - if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, wm) < 0) { - weston_log("X wm connection socketpair failed\n"); - return 1; + if (wxs->pid == -1) { + weston_log( "failed to fork\n"); + return -1; } - wxs->process.pid = fork(); - switch (wxs->process.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); - - snprintf(display, sizeof display, ":%d", wxs->display); - - fd = dup(wxs->abstract_fd); - if (fd < 0) - goto fail; - snprintf(abstract_fd, sizeof abstract_fd, "%d", fd); - fd = dup(wxs->unix_fd); - if (fd < 0) - goto fail; - snprintf(unix_fd, sizeof unix_fd, "%d", fd); - fd = dup(wm[1]); - if (fd < 0) - goto fail; - snprintf(wm_fd, sizeof wm_fd, "%d", fd); - - section = weston_config_get_section(wxs->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", - "-listen", abstract_fd, - "-listen", unix_fd, - "-wm", wm_fd, - "-terminate", - NULL) < 0) - weston_log("exec of '%s %s -rootless " - "-listen %s -listen %s -wm %s " - "-terminate' failed: %m\n", - xserver, display, - abstract_fd, unix_fd, wm_fd); - fail: - _exit(EXIT_FAILURE); - - default: - weston_log("forked X server, pid %d\n", wxs->process.pid); - - close(sv[1]); - wxs->client = wl_client_create(wxs->wl_display, sv[0]); - - close(wm[1]); - wxs->wm_fd = wm[0]; - - weston_watch_process(&wxs->process); - - wl_event_source_remove(wxs->abstract_source); - wl_event_source_remove(wxs->unix_source); - break; + weston_log("forked X server, pid %d\n", wxs->pid); - case -1: - weston_log( "failed to fork\n"); - break; - } + wl_event_source_remove(wxs->abstract_source); + wl_event_source_remove(wxs->unix_source); return 1; } @@ -157,7 +77,7 @@ weston_xserver_shutdown(struct weston_xserver *wxs) unlink(path); snprintf(path, sizeof path, "/tmp/.X11-unix/X%d", wxs->display); unlink(path); - if (wxs->process.pid == 0) { + if (wxs->pid == 0) { wl_event_source_remove(wxs->abstract_source); wl_event_source_remove(wxs->unix_source); } @@ -170,13 +90,10 @@ weston_xserver_shutdown(struct weston_xserver *wxs) wxs->loop = NULL; } -static void -weston_xserver_cleanup(struct weston_process *process, int status) +WL_EXPORT void +weston_xserver_exited(struct weston_xserver *wxs, int status) { - struct weston_xserver *wxs = - container_of(process, struct weston_xserver, process); - - wxs->process.pid = 0; + wxs->pid = 0; wxs->client = NULL; wxs->resource = NULL; @@ -329,41 +246,24 @@ create_lockfile(int display, char *lockfile, size_t lsize) return 0; } -static void -weston_xserver_destroy(struct wl_listener *l, void *data) -{ - struct weston_xserver *wxs = - container_of(l, struct weston_xserver, destroy_listener); - - if (!wxs) - return; - - if (wxs->loop) - weston_xserver_shutdown(wxs); - - free(wxs); -} - -WL_EXPORT int -module_init(struct weston_compositor *compositor, - int *argc, char *argv[], - struct weston_config *config) - +WL_EXPORT struct weston_xserver * +weston_xserver_create(struct weston_compositor *c, const char *xserver) { - struct wl_display *display = compositor->wl_display; + struct wl_display *display = c->wl_display; struct weston_xserver *wxs; char lockfile[256], display_name[8]; wxs = zalloc(sizeof *wxs); if (wxs == NULL) - return -1; - wxs->process.cleanup = weston_xserver_cleanup; + return NULL; wxs->wl_display = display; - wxs->compositor = compositor; + wxs->compositor = c; + wxs->spawn_xserver = NULL; + wxs->xserver_path = strdup(xserver); wxs->display = 0; - retry: +retry: if (create_lockfile(wxs->display, lockfile, sizeof lockfile) < 0) { if (errno == EAGAIN) { goto retry; @@ -372,7 +272,7 @@ module_init(struct weston_compositor *compositor, goto retry; } else { free(wxs); - return -1; + return NULL; } } @@ -388,14 +288,13 @@ module_init(struct weston_compositor *compositor, unlink(lockfile); close(wxs->abstract_fd); free(wxs); - return -1; + return NULL; } snprintf(display_name, sizeof display_name, ":%d", wxs->display); weston_log("xserver listening on display %s\n", display_name); setenv("DISPLAY", display_name, 1); - wxs->config = config; wxs->loop = wl_display_get_event_loop(display); wxs->abstract_source = wl_event_loop_add_fd(wxs->loop, wxs->abstract_fd, @@ -408,8 +307,16 @@ module_init(struct weston_compositor *compositor, wxs->sigusr1_source = wl_event_loop_add_signal(wxs->loop, SIGUSR1, handle_sigusr1, wxs); - wxs->destroy_listener.notify = weston_xserver_destroy; - wl_signal_add(&compositor->destroy_signal, &wxs->destroy_listener); - return 0; + return wxs; +} + +WL_EXPORT void +weston_xserver_destroy(struct weston_xserver *wxs) +{ + if (wxs->loop) + weston_xserver_shutdown(wxs); + + free(wxs->xserver_path); + free(wxs); } diff --git a/xwayland/xwayland-module.c b/xwayland/xwayland-module.c new file mode 100644 index 0000000..39bac87 --- /dev/null +++ b/xwayland/xwayland-module.c @@ -0,0 +1,185 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <signal.h> + +#include "xwayland.h" +#include "compositor.h" + +struct xserver { + struct wl_listener destroy_listener; + struct weston_xserver *weston_xserver; + struct weston_process process; +}; + +static void +xserver_destroy(struct wl_listener *l, void *data) +{ + struct xserver *xs = + container_of(l, struct xserver, destroy_listener); + + if (!xs || !xs->weston_xserver) + return; + + weston_xserver_destroy(xs->weston_xserver); + free(xs); +} + +static pid_t +xserver_spawn(struct weston_xserver *wxs) +{ + struct wl_listener *l = wl_signal_get(&wxs->compositor->destroy_signal, + xserver_destroy); + struct xserver *xs = container_of(l, struct xserver, destroy_listener); + + pid_t pid; + char display[8], s[8], abstract_fd[8], unix_fd[8], wm_fd[8]; + int sv[2], wm[2], fd; + + 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); + + snprintf(display, sizeof display, ":%d", wxs->display); + + fd = dup(wxs->abstract_fd); + if (fd < 0) + goto fail; + snprintf(abstract_fd, sizeof abstract_fd, "%d", fd); + fd = dup(wxs->unix_fd); + if (fd < 0) + goto fail; + snprintf(unix_fd, sizeof unix_fd, "%d", fd); + fd = dup(wm[1]); + if (fd < 0) + goto fail; + snprintf(wm_fd, sizeof wm_fd, "%d", fd); + + /* 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(wxs->xserver_path, + wxs->xserver_path, + display, + "-rootless", + "-listen", abstract_fd, + "-listen", unix_fd, + "-wm", wm_fd, + "-terminate", + NULL) < 0) + weston_log("exec of '%s %s -rootless " + "-listen %s -listen %s -wm %s " + "-terminate' failed: %m\n", + wxs->xserver_path, display, + abstract_fd, unix_fd, wm_fd); + fail: + _exit(EXIT_FAILURE); + + default: + close(sv[1]); + wxs->client = wl_client_create(wxs->wl_display, sv[0]); + + close(wm[1]); + wxs->wm_fd = wm[0]; + + xs->process.pid = pid; + weston_watch_process(&xs->process); + break; + + case -1: + weston_log( "failed to fork\n"); + break; + } + + return pid; +} + +static void +xserver_cleanup(struct weston_process *process, int status) +{ + struct xserver *xs = + container_of(process, struct xserver, process); + weston_xserver_exited(xs->weston_xserver, status); +} + +WL_EXPORT int +module_init(struct weston_compositor *compositor, + int *argc, char *argv[], struct weston_config *config) + +{ + struct xserver *xs; + struct weston_config_section *section; + char *xserver = NULL; + + section = weston_config_get_section(config, + "xwayland", NULL, NULL); + weston_config_section_get_string(section, "path", + &xserver, XSERVER_PATH); + + xs = zalloc(sizeof *xs); + if (!xs) + return -1; + + xs->weston_xserver = weston_xserver_create(compositor, xserver); + if (!xs->weston_xserver) + return -1; + + xs->process.cleanup = xserver_cleanup; + xs->weston_xserver->spawn_xserver = xserver_spawn; + xs->destroy_listener.notify = xserver_destroy; + wl_signal_add(&compositor->destroy_signal, &xs->destroy_listener); + + return 0; +} \ No newline at end of file diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h index 161615f..4f3972a 100644 --- a/xwayland/xwayland.h +++ b/xwayland/xwayland.h @@ -20,6 +20,13 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef _WESTON_XWAYLAND_H_ +#define _WESTON_XWAYLAND_H_ + +#ifdef __cplusplus +extern "C" { +#endif + #include <wayland-server.h> #include <xcb/xcb.h> #include <xcb/xfixes.h> @@ -41,14 +48,16 @@ struct weston_xserver { struct wl_event_source *unix_source; int wm_fd; int display; + char *xserver_path; struct wl_event_source *sigusr1_source; - struct weston_process process; + pid_t pid; struct wl_resource *resource; struct wl_client *client; struct weston_compositor *compositor; struct weston_wm *wm; - struct weston_config *config; struct wl_listener destroy_listener; + + pid_t (*spawn_xserver)(struct weston_xserver *wxs); }; struct weston_wm { @@ -151,6 +160,13 @@ struct weston_wm { } atom; }; +struct weston_xserver * +weston_xserver_create(struct weston_compositor *c, const char *xserver); +void +weston_xserver_destroy(struct weston_xserver *wxs); +void +weston_xserver_exited(struct weston_xserver *wxs, int status); + void dump_property(struct weston_wm *wm, xcb_atom_t property, xcb_get_property_reply_t *reply); @@ -177,3 +193,9 @@ weston_wm_handle_dnd_event(struct weston_wm *wm, xcb_generic_event_t *event); void weston_wm_dnd_init(struct weston_wm *wm); + +#ifdef __cplusplus +} +#endif + +#endif -- 2.1.3 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel