[weston,v2,15/17] libweston: libweston-ify xwayland

Submitted by Giulio Camuffo on Dec. 4, 2014, 9:01 p.m.

Details

Message ID 1417726883-8305-16-git-send-email-giuliocamuffo@gmail.com
State Superseded
Headers show

Not browsing as part of any series.

Commit Message

Giulio Camuffo Dec. 4, 2014, 9:01 p.m.
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        | 155 ++++++++-----------------------------
 xwayland/xwayland-module.c | 188 +++++++++++++++++++++++++++++++++++++++++++++
 xwayland/xwayland.h        |  25 +++++-
 4 files changed, 273 insertions(+), 135 deletions(-)
 create mode 100644 xwayland/xwayland-module.c

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index 109f7d7..4ddfe34 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -182,7 +182,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
@@ -859,9 +860,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			\
@@ -871,17 +872,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			\
@@ -889,6 +889,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..1bbf2e0 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,23 @@  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)
 {
-	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->display = 0;
 
- retry:
+retry:
 	if (create_lockfile(wxs->display, lockfile, sizeof lockfile) < 0) {
 		if (errno == EAGAIN) {
 			goto retry;
@@ -372,7 +271,7 @@  module_init(struct weston_compositor *compositor,
 			goto retry;
 		} else {
 			free(wxs);
-			return -1;
+			return NULL;
 		}
 	}
 
@@ -388,14 +287,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 +306,15 @@  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);
 }
diff --git a/xwayland/xwayland-module.c b/xwayland/xwayland-module.c
new file mode 100644
index 0000000..d74f0f0
--- /dev/null
+++ b/xwayland/xwayland-module.c
@@ -0,0 +1,188 @@ 
+/*
+ * 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;
+	char *xserver_path;
+};
+
+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->xserver_path);
+	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(xs->xserver_path,
+			  xs->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",
+                                   xs->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;
+
+	xs = zalloc(sizeof *xs);
+	if (!xs)
+		return -1;
+
+	xs->weston_xserver = weston_xserver_create(compositor);
+	if (!xs->weston_xserver) {
+		free(xs);
+		return -1;
+	}
+
+	section = weston_config_get_section(config,
+	                                    "xwayland", NULL, NULL);
+	weston_config_section_get_string(section, "path",
+	                                 &xs->xserver_path, XSERVER_PATH);
+
+	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..2bbbac0 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>
@@ -42,13 +49,14 @@  struct weston_xserver {
 	int wm_fd;
 	int display;
 	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 +159,13 @@  struct weston_wm {
 	} atom;
 };
 
+struct weston_xserver *
+weston_xserver_create(struct weston_compositor *c);
+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 +192,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