commit f93a225bb6bbda31d1981f3f8844f4a104b3e787
parent f2a833eaa026fe676eb1f98ea943808363f5a189
Author: Benjamin Chausse <benjamin@chausse.xyz>
Date:   Sat, 17 Oct 2020 23:49:53 -0400

README overhaul

Diffstat:
DREADME | 48------------------------------------------------
AREADME.md | 243+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mconfig.def.h | 1+
Mdwm.c | 9+++++----
Apatches/dwm-activetagindicatorbar-6.2.diff | 17+++++++++++++++++
Apatches/dwm-bar-height-6.2.diff | 25+++++++++++++++++++++++++
Apatches/dwm-statuscmd-signal-6.2.diff | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 448 insertions(+), 52 deletions(-)

diff --git a/README b/README @@ -1,48 +0,0 @@ -dwm - dynamic window manager -============================ -dwm is an extremely fast, small, and dynamic window manager for X. - - -Requirements ------------- -In order to build dwm you need the Xlib header files. - - -Installation ------------- -Edit config.mk to match your local setup (dwm is installed into -the /usr/local namespace by default). - -Afterwards enter the following command to build and install dwm (if -necessary as root): - - make clean install - - -Running dwm ------------ -Add the following line to your .xinitrc to start dwm using startx: - - exec dwm - -In order to connect dwm to a specific display, make sure that -the DISPLAY environment variable is set correctly, e.g.: - - DISPLAY=foo.bar:1 exec dwm - -(This will start dwm on display :1 of the host foo.bar.) - -In order to display status info in the bar, you can do something -like this in your .xinitrc: - - while xsetroot -name "`date` `uptime | sed 's/.*,//'`" - do - sleep 1 - done & - exec dwm - - -Configuration -------------- -The configuration of dwm is done by creating a custom config.h -and (re)compiling the source code. diff --git a/README.md b/README.md @@ -0,0 +1,243 @@ +My dwm +--- +A Dynamic Window Manager + +dwm is an extremely fast, small, and dynamic window manager for X. +It is written with the [suckless philosophy][15] +in mind and is objectively one of the best window managers out there. + +## What my build has to offer +I have patched dwm extensively using official patches but also with the +awesome patches [Floris Laporte][16] makes for his own build to +make the experience more enjoyable. Here are the following patches which I +installed: + +- [dwm-activetagindicatorbar-6.2][1] +- [dwm-alpha-20180613-b69c870][2] +- [dwm-bar-height-6.2][3] +- [dwm-centeredmaster-6.1][4] +- [dwm-dwmc-6.2][5] +- [dwm-focusmaster][6] +- [dwm-fullscreen][7] +- [dwm-gaplessgrid-20160731-56a31dc][8] +- [dwm-libxft-bgra][9] +- [dwm-movestack-6.1][10] +- [dwm-rotatestack-20161021-ab9571b][11] +- [dwm-statuscmd-signal-6.2][21] +- [dwm-tilegap][12] +- [dwm-zoomswap-6.2][13] +- [flaport-center][14] +- [flaport-mastermon][14] +- [flaport-swallow][14] + +So that's a nice list... But what does it actually mean? Here are the main +points that make my build stand out. + +**Decentralized keybindings:** + +So if I have a piece of software that does one thing and does it well, why +would I use anything else. I personally use the *Simple X Hotkey Daemon* +([SXHKD][17]) to manage all my keybindings and dwm should be no exception. +That's why I use the [dwmc][5] patch to allow sxhkd to control dwm. + +For this reason, I highly recommend you take a look at my [dotfiles][18] +repository as it contains my current configuration for sxhkd. **This build +of dwm is basically unusable until you have sxhkd setup for it.** This also +means sxhkd should be launched along dwm inside your `.xinitrc`. As a bonus, +if you install this build of dwm with my dotfiles using [archer][19], you +can press `super + alt + shift + h` to view a procedurally generated pdf of +all my keybindings. + +**Window swallowing:** + +This is a feature which allows terminals to "transform" themselves into the +software they are launching (essentially saving screen real estate). For +example: If I were to open a video inside mpv from my terminal, the terminal +window would disapear and where it once was, mpv would appear. + +**Aesthetics:** + +I love transparency and that's why I added the [alpha][2] patch to my build. +While I was at it, I switched the standard corner square bar indicator for a +centered rectangle on each tag using the [activetagindicatorbar][1] patch. +Most fonts don't play well with it so I added the [bar-height][3] patch to make +the bar taller. I don't like to have gaps everywhere, but I don't dislike them +either. Therefore, I only added them to the tiling layout (which is where they +make the most sense). + +**Emoji Compatibility:** + +Some Suckless software have a frustrating tendency of crashing when +encountering color emoji. This got fixed with the [libxft-bgra][9] patch. I'm +not the greatest fan of emojis (I personally prefer the fontawesome fonts for +icons), but in the unlikely event that one makes it's way to my statusbar, it +will not crash. + +**dwmblocks compatibility:** + +I personnally have a personal build of [dwmblocks][20] which is capable of +handling click events. For that to work, I had to add the +[statuscmd-signal][21] patch. + +**Accessible stack navigation and manipulation:** + +I don't want to spend half an hour placing a window where I want in in the +stack. I need a suite of functions aiding me to do certain motions +either to position windows or navigate through them: + +- [Rotatestack][11]: Rotate the entire stack (clockwise/couterclockwise). +- [Movestack][10]: Move the current window up or down the stack. +- [FocusMaster][6]: Focus the master window (the last spawned window). +- [ZoomSwap][13]: Swap the master window with the currently focused one. + +**Diverse but consise tiling modes:** + +I'm not a fan of having so many tiling modes I need a patch just to switch +through all of them. I only included those I found usefull on a day to day +basis. The following schematics will showcase these (1 being the newest +spawned window): + +``` + Tile (Regular): +┌───────────────────────────────┐┌────────────────────────────────┐ +│ 1 ││ 2 │ +│ ││ │ +│ │└────────────────────────────────┘ +│ │┌────────────────────────────────┐ +│ ││ 3 │ +│ ││ │ +│ │└────────────────────────────────┘ +│ │┌────────────────────────────────┐ +│ ││ 4 │ +│ ││ │ +│ │└────────────────────────────────┘ +│ │┌────────────────────────────────┐ +│ ││ 5 │ +│ ││ │ +│ │└────────────────────────────────┘ +│ │┌────────────────────────────────┐ +│ ││ 6 │ +│ ││ │ +└───────────────────────────────┘└────────────────────────────────┘ + + Centered Master: +┌───────────────┐┌───────────────────────────────┐┌───────────────┐ +│ 3 ││ 1 ││ 2 │ +│ ││ ││ │ +└───────────────┘│ │└───────────────┘ +┌───────────────┐│ │┌───────────────┐ +│ 5 ││ ││ 4 │ +│ ││ ││ │ +└───────────────┘│ │└───────────────┘ +┌───────────────┐│ │┌───────────────┐ +│ 7 ││ ││ 6 │ +│ ││ ││ │ +└───────────────┘│ │└───────────────┘ +┌───────────────┐│ │┌───────────────┐ +│ 9 ││ ││ 8 │ +│ ││ ││ │ +└───────────────┘│ │└───────────────┘ +┌───────────────┐│ │┌───────────────┐ +│ 11 ││ ││ 10 │ +│ ││ ││ │ +└───────────────┘└───────────────────────────────┘└───────────────┘ + + Floating Centered Master: +┌───────────────┐┌───────────────┐┌───────────────┐┌───────────────┐ +│ 2 ││ 3 ││ 4 ││ 5 │ +│ ││ ││ ││ │ +│ ┌──────────────────────────────────────┐ │ +│ │ 1 │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ └──────────────────────────────────────┘ │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +└───────────────┘└───────────────┘└───────────────┘└───────────────┘ + + Gappless Grid: +┌───────────────┐┌───────────────┐┌───────────────┐┌───────────────┐ +│ 1 ││ 5 ││ 9 ││ 13 │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +└───────────────┘└───────────────┘└───────────────┘└───────────────┘ +┌───────────────┐┌───────────────┐┌───────────────┐┌───────────────┐ +│ 2 ││ 6 ││ 10 ││ 14 │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +└───────────────┘└───────────────┘└───────────────┘└───────────────┘ +┌───────────────┐┌───────────────┐┌───────────────┐┌───────────────┐ +│ 3 ││ 7 ││ 11 ││ 15 │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +└───────────────┘└───────────────┘└───────────────┘└───────────────┘ +┌───────────────┐┌───────────────┐┌───────────────┐┌───────────────┐ +│ 4 ││ 8 ││ 12 ││ 16 │ +│ ││ ││ ││ │ +│ ││ ││ ││ │ +└───────────────┘└───────────────┘└───────────────┘└───────────────┘ + +``` +There are 3 more layout which don't require drawings: +- Fullscreen +- Monocle: Windows are stacked one over the over in "fullscreen" + (the statusbar remains). +- Floating: Windows don't respond to any tiling function and simply + spawn in the top left corner (they remain in place coming from + another tiling function). + +## Requirements +In order to build dwm you need the Xlib header files. + + +## Installation +Edit config.mk to match your local setup (dwm is installed into +the /usr/local namespace by default). + +Afterwards enter the following command to build and install dwm (if +necessary as root): +``` + make clean install +``` + +## Running dwm +Add the following line to your .xinitrc to start dwm using startx: +``` + exec dwm +``` + +## Configuration +The configuration of dwm is done by creating a custom config.h +and (re)compiling the source code. + + +[1]: https://dwm.suckless.org/patches/activetagindicatorbar/ +[2]: https://dwm.suckless.org/patches/alpha/ +[3]: https://dwm.suckless.org/patches/bar_height/ +[4]: https://dwm.suckless.org/patches/centeredmaster/ +[5]: https://dwm.suckless.org/patches/dwmc/ +[6]: https://dwm.suckless.org/patches/focusmaster/ +[7]: https://dwm.suckless.org/patches/fullscreen/ +[8]: https://dwm.suckless.org/patches/gaplessgrid/ +[9]: https://youtu.be/f9qNXV01yzg +[10]: https://dwm.suckless.org/patches/movestack/ +[11]: https://dwm.suckless.org/patches/rotatestack/ +[12]: https://dwm.suckless.org/patches/tilegap/ +[13]: https://dwm.suckless.org/patches/zoomswap/ +[14]: https://github.com/flaport/dwm +[15]: https://suckless.org/philosophy/ +[16]: https://github.com/flaport +[17]: https://github.com/baskerville/sxhkd +[18]: https://git.chausse.xyz/dotfiles/ +[19]: https://git.chausse.xyz/archer/ +[20]: https://git.chausse.xyz/dwmblocks/ +[21]: https://dwm.suckless.org/patches/statuscmd/ diff --git a/config.def.h b/config.def.h @@ -7,6 +7,7 @@ static const unsigned int snap = 15; /* snap pixel */ static const int swallowfloating = 1; /* 1 means swallow floating windows by default */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ +static const int user_bh = 28; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ static const char *fonts[] = { "monospace:size=12" }; static const char dmenufont[] = "monospace:size=12"; static const char col_gray1[] = "#222d32"; diff --git a/dwm.c b/dwm.c @@ -896,9 +896,10 @@ drawbar(Monitor *m) drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? ( m == selmon ? SchemeSel : SchemeInactive) : SchemeNorm]); drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); if (occ & 1 << i) - drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); + drw_rect(drw, x + boxw, 0, w - ( 2 * boxw + 1), boxw, + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); + x += w; } } @@ -2003,7 +2004,7 @@ setup(void) if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) die("no fonts could be loaded."); lrpad = drw->fonts->h; - bh = drw->fonts->h + 2; + bh = user_bh ? user_bh : drw->fonts->h + 2; updategeom(); /* init atoms */ utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/patches/dwm-activetagindicatorbar-6.2.diff b/patches/dwm-activetagindicatorbar-6.2.diff @@ -0,0 +1,17 @@ +diff -up dwm-a/dwm.c dwm-b/dwm.c +--- dwm-a/dwm.c 2019-02-02 06:55:28.000000000 -0600 ++++ dwm-b/dwm.c 2019-02-23 21:43:13.359179100 -0600 +@@ -719,9 +719,10 @@ drawbar(Monitor *m) + drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? SchemeSel : SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); + if (occ & 1 << i) +- drw_rect(drw, x + boxs, boxs, boxw, boxw, +- m == selmon && selmon->sel && selmon->sel->tags & 1 << i, +- urg & 1 << i); ++ drw_rect(drw, x + boxw, 0, w - ( 2 * boxw + 1), boxw, ++ m == selmon && selmon->sel && selmon->sel->tags & 1 << i, ++ urg & 1 << i); ++ + x += w; + } + w = blw = TEXTW(m->ltsymbol); diff --git a/patches/dwm-bar-height-6.2.diff b/patches/dwm-bar-height-6.2.diff @@ -0,0 +1,25 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..9814500 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -5,6 +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 int user_bh = 0; /* 0 means that dwm will calculate bar height, >= 1 means dwm will user_bh as bar height */ + static const char *fonts[] = { "monospace:size=10" }; + static const char dmenufont[] = "monospace:size=10"; + static const char col_gray1[] = "#222222"; +diff --git a/dwm.c b/dwm.c +index 4465af1..2c27cb3 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -1545,7 +1545,7 @@ setup(void) + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); + lrpad = drw->fonts->h; +- bh = drw->fonts->h + 2; ++ bh = user_bh ? user_bh : drw->fonts->h + 2; + updategeom(); + /* init atoms */ + utf8string = XInternAtom(dpy, "UTF8_STRING", False); diff --git a/patches/dwm-statuscmd-signal-6.2.diff b/patches/dwm-statuscmd-signal-6.2.diff @@ -0,0 +1,157 @@ +diff --git a/config.def.h b/config.def.h +index 1c0b587..b67825e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -103,7 +103,9 @@ static Button buttons[] = { + { ClkLtSymbol, 0, Button1, setlayout, {0} }, + { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button2, zoom, {0} }, +- { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, ++ { ClkStatusText, 0, Button1, sigdwmblocks, {.i = 1} }, ++ { ClkStatusText, 0, Button2, sigdwmblocks, {.i = 2} }, ++ { ClkStatusText, 0, Button3, sigdwmblocks, {.i = 3} }, + { ClkClientWin, MODKEY, Button1, movemouse, {0} }, + { ClkClientWin, MODKEY, Button2, togglefloating, {0} }, + { ClkClientWin, MODKEY, Button3, resizemouse, {0} }, +diff --git a/dwm.c b/dwm.c +index 4465af1..c600131 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -156,6 +156,7 @@ static void clientmessage(XEvent *e); + static void configure(Client *c); + static void configurenotify(XEvent *e); + static void configurerequest(XEvent *e); ++static void copyvalidchars(char *text, char *rawtext); + static Monitor *createmon(void); + static void destroynotify(XEvent *e); + static void detach(Client *c); +@@ -169,6 +170,7 @@ static void focus(Client *c); + static void focusin(XEvent *e); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static int getdwmblockspid(); + static int getrootptr(int *x, int *y); + static long getstate(Window w); + static int gettextprop(Window w, Atom atom, char *text, unsigned int size); +@@ -205,6 +207,7 @@ static void setup(void); + static void seturgent(Client *c, int urg); + static void showhide(Client *c); + static void sigchld(int unused); ++static void sigdwmblocks(const Arg *arg); + static void spawn(const Arg *arg); + static void tag(const Arg *arg); + static void tagmon(const Arg *arg); +@@ -237,6 +240,9 @@ static void zoom(const Arg *arg); + /* variables */ + static const char broken[] = "broken"; + static char stext[256]; ++static char rawstext[256]; ++static int dwmblockssig; ++pid_t dwmblockspid = 0; + static int screen; + static int sw, sh; /* X display screen geometry width, height */ + static int bh, blw = 0; /* bar geometry */ +@@ -439,9 +445,26 @@ buttonpress(XEvent *e) + arg.ui = 1 << i; + } else if (ev->x < x + blw) + click = ClkLtSymbol; +- else if (ev->x > selmon->ww - TEXTW(stext)) ++ else if (ev->x > (x = selmon->ww - TEXTW(stext) + lrpad)) { + click = ClkStatusText; +- else ++ ++ char *text = rawstext; ++ int i = -1; ++ char ch; ++ dwmblockssig = 0; ++ while (text[++i]) { ++ if ((unsigned char)text[i] < ' ') { ++ ch = text[i]; ++ text[i] = '\0'; ++ x += TEXTW(text) - lrpad; ++ text[i] = ch; ++ text += i+1; ++ i = -1; ++ if (x >= ev->x) break; ++ dwmblockssig = ch; ++ } ++ } ++ } else + click = ClkWinTitle; + } else if ((c = wintoclient(ev->window))) { + focus(c); +@@ -627,6 +650,19 @@ configurerequest(XEvent *e) + XSync(dpy, False); + } + ++void ++copyvalidchars(char *text, char *rawtext) ++{ ++ int i = -1, j = 0; ++ ++ while(rawtext[++i]) { ++ if ((unsigned char)rawtext[i] >= ' ') { ++ text[j++] = rawtext[i]; ++ } ++ } ++ text[j] = '\0'; ++} ++ + Monitor * + createmon(void) + { +@@ -871,6 +907,18 @@ getatomprop(Client *c, Atom prop) + return atom; + } + ++int ++getdwmblockspid() ++{ ++ char buf[16]; ++ FILE *fp = popen("pidof -s dwmblocks", "r"); ++ fgets(buf, sizeof(buf), fp); ++ pid_t pid = strtoul(buf, NULL, 10); ++ pclose(fp); ++ dwmblockspid = pid; ++ return pid != 0 ? 0 : -1; ++} ++ + int + getrootptr(int *x, int *y) + { +@@ -1636,6 +1684,23 @@ sigchld(int unused) + while (0 < waitpid(-1, NULL, WNOHANG)); + } + ++void ++sigdwmblocks(const Arg *arg) ++{ ++ union sigval sv; ++ sv.sival_int = (dwmblockssig << 8) | arg->i; ++ if (!dwmblockspid) ++ if (getdwmblockspid() == -1) ++ return; ++ ++ if (sigqueue(dwmblockspid, SIGUSR1, sv) == -1) { ++ if (errno == ESRCH) { ++ if (!getdwmblockspid()) ++ sigqueue(dwmblockspid, SIGUSR1, sv); ++ } ++ } ++} ++ + void + spawn(const Arg *arg) + { +@@ -1987,8 +2052,10 @@ updatesizehints(Client *c) + void + updatestatus(void) + { +- if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext))) ++ if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) + strcpy(stext, "dwm-"VERSION); ++ else ++ copyvalidchars(stext, rawstext); + drawbar(selmon); + } +