From bbfbd28dfa0d6bc15203637e43be75b7c127eb29 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 25 Oct 2011 22:18:17 +0100 Subject: [PATCH] Add a --no-startup-id flag for exec (command), exec (config), exec_always (config) --- include/data.h | 3 ++ include/startup.h | 5 ++- src/cfgparse.y | 26 ++++++++++++-- src/cmdparse.y | 11 ++++-- src/main.c | 6 ++-- src/startup.c | 91 ++++++++++++++++++++++++++--------------------- 6 files changed, 93 insertions(+), 49 deletions(-) diff --git a/include/data.h b/include/data.h index cd58ec26..740278ae 100644 --- a/include/data.h +++ b/include/data.h @@ -218,6 +218,9 @@ struct Binding { struct Autostart { /** Command, like in command mode */ char *command; + /** no_startup_id flag for start_application(). Determines whether a + * startup notification context/ID should be created. */ + bool no_startup_id; TAILQ_ENTRY(Autostart) autostarts; TAILQ_ENTRY(Autostart) autostarts_always; }; diff --git a/include/startup.h b/include/startup.h index 9d110c6d..290c8d21 100644 --- a/include/startup.h +++ b/include/startup.h @@ -25,8 +25,11 @@ * The shell is determined by looking for the SHELL environment variable. If * it does not exist, /bin/sh is used. * + * The no_startup_id flag determines whether a startup notification context + * (and ID) should be created, which is the default and encouraged behavior. + * */ -void start_application(const char *command); +void start_application(const char *command, bool no_startup_id); /** * Called by libstartup-notification when something happens diff --git a/src/cfgparse.y b/src/cfgparse.y index 7cd0ce9b..2e0bbe0b 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -1507,8 +1507,19 @@ restart_state: exec: TOKEXEC STR { + char *command = $2; + bool no_startup_id = false; + if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) { + no_startup_id = true; + /* We need to make a copy here, otherwise we leak the + * --no-startup-id bytes in the beginning of the string */ + command = sstrdup(command + strlen("--no-startup-id ")); + free($2); + } + struct Autostart *new = smalloc(sizeof(struct Autostart)); - new->command = $2; + new->command = command; + new->no_startup_id = no_startup_id; TAILQ_INSERT_TAIL(&autostarts, new, autostarts); } ; @@ -1516,8 +1527,19 @@ exec: exec_always: TOKEXEC_ALWAYS STR { + char *command = $2; + bool no_startup_id = false; + if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) { + no_startup_id = true; + /* We need to make a copy here, otherwise we leak the + * --no-startup-id bytes in the beginning of the string */ + command = sstrdup(command + strlen("--no-startup-id ")); + free($2); + } + struct Autostart *new = smalloc(sizeof(struct Autostart)); - new->command = $2; + new->command = command; + new->no_startup_id = no_startup_id; TAILQ_INSERT_TAIL(&autostarts_always, new, autostarts_always); } ; diff --git a/src/cmdparse.y b/src/cmdparse.y index ab26fa59..3eb33426 100644 --- a/src/cmdparse.y +++ b/src/cmdparse.y @@ -389,8 +389,15 @@ operation: exec: TOK_EXEC STR { - printf("should execute %s\n", $2); - start_application($2); + char *command = $2; + bool no_startup_id = false; + if (strncasecmp($2, "--no-startup-id ", strlen("--no-startup-id ")) == 0) { + no_startup_id = true; + command += strlen("--no-startup-id "); + } + + printf("should execute %s, no_startup_id = %d\n", command, no_startup_id); + start_application(command, no_startup_id); free($2); } ; diff --git a/src/main.c b/src/main.c index 52c9e2cd..3cbdfca5 100644 --- a/src/main.c +++ b/src/main.c @@ -635,7 +635,7 @@ int main(int argc, char *argv[]) { struct Autostart *exec; TAILQ_FOREACH(exec, &autostarts, autostarts) { LOG("auto-starting %s\n", exec->command); - start_application(exec->command); + start_application(exec->command, exec->no_startup_id); } } @@ -643,7 +643,7 @@ int main(int argc, char *argv[]) { struct Autostart *exec_always; TAILQ_FOREACH(exec_always, &autostarts_always, autostarts_always) { LOG("auto-starting (always!) %s\n", exec_always->command); - start_application(exec_always->command); + start_application(exec_always->command, exec_always->no_startup_id); } /* Start i3bar processes for all configured bars */ @@ -653,7 +653,7 @@ int main(int argc, char *argv[]) { sasprintf(&command, "i3bar --bar_id=%s --socket=\"%s\"", barconfig->id, current_socketpath); LOG("Starting bar process: %s\n", command); - start_application(command); + start_application(command, true); free(command); } diff --git a/src/startup.c b/src/startup.c index 6a98f3cd..bddf7da1 100644 --- a/src/startup.c +++ b/src/startup.c @@ -63,44 +63,50 @@ static void startup_timeout(EV_P_ ev_timer *w, int revents) { * The shell is determined by looking for the SHELL environment variable. If it * does not exist, /bin/sh is used. * + * The no_startup_id flag determines whether a startup notification context + * (and ID) should be created, which is the default and encouraged behavior. + * */ -void start_application(const char *command) { - /* Create a startup notification context to monitor the progress of this - * startup. */ +void start_application(const char *command, bool no_startup_id) { SnLauncherContext *context; - context = sn_launcher_context_new(sndisplay, conn_screen); - sn_launcher_context_set_name(context, "i3"); - sn_launcher_context_set_description(context, "exec command in i3"); - /* Chop off everything starting from the first space (if there are any - * spaces in the command), since we don’t want the parameters. */ - char *first_word = sstrdup(command); - char *space = strchr(first_word, ' '); - if (space) - *space = '\0'; - sn_launcher_context_initiate(context, "i3", first_word, last_timestamp); - free(first_word); - - /* Trigger a timeout after 60 seconds */ - struct ev_timer *timeout = scalloc(sizeof(struct ev_timer)); - ev_timer_init(timeout, startup_timeout, 60.0, 0.); - timeout->data = context; - ev_timer_start(main_loop, timeout); - - LOG("startup id = %s\n", sn_launcher_context_get_startup_id(context)); - - /* Save the ID and current workspace in our internal list of startup - * sequences */ - Con *ws = con_get_workspace(focused); - struct Startup_Sequence *sequence = scalloc(sizeof(struct Startup_Sequence)); - sequence->id = sstrdup(sn_launcher_context_get_startup_id(context)); - sequence->workspace = sstrdup(ws->name); - sequence->context = context; - TAILQ_INSERT_TAIL(&startup_sequences, sequence, sequences); - - /* Increase the refcount once (it starts with 1, so it will be 2 now) for - * the timeout. Even if the sequence gets completed, the timeout still - * needs the context (but will unref it then) */ - sn_launcher_context_ref(context); + + if (!no_startup_id) { + /* Create a startup notification context to monitor the progress of this + * startup. */ + context = sn_launcher_context_new(sndisplay, conn_screen); + sn_launcher_context_set_name(context, "i3"); + sn_launcher_context_set_description(context, "exec command in i3"); + /* Chop off everything starting from the first space (if there are any + * spaces in the command), since we don’t want the parameters. */ + char *first_word = sstrdup(command); + char *space = strchr(first_word, ' '); + if (space) + *space = '\0'; + sn_launcher_context_initiate(context, "i3", first_word, last_timestamp); + free(first_word); + + /* Trigger a timeout after 60 seconds */ + struct ev_timer *timeout = scalloc(sizeof(struct ev_timer)); + ev_timer_init(timeout, startup_timeout, 60.0, 0.); + timeout->data = context; + ev_timer_start(main_loop, timeout); + + LOG("startup id = %s\n", sn_launcher_context_get_startup_id(context)); + + /* Save the ID and current workspace in our internal list of startup + * sequences */ + Con *ws = con_get_workspace(focused); + struct Startup_Sequence *sequence = scalloc(sizeof(struct Startup_Sequence)); + sequence->id = sstrdup(sn_launcher_context_get_startup_id(context)); + sequence->workspace = sstrdup(ws->name); + sequence->context = context; + TAILQ_INSERT_TAIL(&startup_sequences, sequence, sequences); + + /* Increase the refcount once (it starts with 1, so it will be 2 now) for + * the timeout. Even if the sequence gets completed, the timeout still + * needs the context (but will unref it then) */ + sn_launcher_context_ref(context); + } LOG("executing: %s\n", command); if (fork() == 0) { @@ -108,7 +114,8 @@ void start_application(const char *command) { setsid(); if (fork() == 0) { /* Setup the environment variable(s) */ - sn_launcher_context_setup_child_process(context); + if (!no_startup_id) + sn_launcher_context_setup_child_process(context); /* Stores the path of the shell */ static const char *shell = NULL; @@ -125,10 +132,12 @@ void start_application(const char *command) { } wait(0); - /* Change the pointer of the root window to indicate progress */ - if (xcursor_supported) - xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH); - else xcb_set_root_cursor(XCURSOR_CURSOR_WATCH); + if (!no_startup_id) { + /* Change the pointer of the root window to indicate progress */ + if (xcursor_supported) + xcursor_set_root_cursor(XCURSOR_CURSOR_WATCH); + else xcb_set_root_cursor(XCURSOR_CURSOR_WATCH); + } } /* -- 2.39.5