[PATCH] compositor: pass options to the shell process

Pekka Paalanen ppaalanen at gmail.com
Fri Nov 4 03:33:36 PDT 2011


When desktop-shell was changed to be launched by the compositor alone,
we also lost the opportunity to give it arguments, specifically the
background picture.

Add the compositor option -b (--shell-option) which can be used to pass
any number of options to the desktop-shell by using it repeatedly.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 compositor/compositor.c         |   15 ++++++++++-
 compositor/meego-tablet-shell.c |    4 +-
 compositor/shell.c              |   50 +++++++++++++++++++++++++-------------
 3 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/compositor/compositor.c b/compositor/compositor.c
index 53b282a..a516837 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -2159,13 +2159,15 @@ int main(int argc, char *argv[])
 	struct wl_event_loop *loop;
 	int o, xserver = 0;
 	void *shell_module, *backend_module;
-	int (*shell_init)(struct wlsc_compositor *ec);
+	int (*shell_init)(struct wlsc_compositor *ec, struct wl_array *opts);
 	struct wlsc_compositor
 		*(*backend_init)(struct wl_display *display, char *options);
 	char *backend = NULL;
 	char *backend_options = "";
 	char *shell = NULL;
 	char *p;
+	struct wl_array shell_options; /* contains (char *) */
+	char **pp;
 
 	static const char opts[] = "B:b:o:S:i:s:x";
 	static const struct option longopts[ ] = {
@@ -2174,12 +2176,19 @@ int main(int argc, char *argv[])
 		{ "socket", 1, NULL, 'S' },
 		{ "idle-time", 1, NULL, 'i' },
 		{ "shell", 1, NULL, 's' },
+		{ "shell-option", 1, NULL, 'b' },
 		{ "xserver", 0, NULL, 'x' },
 		{ NULL, }
 	};
 
+	wl_array_init(&shell_options);
+
 	while (o = getopt_long(argc, argv, opts, longopts, &o), o > 0) {
 		switch (o) {
+		case 'b':
+			pp = wl_array_add(&shell_options, sizeof *pp);
+			*pp = optarg;
+			break;
 		case 'B':
 			backend = optarg;
 			break;
@@ -2245,7 +2254,7 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (shell_init(ec) < 0)
+	if (shell_init(ec, &shell_options) < 0)
 		exit(EXIT_FAILURE);
 
 	if (xserver)
@@ -2267,5 +2276,7 @@ int main(int argc, char *argv[])
 
 	ec->destroy(ec);
 
+	wl_array_release(&shell_options);
+
 	return 0;
 }
diff --git a/compositor/meego-tablet-shell.c b/compositor/meego-tablet-shell.c
index 35b9775..368971f 100644
--- a/compositor/meego-tablet-shell.c
+++ b/compositor/meego-tablet-shell.c
@@ -638,10 +638,10 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 }
 
 void
-shell_init(struct wlsc_compositor *compositor);
+shell_init(struct wlsc_compositor *compositor, struct wl_array *opts);
 
 WL_EXPORT void
-shell_init(struct wlsc_compositor *compositor)
+shell_init(struct wlsc_compositor *compositor, struct wl_array *opts)
 {
 	struct meego_tablet_shell *shell;
 	struct wl_event_loop *loop;
diff --git a/compositor/shell.c b/compositor/shell.c
index ed2637d..b409d50 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -943,13 +943,39 @@ desktop_shell_sigchld(struct wlsc_process *process, int status)
 	shell->child.client = NULL; /* already destroyed by wayland */
 }
 
+static void
+child_exec(int sockfd, const char *path, struct wl_array *opts)
+{
+	char s[32];
+	int flags;
+	char **argv;
+	int nelem = opts ? (opts->size / sizeof *argv) : 0;
+
+	argv = malloc((nelem + 2) * sizeof *argv);
+	argv[0] = (char *)path;
+	if (nelem > 0)
+		memcpy(&argv[1], opts->data, opts->size);
+	argv[nelem + 1] = NULL;
+
+	/* SOCK_CLOEXEC closes both ends, so we need to unset
+	 * the flag on the client fd. */
+	flags = fcntl(sockfd, F_GETFD);
+	if (flags != -1)
+		fcntl(sockfd, F_SETFD, flags & ~FD_CLOEXEC);
+
+	snprintf(s, sizeof s, "%d", sockfd);
+	setenv("WAYLAND_SOCKET", s, 1);
+
+	if (execv(path, argv) < 0)
+		fprintf(stderr, "running '%s' failed: %m\n", path);
+}
+
 static int
-launch_desktop_shell_process(struct wl_shell *shell)
+launch_desktop_shell_process(struct wl_shell *shell, struct wl_array *opts)
 {
 	const char *shell_exe = "./clients/desktop-shell";
 	struct wlsc_compositor *compositor = shell->compositor;
-	char s[32];
-	int sv[2], flags;
+	int sv[2];
 
 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
 		fprintf(stderr, "socketpair failed\n");
@@ -961,17 +987,7 @@ launch_desktop_shell_process(struct wl_shell *shell)
 
 	switch (shell->child.process.pid) {
 	case 0:
-		/* SOCK_CLOEXEC closes both ends, so we need to unset
-		 * the flag on the client fd. */
-		flags = fcntl(sv[1], F_GETFD);
-		if (flags != -1)
-			fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
-
-		snprintf(s, sizeof s, "%d", sv[1]);
-		setenv("WAYLAND_SOCKET", s, 1);
-		if (execl(shell_exe, shell_exe, NULL) < 0)
-			fprintf(stderr, "%s: running '%s' failed: %m\n",
-				__func__, shell_exe);
+		child_exec(sv[1], shell_exe, opts);
 		exit(-1);
 
 	default:
@@ -1017,10 +1033,10 @@ bind_desktop_shell(struct wl_client *client,
 }
 
 int
-shell_init(struct wlsc_compositor *ec);
+shell_init(struct wlsc_compositor *ec, struct wl_array *opts);
 
 WL_EXPORT int
-shell_init(struct wlsc_compositor *ec)
+shell_init(struct wlsc_compositor *ec, struct wl_array *opts)
 {
 	struct wl_shell *shell;
 
@@ -1044,7 +1060,7 @@ shell_init(struct wlsc_compositor *ec)
 				  shell, bind_desktop_shell) == NULL)
 		return -1;
 
-	if (launch_desktop_shell_process(shell) != 0)
+	if (launch_desktop_shell_process(shell, opts) != 0)
 		return -1;
 
 	wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
-- 
1.7.3.4



More information about the wayland-devel mailing list