diff --git a/config.def.h b/config.def.h index 6c2e7f2..1fa074d 100644 --- a/config.def.h +++ b/config.def.h @@ -5,7 +5,7 @@ static const unsigned int borderpx = 1; /* border pixel of windows */ static const unsigned int snap = 32; /* snap pixel */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ -static const char *fonts[] = { "monospace:size=10" }; +static const char *fonts[] = { "JetBrainsMono Nerd Font:size=12" }; static const char dmenufont[] = "monospace:size=10"; static const char col_gray1[] = "#222222"; static const char col_gray2[] = "#444444"; @@ -18,6 +18,12 @@ 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" }; @@ -63,7 +69,9 @@ static const char *rofi[] = {"rofi", "-show", "drun", "-show-emojis", NULL}; static const char *browser[] = {"brave"}; static const char *termcmd[] = { "st", NULL }; static const char *alatty[] = {"alacritty", NULL}; +static const char *fileman[] = {"thunar", NULL}; +#include "selfrestart.c" static const Key keys[] = { /* modifier key function argument */ { MODKEY, XK_p, spawn, {.v = rofi } }, @@ -71,6 +79,7 @@ static const Key keys[] = { { MODKEY|ControlMask, XK_Return, spawn, {.v = alatty } }, { MODKEY, XK_b, togglebar, {0} }, { MODKEY|ShiftMask, XK_b, spawn, {.v = browser } }, + { MODKEY|ShiftMask, XK_f, spawn, {.v = fileman } }, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, @@ -100,6 +109,7 @@ static const Key keys[] = { TAGKEYS( XK_7, 6) TAGKEYS( XK_8, 7) TAGKEYS( XK_9, 8) + { MODKEY|Mod1Mask, XK_r, self_restart, {0} }, { MODKEY|ShiftMask, XK_q, quit, {0} }, }; @@ -119,4 +129,3 @@ static const Button buttons[] = { { ClkTagBar, MODKEY, Button1, tag, {0} }, { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; - diff --git a/drw.o b/drw.o new file mode 100644 index 0000000..833480a Binary files /dev/null and b/drw.o differ diff --git a/dwm b/dwm new file mode 100755 index 0000000..a4df7b5 Binary files /dev/null and b/dwm differ diff --git a/dwm.c b/dwm.c index 4f345ee..51de970 100644 --- a/dwm.c +++ b/dwm.c @@ -232,6 +232,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"; @@ -273,6 +274,36 @@ 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) @@ -1257,6 +1288,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; } @@ -1542,6 +1583,7 @@ setup(void) XSetWindowAttributes wa; Atom utf8string; struct sigaction sa; + pid_t pid; /* do not transform children into zombies when they terminate */ sigemptyset(&sa.sa_mask); @@ -1550,7 +1592,21 @@ setup(void) sigaction(SIGCHLD, &sa, NULL); /* clean up any zombies (inherited from .xinitrc etc) immediately */ - while (waitpid(-1, NULL, WNOHANG) > 0); + 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; + } + } + + } /* init screen */ screen = DefaultScreen(dpy); @@ -2151,6 +2207,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) diff --git a/dwm.o b/dwm.o new file mode 100644 index 0000000..5109bdb Binary files /dev/null and b/dwm.o differ diff --git a/dwm_time b/dwm_time new file mode 100755 index 0000000..3f2aaeb Binary files /dev/null and b/dwm_time differ diff --git a/patches/dwm-cool_autostart-6.5.diff b/patches/dwm-cool_autostart-6.5.diff new file mode 100644 index 0000000..22b6ecd --- /dev/null +++ b/patches/dwm-cool_autostart-6.5.diff @@ -0,0 +1,121 @@ +diff --git a/config.def.h b/config.def.h +index 9efa774..aba210d 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 f1d86b2..3ce99fc 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -233,6 +233,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"; +@@ -274,6 +275,36 @@ 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) +@@ -1258,6 +1289,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; + } + +@@ -1543,6 +1584,7 @@ setup(void) + XSetWindowAttributes wa; + Atom utf8string; + struct sigaction sa; ++ pid_t pid; + + /* do not transform children into zombies when they terminate */ + sigemptyset(&sa.sa_mask); +@@ -1551,7 +1593,21 @@ setup(void) + sigaction(SIGCHLD, &sa, NULL); + + /* clean up any zombies (inherited from .xinitrc etc) immediately */ +- while (waitpid(-1, NULL, WNOHANG) > 0); ++ 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; ++ } ++ } ++ ++ } + + /* init screen */ + screen = DefaultScreen(dpy); +@@ -2152,6 +2208,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) diff --git a/patches/dwm-r1615-selfrestart.diff b/patches/dwm-r1615-selfrestart.diff new file mode 100644 index 0000000..8627003 --- /dev/null +++ b/patches/dwm-r1615-selfrestart.diff @@ -0,0 +1,100 @@ +# HG changeset patch +# User Barbu Paul - Gheorghe +# Date 1354650884 -7200 +# Node ID 6c472a21a5887c5295a331c48c4da188ec2c8413 +# Parent aaab44133a6830c9a00263731d098c01cc1d6fb5 +selfrestart now magically locates the current dwm (no need to hardcode a path) + +diff -r aaab44133a68 -r 6c472a21a588 config.def.h +--- a/config.def.h Tue Dec 04 21:54:44 2012 +0200 ++++ b/config.def.h Tue Dec 04 21:54:44 2012 +0200 +@@ -54,5 +54,7 @@ + static const char *termcmd[] = { "st", NULL }; + static const char *alatty[] = {"alacritty", NULL}; ++#include "selfrestart.c" ++ + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_p, spawn, {.v = rofi } }, +@@ -89,6 +91,7 @@ + TAGKEYS( XK_7, 6) + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) ++ { MODKEY|ShiftMask, XK_r, self_restart, {0} }, + { MODKEY|ShiftMask, XK_q, quit, {0} }, + }; + +@@ -108,4 +111,3 @@ + { ClkTagBar, MODKEY, Button1, tag, {0} }, + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; +- +diff -r aaab44133a68 -r 6c472a21a588 selfrestart.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/selfrestart.c Tue Dec 04 21:54:44 2012 +0200 +@@ -0,0 +1,65 @@ ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ * Magically finds the current's executable path ++ * ++ * I'm doing the do{}while(); trick because Linux (what I'm running) is not ++ * POSIX compilant and so lstat() cannot be trusted on /proc entries ++ * ++ * @return char* the path of the current executable ++ */ ++char *get_dwm_path(){ ++ struct stat s; ++ int r, length, rate = 42; ++ char *path = NULL; ++ ++ if(lstat("/proc/self/exe", &s) == -1){ ++ perror("lstat:"); ++ return NULL; ++ } ++ ++ length = s.st_size + 1 - rate; ++ ++ do{ ++ length+=rate; ++ ++ free(path); ++ path = malloc(sizeof(char) * length); ++ ++ if(path == NULL){ ++ perror("malloc:"); ++ return NULL; ++ } ++ ++ r = readlink("/proc/self/exe", path, length); ++ ++ if(r == -1){ ++ perror("readlink:"); ++ return NULL; ++ } ++ }while(r >= length); ++ ++ path[r] = '\0'; ++ ++ return path; ++} ++ ++/** ++ * self-restart ++ * ++ * Initially inspired by: Yu-Jie Lin ++ * https://sites.google.com/site/yjlnotes/notes/dwm ++ */ ++void self_restart(const Arg *arg) { ++ char *const argv[] = {get_dwm_path(), NULL}; ++ ++ if(argv[0] == NULL){ ++ return; ++ } ++ ++ execv(argv[0], argv); ++} diff --git a/patches/dwm-restartsig-20180523-6.2.diff b/patches/dwm-restartsig-20180523-6.2.diff new file mode 100644 index 0000000..f1f8680 --- /dev/null +++ b/patches/dwm-restartsig-20180523-6.2.diff @@ -0,0 +1,139 @@ +From 2991f37f0aaf44b9f9b11e7893ff0af8eb88f649 Mon Sep 17 00:00:00 2001 +From: Christopher Drelich +Date: Wed, 23 May 2018 22:50:38 -0400 +Subject: [PATCH] Modifies quit to handle restarts and adds SIGHUP and SIGTERM + handlers. + +Modified quit() to restart if it receives arg .i = 1 +MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that. + +Signal handlers were handled for SIGHUP and SIGTERM. +If dwm receives these signals it calls quit() with +arg .i = to 1 or 0, respectively. + +To restart dwm: +MOD+CTRL+SHIFT+Q +or +kill -HUP dwmpid + +To quit dwm cleanly: +MOD+SHIFT+Q +or +kill -TERM dwmpid +--- + config.def.h | 1 + + dwm.1 | 10 ++++++++++ + dwm.c | 22 ++++++++++++++++++++++ + 3 files changed, 33 insertions(+) + +diff --git a/config.def.h b/config.def.h +index a9ac303..e559429 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -94,6 +94,7 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} }, + }; + + /* button definitions */ +diff --git a/dwm.1 b/dwm.1 +index 13b3729..36a331c 100644 +--- a/dwm.1 ++++ b/dwm.1 +@@ -142,6 +142,9 @@ Add/remove all windows with nth tag to/from the view. + .TP + .B Mod1\-Shift\-q + Quit dwm. ++.TP ++.B Mod1\-Control\-Shift\-q ++Restart dwm. + .SS Mouse commands + .TP + .B Mod1\-Button1 +@@ -155,6 +158,13 @@ Resize focused window while dragging. Tiled windows will be toggled to the float + .SH CUSTOMIZATION + dwm is customized by creating a custom config.h and (re)compiling the source + code. This keeps it fast, secure and simple. ++.SH SIGNALS ++.TP ++.B SIGHUP - 1 ++Restart the dwm process. ++.TP ++.B SIGTERM - 15 ++Cleanly terminate the dwm process. + .SH SEE ALSO + .BR dmenu (1), + .BR st (1) +diff --git a/dwm.c b/dwm.c +index bb95e26..286eecd 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -205,6 +205,8 @@ static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); ++static void sighup(int unused); ++static void sigterm(int unused); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -260,6 +262,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { + [UnmapNotify] = unmapnotify + }; + static Atom wmatom[WMLast], netatom[NetLast]; ++static int restart = 0; + static int running = 1; + static Cur *cursor[CurLast]; + static Clr **scheme; +@@ -1248,6 +1251,7 @@ propertynotify(XEvent *e) + void + quit(const Arg *arg) + { ++ if(arg->i) restart = 1; + running = 0; + } + +@@ -1536,6 +1540,9 @@ setup(void) + /* clean up any zombies immediately */ + sigchld(0); + ++ signal(SIGHUP, sighup); ++ signal(SIGTERM, sigterm); ++ + /* init screen */ + screen = DefaultScreen(dpy); + sw = DisplayWidth(dpy, screen); +@@ -1637,6 +1644,20 @@ sigchld(int unused) + } + + void ++sighup(int unused) ++{ ++ Arg a = {.i = 1}; ++ quit(&a); ++} ++ ++void ++sigterm(int unused) ++{ ++ Arg a = {.i = 0}; ++ quit(&a); ++} ++ ++void + spawn(const Arg *arg) + { + if (arg->v == dmenucmd) +@@ -2139,6 +2160,7 @@ main(int argc, char *argv[]) + setup(); + scan(); + run(); ++ if(restart) execvp(argv[0], argv); + cleanup(); + XCloseDisplay(dpy); + return EXIT_SUCCESS; +-- +2.7.4 + diff --git a/selfrestart.c b/selfrestart.c new file mode 100644 index 0000000..d695d48 --- /dev/null +++ b/selfrestart.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +/** + * Magically finds the current's executable path + * + * I'm doing the do{}while(); trick because Linux (what I'm running) is not + * POSIX compilant and so lstat() cannot be trusted on /proc entries + * + * @return char* the path of the current executable + */ +char *get_dwm_path(){ + struct stat s; + int r, length, rate = 42; + char *path = NULL; + + if(lstat("/proc/self/exe", &s) == -1){ + perror("lstat:"); + return NULL; + } + + length = s.st_size + 1 - rate; + + do{ + length+=rate; + + free(path); + path = malloc(sizeof(char) * length); + + if(path == NULL){ + perror("malloc:"); + return NULL; + } + + r = readlink("/proc/self/exe", path, length); + + if(r == -1){ + perror("readlink:"); + return NULL; + } + }while(r >= length); + + path[r] = '\0'; + + return path; +} + +/** + * self-restart + * + * Initially inspired by: Yu-Jie Lin + * https://sites.google.com/site/yjlnotes/notes/dwm + */ +void self_restart(const Arg *arg) { + char *const argv[] = {get_dwm_path(), NULL}; + + if(argv[0] == NULL){ + return; + } + + execv(argv[0], argv); +} diff --git a/util.o b/util.o new file mode 100644 index 0000000..daaf0da Binary files /dev/null and b/util.o differ