[PATCH Weston 1/1] desktop-shell: implement autolaunch

Pekka Paalanen pekka.paalanen at collabora.co.uk
Wed Oct 22 06:53:55 PDT 2014


Process a new section 'autolaunch' from weston.ini, launching all
programs given there on desktop start-up.

[Frederic Plourde: cut redundancy between do_autolaunch and panel_add_launcher]
---
 clients/desktop-shell.c | 97 ++++++++++++++++++++++++++++++++++++++++++-------
 man/weston.ini.man      | 17 +++++++++
 weston.ini.in           |  3 ++
 3 files changed, 103 insertions(+), 14 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 961a9b2..a964094 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -597,72 +597,82 @@ load_icon_or_fallback(const char *icon)
 	cairo_move_to(cr, 4, 16);
 	cairo_line_to(cr, 16, 4);
 	cairo_stroke(cr);
 
 	cairo_destroy(cr);
 
 	return surface;
 }
 
 static void
-panel_add_launcher(struct panel *panel, const char *icon, const char *path)
+parse_launcher_path(char *path, struct wl_array *envp_array, struct wl_array *argv_array)
 {
-	struct panel_launcher *launcher;
 	char *start, *p, *eq, **ps;
 	int i, j, k;
 
-	launcher = xzalloc(sizeof *launcher);
-	launcher->icon = load_icon_or_fallback(icon);
-	launcher->path = xstrdup(path);
+	struct wl_array *envp = envp_array;
+	struct wl_array *argv = argv_array;
 
-	wl_array_init(&launcher->envp);
-	wl_array_init(&launcher->argv);
+	wl_array_init(envp);
+	wl_array_init(argv);
 	for (i = 0; environ[i]; i++) {
-		ps = wl_array_add(&launcher->envp, sizeof *ps);
+		ps = wl_array_add(envp, sizeof *ps);
 		*ps = environ[i];
 	}
 	j = 0;
 
-	start = launcher->path;
+	start = path;
 	while (*start) {
 		for (p = start, eq = NULL; *p && !isspace(*p); p++)
 			if (*p == '=')
 				eq = p;
 
 		if (eq && j == 0) {
-			ps = launcher->envp.data;
+			ps = envp->data;
 			for (k = 0; k < i; k++)
 				if (strncmp(ps[k], start, eq - start) == 0) {
 					ps[k] = start;
 					break;
 				}
 			if (k == i) {
-				ps = wl_array_add(&launcher->envp, sizeof *ps);
+				ps = wl_array_add(envp, sizeof *ps);
 				*ps = start;
 				i++;
 			}
 		} else {
-			ps = wl_array_add(&launcher->argv, sizeof *ps);
+			ps = wl_array_add(argv, sizeof *ps);
 			*ps = start;
 			j++;
 		}
 
 		while (*p && isspace(*p))
 			*p++ = '\0';
 
 		start = p;
 	}
 
-	ps = wl_array_add(&launcher->envp, sizeof *ps);
+	ps = wl_array_add(envp, sizeof *ps);
 	*ps = NULL;
-	ps = wl_array_add(&launcher->argv, sizeof *ps);
+	ps = wl_array_add(argv, sizeof *ps);
 	*ps = NULL;
+}
+
+static void
+panel_add_launcher(struct panel *panel, const char *icon, const char *path)
+{
+	struct panel_launcher *launcher;
+
+	launcher = xzalloc(sizeof *launcher);
+	launcher->icon = load_icon_or_fallback(icon);
+	launcher->path = xstrdup(path);
+
+	parse_launcher_path(launcher->path, &launcher->envp, &launcher->argv);
 
 	launcher->panel = panel;
 	wl_list_insert(panel->launcher_list.prev, &launcher->link);
 
 	launcher->widget = widget_add_widget(panel->widget, launcher);
 	widget_set_enter_handler(launcher->widget,
 				 panel_launcher_enter_handler);
 	widget_set_leave_handler(launcher->widget,
 				   panel_launcher_leave_handler);
 	widget_set_button_handler(launcher->widget,
@@ -1316,20 +1326,77 @@ panel_add_launchers(struct panel *panel, struct desktop *desktop)
 	}
 
 	if (count == 0) {
 		/* add default launcher */
 		panel_add_launcher(panel,
 				   DATADIR "/weston/terminal.png",
 				   BINDIR "/weston-terminal");
 	}
 }
 
