Add cool auto start patch 🤖😎
This commit is contained in:
		
							parent
							
								
									05a4baef3d
								
							
						
					
					
						commit
						dc81ec5ff4
					
				
					 6 changed files with 269 additions and 91 deletions
				
			
		| 
						 | 
				
			
			@ -23,6 +23,11 @@ static const char *colors[][3]      = {
 | 
			
		|||
	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const char *const autostart[] = {
 | 
			
		||||
	"st", NULL,
 | 
			
		||||
	NULL /* terminate */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* tagging */
 | 
			
		||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,7 @@ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn()
 | 
			
		|||
static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
 | 
			
		||||
static const char *termcmd[]  = { "st", NULL };
 | 
			
		||||
 | 
			
		||||
#include "movestack.c"
 | 
			
		||||
static Key keys[] = {
 | 
			
		||||
	/* modifier                     key        function        argument */
 | 
			
		||||
	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +77,8 @@ static Key keys[] = {
 | 
			
		|||
	{ MODKEY,                       XK_d,      incnmaster,     {.i = -1 } },
 | 
			
		||||
	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
 | 
			
		||||
	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
 | 
			
		||||
	{ MODKEY|ShiftMask,             XK_j,      movestack,      {.i = +1 } },
 | 
			
		||||
	{ MODKEY|ShiftMask,             XK_k,      movestack,      {.i = -1 } },
 | 
			
		||||
	{ MODKEY,                       XK_Return, zoom,           {0} },
 | 
			
		||||
	{ MODKEY,                       XK_Tab,    view,           {0} },
 | 
			
		||||
	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								config.h
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								config.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#define WEBBROWSER		 "google-chrome-stable"
 | 
			
		||||
#define TERMINAL		 "alacritty"
 | 
			
		||||
#define SCREENSHOT		 "spectacle"
 | 
			
		||||
 | 
			
		||||
/* appearance */
 | 
			
		||||
static const unsigned int borderpx  = 1;        /* border pixel of windows */
 | 
			
		||||
static const unsigned int gappx     = 3;        /* gaps size between windows */
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,11 @@ static const char *colors[][3]      = {
 | 
			
		|||
	[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
 | 
			
		||||
	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
 | 
			
		||||
};
 | 
			
		||||
// Autostart programs
 | 
			
		||||
static const char *const autostart[] = {
 | 
			
		||||
   "st", NULL,
 | 
			
		||||
    NULL /* terminate */
 | 
			
		||||
 };
 | 
			
		||||
 | 
			
		||||
/* tagging */
 | 
			
		||||
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										58
									
								
								dwm.c
									
										
									
									
									
								
							
							
						
						
									
										58
									
								
								dwm.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -267,6 +267,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
 | 
			
		|||
static int xerrordummy(Display *dpy, XErrorEvent *ee);
 | 
			
		||||
static int xerrorstart(Display *dpy, XErrorEvent *ee);
 | 
			
		||||
static void zoom(const Arg *arg);
 | 
			
		||||
static void autostart_exec(void);
 | 
			
		||||
 | 
			
		||||
/* variables */
 | 
			
		||||
static Systray *systray = NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -319,6 +320,34 @@ struct Pertag {
 | 
			
		|||
/* compile-time check if all tags fit into an unsigned int bit array. */
 | 
			
		||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
 | 
			
		||||
 | 
			
		||||
/* dwm will keep pid's of processes from autostart array and kill them at quit */
 | 
			
		||||
static pid_t *autostart_pids;
 | 
			
		||||
static size_t autostart_len;
 | 
			
		||||
 | 
			
		||||
/* execute command from autostart array */
 | 
			
		||||
static void
 | 
			
		||||
autostart_exec() {
 | 
			
		||||
	const char *const *p;
 | 
			
		||||
	size_t i = 0;
 | 
			
		||||
 | 
			
		||||
	/* count entries */
 | 
			
		||||
	for (p = autostart; *p; autostart_len++, p++)
 | 
			
		||||
		while (*++p);
 | 
			
		||||
 | 
			
		||||
	autostart_pids = malloc(autostart_len * sizeof(pid_t));
 | 
			
		||||
	for (p = autostart; *p; i++, p++) {
 | 
			
		||||
		if ((autostart_pids[i] = fork()) == 0) {
 | 
			
		||||
			setsid();
 | 
			
		||||
			execvp(*p, (char *const *)p);
 | 
			
		||||
			fprintf(stderr, "dwm: execvp %s\n", *p);
 | 
			
		||||
			perror(" failed");
 | 
			
		||||
			_exit(EXIT_FAILURE);
 | 
			
		||||
		}
 | 
			
		||||
		/* skip arguments */
 | 
			
		||||
		while (*++p);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* function implementations */
 | 
			
		||||
void
 | 
			
		||||
applyrules(Client *c)
 | 
			
		||||
| 
						 | 
				
			
			@ -1420,6 +1449,16 @@ propertynotify(XEvent *e)
 | 
			
		|||
void
 | 
			
		||||
quit(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	running = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1870,9 +1909,25 @@ showhide(Client *c)
 | 
			
		|||
void
 | 
			
		||||
sigchld(int unused)
 | 
			
		||||
{
 | 
			
		||||
	pid_t pid;
 | 
			
		||||
 | 
			
		||||
	if (signal(SIGCHLD, sigchld) == SIG_ERR)
 | 
			
		||||
		die("can't install SIGCHLD handler:");
 | 
			
		||||
	while (0 < waitpid(-1, NULL, WNOHANG));
 | 
			
		||||
	while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
 | 
			
		||||
		pid_t *p, *lim;
 | 
			
		||||
 | 
			
		||||
		if (!(p = autostart_pids))
 | 
			
		||||
			continue;
 | 
			
		||||
		lim = &p[autostart_len];
 | 
			
		||||
 | 
			
		||||
		for (; p < lim; p++) {
 | 
			
		||||
			if (*p == pid) {
 | 
			
		||||
				*p = -1;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
| 
						 | 
				
			
			@ -2596,6 +2651,7 @@ main(int argc, char *argv[])
 | 
			
		|||
	if (!(dpy = XOpenDisplay(NULL)))
 | 
			
		||||
		die("dwm: cannot open display");
 | 
			
		||||
	checkotherwm();
 | 
			
		||||
	autostart_exec();
 | 
			
		||||
	setup();
 | 
			
		||||
#ifdef __OpenBSD__
 | 
			
		||||
	if (pledge("stdio rpath proc exec", NULL) == -1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										172
									
								
								dwm.c.orig
									
										
									
									
									
								
							
							
						
						
									
										172
									
								
								dwm.c.orig
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -29,7 +29,6 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <X11/cursorfont.h>
 | 
			
		||||
#include <X11/keysym.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -127,6 +126,7 @@ typedef struct {
 | 
			
		|||
	void (*arrange)(Monitor *);
 | 
			
		||||
} Layout;
 | 
			
		||||
 | 
			
		||||
typedef struct Pertag Pertag;
 | 
			
		||||
struct Monitor {
 | 
			
		||||
	char ltsymbol[16];
 | 
			
		||||
	float mfact;
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +146,7 @@ struct Monitor {
 | 
			
		|||
	Monitor *next;
 | 
			
		||||
	Window barwin;
 | 
			
		||||
	const Layout *lt[2];
 | 
			
		||||
	Pertag *pertag;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -220,7 +221,6 @@ static void resizemouse(const Arg *arg);
 | 
			
		|||
static void resizerequest(XEvent *e);
 | 
			
		||||
static void restack(Monitor *m);
 | 
			
		||||
static void run(void);
 | 
			
		||||
static void runautostart(void);
 | 
			
		||||
static void scan(void);
 | 
			
		||||
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
 | 
			
		||||
static void sendmon(Client *c, Monitor *m);
 | 
			
		||||
| 
						 | 
				
			
			@ -270,11 +270,7 @@ static void zoom(const Arg *arg);
 | 
			
		|||
 | 
			
		||||
/* variables */
 | 
			
		||||
static Systray *systray = NULL;
 | 
			
		||||
static const char autostartblocksh[] = "autostart_blocking.sh";
 | 
			
		||||
static const char autostartsh[] = "autostart.sh";
 | 
			
		||||
static const char broken[] = "broken";
 | 
			
		||||
static const char dwmdir[] = "dwm";
 | 
			
		||||
static const char localshare[] = ".local/share";
 | 
			
		||||
static char stext[256];
 | 
			
		||||
static int screen;
 | 
			
		||||
static int sw, sh;           /* X display screen geometry width, height */
 | 
			
		||||
| 
						 | 
				
			
			@ -311,6 +307,15 @@ static Window root, wmcheckwin;
 | 
			
		|||
/* configuration, allows nested code to access above variables */
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
struct Pertag {
 | 
			
		||||
	unsigned int curtag, prevtag; /* current and previous tag */
 | 
			
		||||
	int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */
 | 
			
		||||
	float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */
 | 
			
		||||
	unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */
 | 
			
		||||
	const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes  */
 | 
			
		||||
	int showbars[LENGTH(tags) + 1]; /* display bar for the current tag */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* compile-time check if all tags fit into an unsigned int bit array. */
 | 
			
		||||
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -730,6 +735,7 @@ Monitor *
 | 
			
		|||
createmon(void)
 | 
			
		||||
{
 | 
			
		||||
	Monitor *m;
 | 
			
		||||
	unsigned int i;
 | 
			
		||||
 | 
			
		||||
	m = ecalloc(1, sizeof(Monitor));
 | 
			
		||||
	m->tagset[0] = m->tagset[1] = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -740,6 +746,20 @@ createmon(void)
 | 
			
		|||
	m->lt[0] = &layouts[0];
 | 
			
		||||
	m->lt[1] = &layouts[1 % LENGTH(layouts)];
 | 
			
		||||
	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
 | 
			
		||||
	m->pertag = ecalloc(1, sizeof(Pertag));
 | 
			
		||||
	m->pertag->curtag = m->pertag->prevtag = 1;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i <= LENGTH(tags); i++) {
 | 
			
		||||
		m->pertag->nmasters[i] = m->nmaster;
 | 
			
		||||
		m->pertag->mfacts[i] = m->mfact;
 | 
			
		||||
 | 
			
		||||
		m->pertag->ltidxs[i][0] = m->lt[0];
 | 
			
		||||
		m->pertag->ltidxs[i][1] = m->lt[1];
 | 
			
		||||
		m->pertag->sellts[i] = m->sellt;
 | 
			
		||||
 | 
			
		||||
		m->pertag->showbars[i] = m->showbar;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1098,7 +1118,7 @@ grabkeys(void)
 | 
			
		|||
void
 | 
			
		||||
incnmaster(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
 | 
			
		||||
	selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
 | 
			
		||||
	arrange(selmon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1566,83 +1586,6 @@ run(void)
 | 
			
		|||
			handler[ev.type](&ev); /* call handler */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
runautostart(void)
 | 
			
		||||
{
 | 
			
		||||
	char *pathpfx;
 | 
			
		||||
	char *path;
 | 
			
		||||
	char *xdgdatahome;
 | 
			
		||||
	char *home;
 | 
			
		||||
	struct stat sb;
 | 
			
		||||
 | 
			
		||||
	if ((home = getenv("HOME")) == NULL)
 | 
			
		||||
		/* this is almost impossible */
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	/* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm,
 | 
			
		||||
	 * otherwise use ~/.local/share/dwm as autostart script directory
 | 
			
		||||
	 */
 | 
			
		||||
	xdgdatahome = getenv("XDG_DATA_HOME");
 | 
			
		||||
	if (xdgdatahome != NULL && *xdgdatahome != '\0') {
 | 
			
		||||
		/* space for path segments, separators and nul */
 | 
			
		||||
		pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2);
 | 
			
		||||
 | 
			
		||||
		if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
 | 
			
		||||
			free(pathpfx);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		/* space for path segments, separators and nul */
 | 
			
		||||
		pathpfx = ecalloc(1, strlen(home) + strlen(localshare)
 | 
			
		||||
		                     + strlen(dwmdir) + 3);
 | 
			
		||||
 | 
			
		||||
		if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
 | 
			
		||||
			free(pathpfx);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* check if the autostart script directory exists */
 | 
			
		||||
	if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
 | 
			
		||||
		/* the XDG conformant path does not exist or is no directory
 | 
			
		||||
		 * so we try ~/.dwm instead
 | 
			
		||||
		 */
 | 
			
		||||
		char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3);
 | 
			
		||||
		if(pathpfx_new == NULL) {
 | 
			
		||||
			free(pathpfx);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		pathpfx = pathpfx_new;
 | 
			
		||||
 | 
			
		||||
		if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
 | 
			
		||||
			free(pathpfx);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* try the blocking script first */
 | 
			
		||||
	path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2);
 | 
			
		||||
	if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
 | 
			
		||||
		free(path);
 | 
			
		||||
		free(pathpfx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (access(path, X_OK) == 0)
 | 
			
		||||
		system(path);
 | 
			
		||||
 | 
			
		||||
	/* now the non-blocking script */
 | 
			
		||||
	if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
 | 
			
		||||
		free(path);
 | 
			
		||||
		free(pathpfx);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (access(path, X_OK) == 0)
 | 
			
		||||
		system(strcat(path, " &"));
 | 
			
		||||
 | 
			
		||||
	free(pathpfx);
 | 
			
		||||
	free(path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
scan(void)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1788,9 +1731,9 @@ void
 | 
			
		|||
setlayout(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
 | 
			
		||||
		selmon->sellt ^= 1;
 | 
			
		||||
		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
 | 
			
		||||
	if (arg && arg->v)
 | 
			
		||||
		selmon->lt[selmon->sellt] = (Layout *)arg->v;
 | 
			
		||||
		selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
 | 
			
		||||
	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
 | 
			
		||||
	if (selmon->sel)
 | 
			
		||||
		arrange(selmon);
 | 
			
		||||
| 
						 | 
				
			
			@ -1809,7 +1752,7 @@ setmfact(const Arg *arg)
 | 
			
		|||
	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
 | 
			
		||||
	if (f < 0.05 || f > 0.95)
 | 
			
		||||
		return;
 | 
			
		||||
	selmon->mfact = f;
 | 
			
		||||
	selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
 | 
			
		||||
	arrange(selmon);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1997,7 +1940,7 @@ tile(Monitor *m)
 | 
			
		|||
void
 | 
			
		||||
togglebar(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	selmon->showbar = !selmon->showbar;
 | 
			
		||||
	selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
 | 
			
		||||
	updatebarpos(selmon);
 | 
			
		||||
	resizebarwin(selmon);
 | 
			
		||||
	if (showsystray) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2047,9 +1990,33 @@ void
 | 
			
		|||
toggleview(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	if (newtagset) {
 | 
			
		||||
		selmon->tagset[selmon->seltags] = newtagset;
 | 
			
		||||
 | 
			
		||||
		if (newtagset == ~0) {
 | 
			
		||||
			selmon->pertag->prevtag = selmon->pertag->curtag;
 | 
			
		||||
			selmon->pertag->curtag = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* test if the user did not select the same tag */
 | 
			
		||||
		if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
 | 
			
		||||
			selmon->pertag->prevtag = selmon->pertag->curtag;
 | 
			
		||||
			for (i = 0; !(newtagset & 1 << i); i++) ;
 | 
			
		||||
			selmon->pertag->curtag = i + 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* apply settings for this view */
 | 
			
		||||
		selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
 | 
			
		||||
		selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
 | 
			
		||||
		selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
 | 
			
		||||
		selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
 | 
			
		||||
		selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
 | 
			
		||||
 | 
			
		||||
		if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
 | 
			
		||||
			togglebar(NULL);
 | 
			
		||||
 | 
			
		||||
		focus(NULL);
 | 
			
		||||
		arrange(selmon);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -2476,11 +2443,37 @@ updatewmhints(Client *c)
 | 
			
		|||
void
 | 
			
		||||
view(const Arg *arg)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	unsigned int tmptag;
 | 
			
		||||
 | 
			
		||||
	if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
 | 
			
		||||
		return;
 | 
			
		||||
	selmon->seltags ^= 1; /* toggle sel tagset */
 | 
			
		||||
	if (arg->ui & TAGMASK)
 | 
			
		||||
	if (arg->ui & TAGMASK) {
 | 
			
		||||
		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
 | 
			
		||||
		selmon->pertag->prevtag = selmon->pertag->curtag;
 | 
			
		||||
 | 
			
		||||
		if (arg->ui == ~0)
 | 
			
		||||
			selmon->pertag->curtag = 0;
 | 
			
		||||
		else {
 | 
			
		||||
			for (i = 0; !(arg->ui & 1 << i); i++) ;
 | 
			
		||||
			selmon->pertag->curtag = i + 1;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		tmptag = selmon->pertag->prevtag;
 | 
			
		||||
		selmon->pertag->prevtag = selmon->pertag->curtag;
 | 
			
		||||
		selmon->pertag->curtag = tmptag;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
 | 
			
		||||
	selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
 | 
			
		||||
	selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
 | 
			
		||||
	selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
 | 
			
		||||
	selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
 | 
			
		||||
 | 
			
		||||
	if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
 | 
			
		||||
		togglebar(NULL);
 | 
			
		||||
 | 
			
		||||
	focus(NULL);
 | 
			
		||||
	arrange(selmon);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2609,7 +2602,6 @@ main(int argc, char *argv[])
 | 
			
		|||
		die("pledge");
 | 
			
		||||
#endif /* __OpenBSD__ */
 | 
			
		||||
	scan();
 | 
			
		||||
	runautostart();
 | 
			
		||||
	run();
 | 
			
		||||
	cleanup();
 | 
			
		||||
	XCloseDisplay(dpy);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										116
									
								
								patches/dwm-cool-autostart-6.2.diff
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								patches/dwm-cool-autostart-6.2.diff
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,116 @@
 | 
			
		|||
diff --git a/config.def.h b/config.def.h
 | 
			
		||||
index 1c0b587..ed056a4 100644
 | 
			
		||||
--- a/config.def.h
 | 
			
		||||
+++ b/config.def.h
 | 
			
		||||
@@ -18,6 +18,11 @@ static const char *colors[][3]      = {
 | 
			
		||||
 	[SchemeSel]  = { col_gray4, col_cyan,  col_cyan  },
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static const char *const autostart[] = {
 | 
			
		||||
+	"st", NULL,
 | 
			
		||||
+	NULL /* terminate */
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 /* tagging */
 | 
			
		||||
 static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
 | 
			
		||||
 
 | 
			
		||||
diff --git a/dwm.c b/dwm.c
 | 
			
		||||
index 9fd0286..1facd56 100644
 | 
			
		||||
--- a/dwm.c
 | 
			
		||||
+++ b/dwm.c
 | 
			
		||||
@@ -234,6 +234,7 @@ static int xerror(Display *dpy, XErrorEvent *ee);
 | 
			
		||||
 static int xerrordummy(Display *dpy, XErrorEvent *ee);
 | 
			
		||||
 static int xerrorstart(Display *dpy, XErrorEvent *ee);
 | 
			
		||||
 static void zoom(const Arg *arg);
 | 
			
		||||
+static void autostart_exec(void);
 | 
			
		||||
 
 | 
			
		||||
 /* variables */
 | 
			
		||||
 static const char broken[] = "broken";
 | 
			
		||||
@@ -275,6 +276,34 @@ static Window root, wmcheckwin;
 | 
			
		||||
 /* compile-time check if all tags fit into an unsigned int bit array. */
 | 
			
		||||
 struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
 | 
			
		||||
 
 | 
			
		||||
+/* dwm will keep pid's of processes from autostart array and kill them at quit */
 | 
			
		||||
+static pid_t *autostart_pids;
 | 
			
		||||
+static size_t autostart_len;
 | 
			
		||||
+
 | 
			
		||||
+/* execute command from autostart array */
 | 
			
		||||
+static void
 | 
			
		||||
+autostart_exec() {
 | 
			
		||||
+	const char *const *p;
 | 
			
		||||
+	size_t i = 0;
 | 
			
		||||
+
 | 
			
		||||
+	/* count entries */
 | 
			
		||||
+	for (p = autostart; *p; autostart_len++, p++)
 | 
			
		||||
+		while (*++p);
 | 
			
		||||
+
 | 
			
		||||
+	autostart_pids = malloc(autostart_len * sizeof(pid_t));
 | 
			
		||||
+	for (p = autostart; *p; i++, p++) {
 | 
			
		||||
+		if ((autostart_pids[i] = fork()) == 0) {
 | 
			
		||||
+			setsid();
 | 
			
		||||
+			execvp(*p, (char *const *)p);
 | 
			
		||||
+			fprintf(stderr, "dwm: execvp %s\n", *p);
 | 
			
		||||
+			perror(" failed");
 | 
			
		||||
+			_exit(EXIT_FAILURE);
 | 
			
		||||
+		}
 | 
			
		||||
+		/* skip arguments */
 | 
			
		||||
+		while (*++p);
 | 
			
		||||
+	}
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /* function implementations */
 | 
			
		||||
 void
 | 
			
		||||
 applyrules(Client *c)
 | 
			
		||||
@@ -1249,6 +1278,16 @@ propertynotify(XEvent *e)
 | 
			
		||||
 void
 | 
			
		||||
 quit(const Arg *arg)
 | 
			
		||||
 {
 | 
			
		||||
+	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);
 | 
			
		||||
+		}
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	running = 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
@@ -1632,9 +1671,25 @@ showhide(Client *c)
 | 
			
		||||
 void
 | 
			
		||||
 sigchld(int unused)
 | 
			
		||||
 {
 | 
			
		||||
+	pid_t pid;
 | 
			
		||||
+
 | 
			
		||||
 	if (signal(SIGCHLD, sigchld) == SIG_ERR)
 | 
			
		||||
 		die("can't install SIGCHLD handler:");
 | 
			
		||||
-	while (0 < waitpid(-1, NULL, WNOHANG));
 | 
			
		||||
+	while (0 < (pid = waitpid(-1, NULL, WNOHANG))) {
 | 
			
		||||
+		pid_t *p, *lim;
 | 
			
		||||
+
 | 
			
		||||
+		if (!(p = autostart_pids))
 | 
			
		||||
+			continue;
 | 
			
		||||
+		lim = &p[autostart_len];
 | 
			
		||||
+
 | 
			
		||||
+		for (; p < lim; p++) {
 | 
			
		||||
+			if (*p == pid) {
 | 
			
		||||
+				*p = -1;
 | 
			
		||||
+				break;
 | 
			
		||||
+			}
 | 
			
		||||
+		}
 | 
			
		||||
+
 | 
			
		||||
+	}
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void
 | 
			
		||||
@@ -2139,6 +2194,7 @@ main(int argc, char *argv[])
 | 
			
		||||
 	if (!(dpy = XOpenDisplay(NULL)))
 | 
			
		||||
 		die("dwm: cannot open display");
 | 
			
		||||
 	checkotherwm();
 | 
			
		||||
+	autostart_exec();
 | 
			
		||||
 	setup();
 | 
			
		||||
 #ifdef __OpenBSD__
 | 
			
		||||
 	if (pledge("stdio rpath proc exec", NULL) == -1)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue