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

Derek Foreman derekf at osg.samsung.com
Wed Oct 22 08:57:16 PDT 2014


I'd prefer to see the refactor and the new feature in separate patches,
but this is pretty trivial.

I also have a slight preference for exit(EXIT_FAILURE), which is already
used somewhere else in that file - though there's also precedent for
exit(1), so you make the call.  :)

I'd not seen printf's %m until today - do we want to depend on a gnuism?
 I've seen at least some activity towards a freebsd port - I don't
believe %m is supported there?


That said, it runs nicely here and does what it says on the tin...

Reviewed-by: Derek Foreman <derekf at osg.samsung.com>

On 22/10/14 08:53 AM, Pekka Paalanen wrote:
> 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
> 



More information about the wayland-devel mailing list