+static void
+do_autolaunch(const char *path_arg)
+{
+	struct wl_array envp;
+	struct wl_array argv;
+	pid_t pid;
+	char **argvpp;
+	char *path;
+
+	path = xstrdup(path_arg);
+
+	parse_launcher_path(path, &envp, &argv);
+
+	/* panel_launcher_activate */
+
+	pid = fork();
+	if (pid < 0) {
+		fprintf(stderr, "fork failed: %m\n");
+		goto out;
+	}
+
+	if (pid)
+		goto out;
+
+	argvpp = argv.data;
+	if (execve(argvpp[0], argvpp, envp.data) < 0) {
+		fprintf(stderr, "execl '%s' failed: %m\n", argvpp[0]);
+		exit(1);
+	}
+
+out:
+	wl_array_release(&argv);
+	wl_array_release(&envp);
+	free(path);
+}
+
+static void
+process_autolaunch(struct desktop *desktop)
+{
+	struct weston_config_section *s;
+	char *path;
+	const char *name;
+
+	s = NULL;
+	while (weston_config_next_section(desktop->config, &s, &name)) {
+		if (strcmp(name, "autolaunch") != 0)
+			continue;
+
+		weston_config_section_get_string(s, "path", &path, NULL);
+		if (!path)
+			continue;
+
+		do_autolaunch(path);
+		free(path);
+	}
+}
+
 int main(int argc, char *argv[])
 {
 	struct desktop desktop = { 0 };
 	struct output *output;
 	struct weston_config_section *s;
 
 	desktop.unlock_task.run = unlock_dialog_finish;
 	wl_list_init(&desktop.outputs);
 
 	desktop.config = weston_config_parse("weston.ini");
@@ -1349,20 +1416,22 @@ int main(int argc, char *argv[])
 	/* Create panel and background for outputs processed before the shell
 	 * global interface was processed */
 	wl_list_for_each(output, &desktop.outputs, link)
 		if (!output->panel)
 			output_init(output, &desktop);
 
 	grab_surface_create(&desktop);
 
 	signal(SIGCHLD, sigchild_handler);
 
+	process_autolaunch(&desktop);
+
 	display_run(desktop.display);
 
 	/* Cleanup */
 	grab_surface_destroy(&desktop);
 	desktop_destroy_outputs(&desktop);
 	if (desktop.unlock_dialog)
 		unlock_dialog_destroy(desktop.unlock_dialog);
 	desktop_shell_destroy(desktop.shell);
 	display_destroy(desktop.display);
 
diff --git a/man/weston.ini.man b/man/weston.ini.man
index c05a221..365141c 100644
--- a/man/weston.ini.man
+++ b/man/weston.ini.man
@@ -66,20 +66,21 @@ Comment lines are ignored:
 .RE
 .PP
 The section headers are:
 .PP
 .RS 4
 .nf
 .BR "core           " "The core modules"
 .BR "libinput       " "Input device configuration"
 .BR "shell          " "Desktop customization"
 .BR "launcher       " "Add launcher to the panel"
+.BR "autolaunch     " "Launch program automatically on startup"
 .BR "screensaver    " "Screensaver selection"
 .BR "output         " "Output configuration"
 .BR "input-method   " "Onscreen keyboard input"
 .BR "keyboard       " "Keyboard layouts"
 .BR "terminal       " "Terminal application options"
 .BR "xwayland       " "XWayland options"
 .BR "screen-share   " "Screen sharing options"
 .fi
 .RE
 .PP
@@ -272,20 +273,36 @@ sets the path to the program that is run by clicking on this launcher (string).
 It is possible to pass arguments and environment variables to the program. For
 example:
 .nf
 .in +4n
 
 path=GDK_BACKEND=wayland gnome-terminal --full-screen
 .in
 .fi
 .PP
 .RE
+.SH "AUTOLAUNCH SECTION"
+There can be multiple autolaunch sections for starting multiple programs.
+.TP 7
+.BI "path=" program
+sets the path (string) to the program that is run automatically when the
+desktop is starting.
+It is possible to pass arguments and environment variables to the program. For
+example:
+.nf
+.in +4n
+
+path=GDK_BACKEND=wayland gnome-terminal --full-screen
+.in
+.fi
+.PP
+.RE
 .SH "SCREENSAVER SECTION"
 The
 .B screensaver
 section is used to select and schedule a screensaver.
 The
 .B screensaver
 section is optional, as are all of the entries that may be specified in
 it.
 .TP 7
 .BI "path=" /usr/libexec/weston-screensaver
diff --git a/weston.ini.in b/weston.ini.in
index 4fca0bb..b0cb31f 100644
--- a/weston.ini.in
+++ b/weston.ini.in
@@ -30,20 +30,23 @@ icon=/usr/share/icons/gnome/24x24/apps/utilities-terminal.png
 path=@bindir@/weston-terminal
 
 [launcher]
 icon=/usr/share/icons/hicolor/24x24/apps/google-chrome.png
 path=/usr/bin/google-chrome
 
 [launcher]
 icon=/usr/share/icons/gnome/24x24/apps/arts.png
 path=@abs_top_builddir@/weston-flower
 
+#[autolaunch]
+#path=@bindir@/weston-terminal
+
 [screensaver]
 # Comment path to disable screensaver
 path=@libexecdir@/weston-screensaver
 duration=600
 
 [input-method]
 path=@libexecdir@/weston-keyboard
 
 #[output]
 #name=LVDS1
-- 
1.9.1



More information about the wayland-devel mailing list