summaryrefslogtreecommitdiff
path: root/wm/dwl/dwl.c
diff options
context:
space:
mode:
Diffstat (limited to 'wm/dwl/dwl.c')
-rw-r--r--wm/dwl/dwl.c101
1 files changed, 73 insertions, 28 deletions
diff --git a/wm/dwl/dwl.c b/wm/dwl/dwl.c
index 3941fb9..349f43d 100644
--- a/wm/dwl/dwl.c
+++ b/wm/dwl/dwl.c
@@ -231,6 +231,7 @@ static void arrange(Monitor *m);
static void arrangelayer(Monitor *m, struct wl_list *list,
struct wlr_box *usable_area, int exclusive);
static void arrangelayers(Monitor *m);
+static void autostartexec(void);
static void axisnotify(struct wl_listener *listener, void *data);
static void buttonpress(struct wl_listener *listener, void *data);
static void chvt(const Arg *arg);
@@ -310,6 +311,7 @@ static void setmon(Client *c, Monitor *m, unsigned int newtags);
static void setpsel(struct wl_listener *listener, void *data);
static void setsel(struct wl_listener *listener, void *data);
static void setup(void);
+static void sigchld(int unused);
static void spawn(const Arg *arg);
static void startdrag(struct wl_listener *listener, void *data);
static void tag(const Arg *arg);
@@ -413,7 +415,6 @@ static void configurex11(struct wl_listener *listener, void *data);
static void createnotifyx11(struct wl_listener *listener, void *data);
static Atom getatom(xcb_connection_t *xc, const char *name);
static void sethints(struct wl_listener *listener, void *data);
-static void sigchld(int unused);
static void xwaylandready(struct wl_listener *listener, void *data);
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
static struct wl_listener xwayland_ready = {.notify = xwaylandready};
@@ -430,6 +431,9 @@ static Atom netatom[NetLast];
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
+static pid_t *autostart_pids;
+static size_t autostart_len;
+
/* function implementations */
void
applybounds(Client *c, struct wlr_box *bbox)
@@ -571,6 +575,27 @@ arrangelayers(Monitor *m)
}
void
+autostartexec(void) {
+ const char *const *p;
+ size_t i = 0;
+
+ /* count entries */
+ for (p = autostart; *p; autostart_len++, p++)
+ while (*++p);
+
+ autostart_pids = calloc(autostart_len, sizeof(pid_t));
+ for (p = autostart; *p; i++, p++) {
+ if ((autostart_pids[i] = fork()) == 0) {
+ setsid();
+ execvp(*p, (char *const *)p);
+ die("dwl: execvp %s:", *p);
+ }
+ /* skip arguments */
+ while (*++p);
+ }
+}
+
+void
axisnotify(struct wl_listener *listener, void *data)
{
/* This event is forwarded by the cursor when a pointer emits an axis event,
@@ -669,6 +694,16 @@ checkidleinhibitor(struct wlr_surface *exclude)
void
cleanup(void)
{
+ size_t i;
+
+ /* kill child processes */
+ for (i = 0; i < autostart_len; i++) {
+ if (0 < autostart_pids[i]) {
+ kill(autostart_pids[i], SIGTERM);
+ waitpid(autostart_pids[i], NULL, 0);
+ }
+ }
+
#ifdef XWAYLAND
wlr_xwayland_destroy(xwayland);
#endif
@@ -2058,6 +2093,7 @@ run(char *startup_cmd)
die("startup: backend_start");
/* Now that the socket exists and the backend is started, run the startup command */
+ autostartexec();
if (startup_cmd) {
int piperw[2];
if (pipe(piperw) < 0)
@@ -2240,15 +2276,7 @@ void
setup(void)
{
struct sigaction sa_term = {.sa_flags = SA_RESTART, .sa_handler = quitsignal};
- struct sigaction sa_sigchld = {
-#ifdef XWAYLAND
- .sa_flags = SA_RESTART,
- .sa_handler = sigchld,
-#else
- .sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART,
- .sa_handler = SIG_IGN,
-#endif
- };
+ struct sigaction sa_sigchld = {.sa_flags = SA_RESTART, .sa_handler = sigchld};
sigemptyset(&sa_term.sa_mask);
sigemptyset(&sa_sigchld.sa_mask);
/* The Wayland display is managed by libwayland. It handles accepting
@@ -2433,6 +2461,41 @@ setup(void)
}
void
+sigchld(int unused)
+{
+ siginfo_t in;
+ /* We should be able to remove this function in favor of a simple
+ * struct sigaction sa = {.sa_handler = SIG_IGN};
+ * sigaction(SIGCHLD, &sa, NULL);
+ * but the Xwayland implementation in wlroots currently prevents us from
+ * setting our own disposition for SIGCHLD.
+ */
+ /* WNOWAIT leaves the child in a waitable state, in case this is the
+ * XWayland process
+ */
+ while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
+#ifdef XWAYLAND
+ && (!xwayland || in.si_pid != xwayland->server->pid)
+#endif
+ ) {
+ pid_t *p, *lim;
+ waitpid(in.si_pid, NULL, 0);
+ if (in.si_pid == child_pid)
+ child_pid = -1;
+ if (!(p = autostart_pids))
+ continue;
+ lim = &p[autostart_len];
+
+ for (; p < lim; p++) {
+ if (*p == in.si_pid) {
+ *p = -1;
+ break;
+ }
+ }
+ }
+}
+
+void
spawn(const Arg *arg)
{
if (fork() == 0) {
@@ -2892,24 +2955,6 @@ sethints(struct wl_listener *listener, void *data)
}
void
-sigchld(int unused)
-{
- siginfo_t in;
- /* We should be able to remove this function in favor of a simple
- * struct sigaction sa = {.sa_handler = SIG_IGN};
- * sigaction(SIGCHLD, &sa, NULL);
- * but the Xwayland implementation in wlroots currently prevents us from
- * setting our own disposition for SIGCHLD.
- */
- /* WNOWAIT leaves the child in a waitable state, in case this is the
- * XWayland process
- */
- while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid
- && (!xwayland || in.si_pid != xwayland->server->pid))
- waitpid(in.si_pid, NULL, 0);
-}
-
-void
xwaylandready(struct wl_listener *listener, void *data)
{
struct wlr_xcursor *xcursor;