This is a flexipatch build. Patches are toggled via #define flags, NOT by applying .diff files.
| File | Role | Committed? |
|---|---|---|
config.def.h |
Source of truth for all configuration | YES |
patches.def.h |
Source of truth for patch enable/disable flags | YES |
config.h |
Local working copy (generated from config.def.h) |
NO (gitignored) |
patches.h |
Local working copy (generated from patches.def.h) |
NO (gitignored) |
config.mk |
Compiler/linker flags, library paths | YES |
dwm.c |
Core window manager (includes config.h at line 878) | YES |
patch/*.c patch/*.h |
Patch implementations and headers | YES |
patch/include.c patch/include.h |
Conditional patch includes (do NOT edit by hand) | YES |
config.def.h for keybindings, layouts, rules, colors, and custom functions.patches.def.h to enable/disable patches (#define PATCH_NAME 0 or 1).config.h and patches.h to match, so local builds work without regenerating.config.h or patches.h — those are gitignored and will be lost.config.h does not exist, make generates it by copying config.def.h. Same for patches.h.Local build (this desktop):
cd /home/krisyotam/dev/dwm
sudo make clean install
Deploy to laptop (khr1st):
# 1. Commit and push from desktop
cd /home/krisyotam/dev/dwm
git add config.def.h patches.def.h
git commit -m "description"
git push
# 2. SSH to laptop, pull, rebuild
ssh khr1st
cd ~/.local/src/dwm && git pull && sudo make clean install
# 3. Self-restart dwm (preserves all windows — no session kill)
# Trigger via sysact menu or a keybinding mapped to self_restart
NEVER tell the user to "restart dwm" or "log out and back in" without mentioning self_restart. The SELFRESTART_PATCH is enabled and does an in-place execv() that preserves all window positions.
Reference: https://suckless.org/coding_style/
The following are guidelines. The most important aspect of style is consistency.
Recommended reading:
Organize files in this order:
main_POSIX_C_SOURCE 200809L or _XOPEN_SOURCE 700.for (int i = 0; ...))./* */ for comments, not //.__VA_ARGS__.{ on the same line, preceded by a single space (except for function definitions).} on its own line unless continuing a statement (} else {).Use blocks for single statements only when the inner statement needs blocks:
for (;;) {
if (foo) {
bar;
baz;
}
}
Use blocks when any branch requires them:
if (foo) {
bar;
} else {
baz;
qux;
}
{ on its own line (function definitions only).static.static void
usage(void)
{
eprintf("usage: %s [file ...]\n", argv0);
}
static.* is adjacent to the variable name, not the type:
char *p; /* correct */
char* p; /* wrong */
if, for, while, switch (they are not function calls).( or before ).() with sizeof.sizeof():
sizeof(int) /* correct */
sizeof (int) /* wrong */
switch (value) {
case 0: /* FALLTHROUGH */
case 1:
case 2:
break;
default:
break;
}
type_t naming (reserved for POSIX, less readable).CamelCase for typedef'd types.Keep lines to a reasonable length: max 79 characters.
bool types. Stick to integer types.if (!(p = malloc(sizeof(*p))))
hcf();
-1 for error, test against 0, not -1:
if (func() < 0)
hcf();
goto to unwind and cleanup when necessary, instead of multiple nested levels.return or exit early on failures instead of deeply nesting./* NOTREACHED */ comment.Use enums for semantically grouped values. Use #define otherwise:
#define MAXSZ 4096
#define MAGIC1 0xdeadbeef
enum {
DIRECTION_X,
DIRECTION_Y,
DIRECTION_Z
};
CamelCase for types and structs: Client, Monitor, Layout, Key, Buttonlowercase or lowercasemultiword for functions: focusmon, tagmon, sendmon, killclientUPPERCASE for macros and constants: MODKEY, NUMTAGS, CLEANMASK, SHCMDSchemeNorm, SchemeSel, NetSupported/* C89-style block comments */ in .c source files (mandatory per suckless style).// C99 inline comments are acceptable in config.def.h for brief binding annotations only.#endif // PATCH_NAME#if SOME_PATCH
/* patch-specific code */
#endif // SOME_PATCH
#endif comment.config.def.h does NOT need guards.Custom functions go before the static const Key keys[] array. They can reference any forward-declared function from dwm.c (sendmon, focusmon, arrange, focus, selmon, mons, etc.) because config.h is included after all declarations in dwm.c (line 878).
The layout array uses flextile-deluxe. Index matters for keybindings.
| Index | Symbol | Layout | Notes |
|---|---|---|---|
| 0 | []= |
Tile | Default |
| 1 | ><> |
Floating | |
| 2 | [M] |
Monocle | |
| 3 | ||| |
Columns | |
| 4 | >M> |
Floating master | |
| 5 | [D] |
Deck | |
| 6 | TTT |
Bottom stack | |
| 7 | === |
Bottom stack horiz | |
| 8 | |M| |
Centered master | |
| 9 | -M- |
Centered master horiz | |
| 10 | ::: |
Gappless grid | |
| 11 | [\\] |
Fibonacci dwindle | |
| 12 | (@) |
Fibonacci spiral | |
| 13 | [T] |
Tatami mats | |
| 14 | RRR |
Reading mode (3 vertical panes) | Custom: nmaster=3 |
When referencing layouts in keybindings, ALWAYS verify the index by counting from 0 in the layouts[] array. Off-by-one errors here cause the wrong layout to activate with no obvious error.
Patches set to 1 in patches.def.h:
Bar: BAR_DWMBLOCKS, BAR_LTSYMBOL, BAR_STATUS, BAR_STATUSCMD, BAR_TAGS, BAR_WINTITLE, BAR_HIDEVACANTTAGS
Core: CFACTS, COOL_AUTOSTART, CYCLELAYOUTS, PERTAG, RESTARTSIG, SCRATCHPADS, SEAMLESS_RESTART, SELFRESTART, SHIFTTAG, SHIFTVIEW, STACKER, STICKY, SWALLOW, TOGGLEFULLSCREEN, VANITYGAPS, XRESOURCES
Layouts: BSTACK, CENTEREDMASTER, CENTEREDFLOATINGMASTER, COLUMNS, DECK, FIBONACCI_DWINDLE, FIBONACCI_SPIRAL, NROWGRID, TILE, MONOCLE
| Binding | Action |
|---|---|
| Super+Q | Reading mode (RRR layout) |
| Super+Shift+Q | Kill client (close window) |
| Super+Backspace | sysact (system actions menu) |
| Super+Left/Right/Up/Down | Send window to monitor in that direction |
| Super+Comma/Period | Focus previous/next monitor |
| Super+T | Tile layout |
| Super+F | Floating layout |
config.def.h before modifying it. Understand the surrounding #if guards.layouts[] array every time.XK_w) across config.def.h to find all uses and check which patches guard them.config.h standalone are ALWAYS false positives (missing types like Arg, Client, Monitor). The only valid test is make in the repo root.config.def.h must also be applied to config.h (and vice versa for patches).// removed: reason note rather than deleting the line, so the history is visible.dwm.c unless absolutely necessary. Configuration belongs in config.def.h. New functions go in config.def.h (before the keys array) or as a new file in patch/.patch/include.c or patch/include.h unless adding a completely new patch file to the patch/ directory."Rebind reading mode to Super+Q, add directional tagmon". No "Co-Authored-By" lines.