-#undef I3__FILE__
-#define I3__FILE__ "startup.c"
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
- * © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
+ * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
*
* startup.c: Startup notification code. Ensures a startup notification context
* is setup when launching applications. We store the current
*
*/
#include "all.h"
+
#include "sd-daemon.h"
#include <sys/types.h>
#include <sys/wait.h>
+#include <paths.h>
#define SN_API_NOT_YET_FROZEN 1
#include <libsn/sn-launcher.h>
if (!sequence) {
DLOG("Sequence already deleted, nevermind.\n");
+ free(w);
return;
}
* seconds ago or earlier. */
struct Startup_Sequence *current, *next;
for (next = TAILQ_FIRST(&startup_sequences);
- next != TAILQ_END(&startup_sequences);
- ) {
+ next != TAILQ_END(&startup_sequences);) {
current = next;
next = TAILQ_NEXT(next, sequences);
}
return active_sequences;
-
}
/**
*/
void startup_sequence_delete(struct Startup_Sequence *sequence) {
assert(sequence != NULL);
- DLOG("Deleting startup sequence %s, delete_at = %ld, current_time = %ld\n",
- sequence->id, sequence->delete_at, time(NULL));
+ DLOG("Deleting startup sequence %s, delete_at = %lld, current_time = %lld\n",
+ sequence->id, (long long)sequence->delete_at, (long long)time(NULL));
/* Unref the context, will be free()d */
sn_launcher_context_unref(sequence->context);
* the application is reparented to init (process-id 1), which correctly handles
* childs, so we don’t have to do it :-).
*
- * The shell is determined by looking for the SHELL environment variable. If it
- * does not exist, /bin/sh is used.
+ * The shell used to start applications is the system's bourne shell (i.e.,
+ * /bin/sh).
*
* 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, bool no_startup_id) {
- SnLauncherContext *context;
+ SnLauncherContext *context = NULL;
if (!no_startup_id) {
/* Create a startup notification context to monitor the progress of this
free(first_word);
/* Trigger a timeout after 60 seconds */
- struct ev_timer *timeout = scalloc(sizeof(struct ev_timer));
+ struct ev_timer *timeout = scalloc(1, sizeof(struct ev_timer));
ev_timer_init(timeout, startup_timeout, 60.0, 0.);
timeout->data = context;
ev_timer_start(main_loop, timeout);
/* 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));
+ struct Startup_Sequence *sequence = scalloc(1, sizeof(struct Startup_Sequence));
sequence->id = sstrdup(sn_launcher_context_get_startup_id(context));
sequence->workspace = sstrdup(ws->name);
sequence->context = context;
}
unsetenv("LISTEN_PID");
unsetenv("LISTEN_FDS");
+ signal(SIGPIPE, SIG_DFL);
if (fork() == 0) {
/* Setup the environment variable(s) */
if (!no_startup_id)
sn_launcher_context_setup_child_process(context);
- /* Stores the path of the shell */
- static const char *shell = NULL;
-
- if (shell == NULL)
- if ((shell = getenv("SHELL")) == NULL)
- shell = "/bin/sh";
-
- /* This is the child */
- execl(shell, shell, "-c", command, (void*)NULL);
+ execl(_PATH_BSHELL, _PATH_BSHELL, "-c", command, NULL);
/* not reached */
}
_exit(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);
+ else
+ xcb_set_root_cursor(XCURSOR_CURSOR_WATCH);
}
}
/* Mark the given sequence for deletion in 30 seconds. */
time_t current_time = time(NULL);
sequence->delete_at = current_time + 30;
- DLOG("Will delete startup sequence %s at timestamp %ld\n",
- sequence->id, sequence->delete_at);
+ DLOG("Will delete startup sequence %s at timestamp %lld\n",
+ sequence->id, (long long)sequence->delete_at);
if (_prune_startup_sequences() == 0) {
DLOG("No more startup sequences running, changing root window cursor to default pointer.\n");
/* Change the pointer of the root window to indicate progress */
if (xcursor_supported)
xcursor_set_root_cursor(XCURSOR_CURSOR_POINTER);
- else xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
+ else
+ xcb_set_root_cursor(XCURSOR_CURSOR_POINTER);
}
break;
default:
}
}
+/**
+ * Renames workspaces that are mentioned in the startup sequences.
+ *
+ */
+void startup_sequence_rename_workspace(const char *old_name, const char *new_name) {
+ struct Startup_Sequence *current;
+ TAILQ_FOREACH(current, &startup_sequences, sequences) {
+ if (strcmp(current->workspace, old_name) != 0)
+ continue;
+ DLOG("Renaming workspace \"%s\" to \"%s\" in startup sequence %s.\n",
+ old_name, new_name, current->id);
+ free(current->workspace);
+ current->workspace = sstrdup(new_name);
+ }
+}
+
/**
* Gets the stored startup sequence for the _NET_STARTUP_ID of a given window.
*
*/
struct Startup_Sequence *startup_sequence_get(i3Window *cwindow,
- xcb_get_property_reply_t *startup_id_reply, bool ignore_mapped_leader) {
+ xcb_get_property_reply_t *startup_id_reply, bool ignore_mapped_leader) {
/* The _NET_STARTUP_ID is only needed during this function, so we get it
* here and don’t save it in the 'cwindow'. */
if (startup_id_reply == NULL || xcb_get_property_value_length(startup_id_reply) == 0) {
xcb_get_property_cookie_t cookie;
cookie = xcb_get_property(conn, false, cwindow->leader,
- A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
+ A__NET_STARTUP_ID, XCB_GET_PROPERTY_TYPE_ANY, 0, 512);
startup_id_reply = xcb_get_property_reply(conn, cookie, NULL);
if (startup_id_reply == NULL ||
}
char *startup_id;
- if (asprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
- (char*)xcb_get_property_value(startup_id_reply)) == -1) {
- perror("asprintf()");
- DLOG("Could not get _NET_STARTUP_ID\n");
- free(startup_id_reply);
- return NULL;
- }
-
+ sasprintf(&startup_id, "%.*s", xcb_get_property_value_length(startup_id_reply),
+ (char *)xcb_get_property_value(startup_id_reply));
struct Startup_Sequence *current, *sequence = NULL;
TAILQ_FOREACH(current, &startup_sequences, sequences) {
if (strcmp(current->id, startup_id) != 0)