From 18fee48e6c25a6f05af186af0858072cacec2259 Mon Sep 17 00:00:00 2001 From: Justinas Grigas Date: Thu, 7 May 2026 18:29:50 +0100 Subject: [PATCH] xresources: runtime configuration using X resources --- config.def.h | 56 ++++++++++++++++++++++++------------- dwm.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 19 deletions(-) diff --git a/config.def.h b/config.def.h index 81c3fc0..3208f10 100644 --- a/config.def.h +++ b/config.def.h @@ -1,21 +1,15 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -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 dmenufont[] = "monospace:size=10"; -static const char col_gray1[] = "#222222"; -static const char col_gray2[] = "#444444"; -static const char col_gray3[] = "#bbbbbb"; -static const char col_gray4[] = "#eeeeee"; -static const char col_cyan[] = "#005577"; -static const char *colors[][3] = { - /* fg bg border */ - [SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, - [SchemeSel] = { col_gray4, col_cyan, col_cyan }, +static unsigned int borderpx = 1; /* border pixel of windows */ +static unsigned int snap = 32; /* snap pixel */ +static int showbar = 1; /* 0 means no bar */ +static int topbar = 1; /* 0 means bottom bar */ +static const char *fonts[] = { "monospace:size=10" }; +static const char *colors[][3] = { + /* scheme fg bg border */ + [SchemeNorm] = { "#bbbbbb", "#222222", "#444444" }, + [SchemeSel] = { "#eeeeee", "#005577", "#005577" }, }; /* tagging */ @@ -32,9 +26,9 @@ static const Rule rules[] = { }; /* layout(s) */ -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ -static const int nmaster = 1; /* number of clients in master area */ -static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */ +static float mfact = 0.55; /* factor of master area size [0.05..0.95] */ +static int nmaster = 1; /* number of clients in master area */ +static int resizehints = 1; /* 1 means respect size hints in tiled resizals */ static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */ static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */ @@ -58,7 +52,7 @@ static const Layout layouts[] = { /* commands */ 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 char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", "monospace:size=10", "-nb", "#222222", "-nf", "#bbbbbb", "-sb", "#005577", "-sf", "#eeeeee", NULL }; static const char *termcmd[] = { "st", NULL }; static const Key keys[] = { @@ -86,6 +80,7 @@ static const Key keys[] = { { MODKEY, XK_period, focusmon, {.i = +1 } }, { MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } }, { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, + { MODKEY, XK_F5, xresreload, {0} }, TAGKEYS( XK_1, 0) TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) @@ -115,3 +110,26 @@ static const Button buttons[] = { { ClkTagBar, MODKEY, Button3, toggletag, {0} }, }; +/* X resources to update */ +static const XResPref resources[] = { + /* name type address */ + { "dwm.font", STRING, &fonts[0] }, + { "dwm.dmenufont", STRING, &dmenucmd[4] }, + { "dwm.background", STRING, &dmenucmd[6] }, + { "dwm.foreground", STRING, &dmenucmd[8] }, + { "dwm.backgroundSel", STRING, &dmenucmd[10] }, + { "dwm.foregroundSel", STRING, &dmenucmd[12] }, + { "dwm.foreground", STRING, &colors[SchemeNorm][ColFg] }, + { "dwm.background", STRING, &colors[SchemeNorm][ColBg] }, + { "dwm.border", STRING, &colors[SchemeNorm][ColBorder] }, + { "dwm.foregroundSel", STRING, &colors[SchemeSel][ColFg] }, + { "dwm.backgroundSel", STRING, &colors[SchemeSel][ColBg] }, + { "dwm.borderSel", STRING, &colors[SchemeSel][ColBorder] }, + { "dwm.borderpx", INTEGER, &borderpx }, + { "dwm.snap", INTEGER, &snap }, + { "dwm.showbar", INTEGER, &showbar }, + { "dwm.topbar", INTEGER, &topbar }, + { "dwm.nmaster", INTEGER, &nmaster }, + { "dwm.resizehints", INTEGER, &resizehints }, + { "dwm.mfact", FLOAT, &mfact }, +}; diff --git a/dwm.c b/dwm.c index ab3a84c..b4c9174 100644 --- a/dwm.c +++ b/dwm.c @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -65,6 +66,7 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ +enum XResType {STRING, INTEGER, FLOAT}; typedef union { int i; @@ -140,6 +142,12 @@ typedef struct { int monitor; } Rule; +typedef struct { + const char *name; + enum XResType type; + void *dst; +} XResPref; + /* function declarations */ static void applyrules(Client *c); static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact); @@ -232,6 +240,9 @@ 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 xresload(const XResPref *resource); +static void xresupdate(void); +static void xresreload(const Arg *arg); /* variables */ static const char broken[] = "broken"; @@ -266,6 +277,7 @@ static Display *dpy; static Drw *drw; static Monitor *mons, *selmon; static Window root, wmcheckwin; +static XrmDatabase xrdb = NULL; /* configuration, allows nested code to access above variables */ #include "config.h" @@ -490,6 +502,7 @@ cleanup(void) free(scheme); XDestroyWindow(dpy, wmcheckwin); drw_free(drw); + XrmDestroyDatabase(xrdb); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); XDeleteProperty(dpy, root, netatom[NetActiveWindow]); @@ -2140,6 +2153,69 @@ zoom(const Arg *arg) pop(c); } +void +xresload(const XResPref *resource) +{ + char *type; + XrmValue ret; + + if (!XrmGetResource(xrdb, resource->name, NULL, &type, &ret)) + return; + if (!ret.addr || strncmp(type, "String", sizeof("String"))) + return; + + switch (resource->type) { + case STRING: + *(char **)resource->dst = ret.addr; + break; + case INTEGER: + *(int *)resource->dst = strtoul(ret.addr, NULL, 10); + break; + case FLOAT: + *(float *)resource->dst = strtof(ret.addr, NULL); + break; + } +} + +void +xresupdate(void) +{ + Display *display; + char *resm; + const XResPref *p; + + display = XOpenDisplay(NULL); + if (!display) + return; + resm = XResourceManagerString(display); + if (resm) { + if (xrdb) + XrmDestroyDatabase(xrdb); + xrdb = XrmGetStringDatabase(resm); + if (xrdb) { + for (p = resources; p < resources + LENGTH(resources); ++p) + xresload(p); + } + } + XCloseDisplay(display); +} + +void +xresreload(const Arg *arg) +{ + int i; + + xresupdate(); + for (i = 0; i < LENGTH(colors); ++i) { + drw_scm_free(drw, scheme[i], 3); + scheme[i] = drw_scm_create(drw, colors[i], 3); + } + drw_fontset_free(drw->fonts); + drw_fontset_create(drw, fonts, LENGTH(fonts)); + focus(NULL); + arrange(NULL); +} + int main(int argc, char *argv[]) { @@ -2152,6 +2228,8 @@ main(int argc, char *argv[]) if (!(dpy = XOpenDisplay(NULL))) die("dwm: cannot open display"); checkotherwm(); + XrmInitialize(); + xresupdate(); setup(); #ifdef __OpenBSD__ if (pledge("stdio rpath proc exec", NULL) == -1) -- 2.53.0