1 From 37e970479dc5d40e57fc0cbfeaa5e39941483237 Mon Sep 17 00:00:00 2001 2 From: Gan Ainm <gan.ainm.riomhphost@gmail.com> 3 Date: Wed, 10 Jun 2020 10:59:02 +0000 4 Subject: [PATCH] dwm-xdgautostart-6.2.diff 5 6 =================================================================== 7 --- 8 dwm.1 | 23 +++++++++++++++++ 9 dwm.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 10 2 files changed, 105 insertions(+) 11 12 diff --git a/dwm.1 b/dwm.1 13 index 13b3729..9533aa6 100644 14 --- a/dwm.1 15 +++ b/dwm.1 16 @@ -30,6 +30,14 @@ top left corner. The tags which are applied to one or more windows are 17 indicated with an empty square in the top left corner. 18 .P 19 dwm draws a small border around windows to indicate the focus state. 20 +.P 21 +On start, dwm can start additional programs that may be specified in two special 22 +shell scripts (see the FILES section below), autostart_blocking.sh and 23 +autostart.sh. The former is executed first and dwm will wait for its 24 +termination before starting. The latter is executed in the background before 25 +dwm enters its handler loop. 26 +.P 27 +Either of these files may be omitted. 28 .SH OPTIONS 29 .TP 30 .B \-v 31 @@ -152,6 +160,21 @@ Toggles focused window between floating and tiled state. 32 .TP 33 .B Mod1\-Button3 34 Resize focused window while dragging. Tiled windows will be toggled to the floating state. 35 +.SH FILES 36 +The files containing programs to be started along with dwm are searched for in 37 +the following directories: 38 +.IP "1. $XDG_DATA_HOME/dwm" 39 +.IP "2. $HOME/.local/share/dwm" 40 +.IP "3. $HOME/.dwm" 41 +.P 42 +The first existing directory is scanned for any of the autostart files below. 43 +.TP 15 44 +autostart.sh 45 +This file is started as a shell background process before dwm enters its handler 46 +loop. 47 +.TP 15 48 +autostart_blocking.sh 49 +This file is started before any autostart.sh; dwm waits for its termination. 50 .SH CUSTOMIZATION 51 dwm is customized by creating a custom config.h and (re)compiling the source 52 code. This keeps it fast, secure and simple. 53 diff --git a/dwm.c b/dwm.c 54 index 4465af1..2156b49 100644 55 --- a/dwm.c 56 +++ b/dwm.c 57 @@ -29,6 +29,7 @@ 58 #include <string.h> 59 #include <unistd.h> 60 #include <sys/types.h> 61 +#include <sys/stat.h> 62 #include <sys/wait.h> 63 #include <X11/cursorfont.h> 64 #include <X11/keysym.h> 65 @@ -193,6 +194,7 @@ static void resizeclient(Client *c, int x, int y, int w, int h); 66 static void resizemouse(const Arg *arg); 67 static void restack(Monitor *m); 68 static void run(void); 69 +static void runautostart(void); 70 static void scan(void); 71 static int sendevent(Client *c, Atom proto); 72 static void sendmon(Client *c, Monitor *m); 73 @@ -235,7 +237,11 @@ static int xerrorstart(Display *dpy, XErrorEvent *ee); 74 static void zoom(const Arg *arg); 75 76 /* variables */ 77 +static const char autostartblocksh[] = "autostart_blocking.sh"; 78 +static const char autostartsh[] = "autostart.sh"; 79 static const char broken[] = "broken"; 80 +static const char dwmdir[] = "dwm"; 81 +static const char localshare[] = ".local/share"; 82 static char stext[256]; 83 static int screen; 84 static int sw, sh; /* X display screen geometry width, height */ 85 @@ -1380,6 +1386,83 @@ run(void) 86 handler[ev.type](&ev); /* call handler */ 87 } 88 89 +void 90 +runautostart(void) 91 +{ 92 + char *pathpfx; 93 + char *path; 94 + char *xdgdatahome; 95 + char *home; 96 + struct stat sb; 97 + 98 + if ((home = getenv("HOME")) == NULL) 99 + /* this is almost impossible */ 100 + return; 101 + 102 + /* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm, 103 + * otherwise use ~/.local/share/dwm as autostart script directory 104 + */ 105 + xdgdatahome = getenv("XDG_DATA_HOME"); 106 + if (xdgdatahome != NULL && *xdgdatahome != '\0') { 107 + /* space for path segments, separators and nul */ 108 + pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2); 109 + 110 + if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) { 111 + free(pathpfx); 112 + return; 113 + } 114 + } else { 115 + /* space for path segments, separators and nul */ 116 + pathpfx = ecalloc(1, strlen(home) + strlen(localshare) 117 + + strlen(dwmdir) + 3); 118 + 119 + if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) { 120 + free(pathpfx); 121 + return; 122 + } 123 + } 124 + 125 + /* check if the autostart script directory exists */ 126 + if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) { 127 + /* the XDG conformant path does not exist or is no directory 128 + * so we try ~/.dwm instead 129 + */ 130 + char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3); 131 + if(pathpfx_new == NULL) { 132 + free(pathpfx); 133 + return; 134 + } 135 + pathpfx = pathpfx_new; 136 + 137 + if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) { 138 + free(pathpfx); 139 + return; 140 + } 141 + } 142 + 143 + /* try the blocking script first */ 144 + path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2); 145 + if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) { 146 + free(path); 147 + free(pathpfx); 148 + } 149 + 150 + if (access(path, X_OK) == 0) 151 + system(path); 152 + 153 + /* now the non-blocking script */ 154 + if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) { 155 + free(path); 156 + free(pathpfx); 157 + } 158 + 159 + if (access(path, X_OK) == 0) 160 + system(strcat(path, " &")); 161 + 162 + free(pathpfx); 163 + free(path); 164 +} 165 + 166 void 167 scan(void) 168 { 169 @@ -2142,6 +2223,7 @@ main(int argc, char *argv[]) 170 die("pledge"); 171 #endif /* __OpenBSD__ */ 172 scan(); 173 + runautostart(); 174 run(); 175 cleanup(); 176 XCloseDisplay(dpy); 177 -- 178 2.27.0 179