commit 327678aac33aa3c14c64e939c22bc39d9e047738
parent c94db3f270fdfa5f80b2dfa3129b18f45ea3a3c6
Author: Justinas Grigas <dev@jstnas.com>
Date: Sun, 24 May 2026 10:46:37 +0100
dwm xresources: refined
Finally got X resources to work well with dwm config
Diffstat:
2 files changed, 272 insertions(+), 27 deletions(-)
diff --git a/dwm.suckless.org/patches/xresources/dwm-xresources-20260524-44dbc68.diff b/dwm.suckless.org/patches/xresources/dwm-xresources-20260524-44dbc68.diff
@@ -0,0 +1,243 @@
+From 18fee48e6c25a6f05af186af0858072cacec2259 Mon Sep 17 00:00:00 2001
+From: Justinas Grigas <dev@jstnas.com>
+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 <X11/Xlib.h>
+ #include <X11/Xproto.h>
+ #include <X11/Xutil.h>
++#include <X11/Xresource.h>
+ #ifdef XINERAMA
+ #include <X11/extensions/Xinerama.h>
+ #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
+
diff --git a/dwm.suckless.org/patches/xresources/index.md b/dwm.suckless.org/patches/xresources/index.md
@@ -1,37 +1,39 @@
-Xresources
-==========
+# Xresources
-Description
------------
-This patch allows to handle settings from Xresources. It differs from xrdb patch in that it can handle any kind of setting as opposed to only color settings.
+Runtime configuration using X resources.
-The -20210314 patch adds an example on how you could set a custom font.
+## Description
-Settings in config.h
---------------------
-In `resources` struct is written the name, the type, and the address of the setting.
+This patch adds X resources support to dwm. At startup, dwm reads the configured
+X resources and applies them.
- Name Type Address
- --------------------------------------------------------
- "nmaster" INTEGER &nmaster
- "mfact" FLOAT &mfact
- "color1" STRING &color1
+This patch also adds a hotkey (`Modkey` + `F5` by default) which reloads the
+configured resources during runtime.
-In Xresources file setting names shoud be prefixed with "dwm."
+## Configuration
- dwm.nmaster:
- dwm.mfact:
- dwm.color1:
+The `resources` array contains list of settings to load from X resources:
-This patch is a port of the st patch of the same name, it also borrows some code from dwm's xrdb patch, so a thank is in order for the authors of those patches.
+ /* X resources to update */
+ static const XResPref resources[] = {
+ /* name type address */
+ { "dwm.font", STRING, &fonts[0] },
+ { "dwm.foreground", STRING, &colors[SchemeNorm][ColFg] },
+ { "dwm.borderpx", INTEGER, &borderpx },
+ { "dwm.mfact", FLOAT, &mfact },
+ };
-Download
---------
-* [dwm-xresources-6.2.diff](dwm-xresources-6.2.diff) (11/06/2020)
-* [dwm-xresources-20210314.diff](dwm-xresources-20210314.diff) (14/03/2021)
-* [dwm-xresources-20210827-138b405.diff](dwm-xresources-20210827-138b405.diff)
+Each entry contains the name of resource, the variable type, and the variable
+address.
+## Download
-Author
-------
-* MLquest8 (miskuzius at gmail.com)
+- [dwm-xresources-6.2.diff](./dwm-xresources-6.2.diff) (11/06/2020)
+- [dwm-xresources-20210314.diff](./dwm-xresources-20210314.diff)
+- [dwm-xresources-20210827-138b405.diff](./dwm-xresources-20210827-138b405.diff)
+- [dwm-xresources-20260524-44dbc68.diff](./dwm-xresources-20260524-44dbc68.diff)
+
+## Author
+
+- MLquest8 (miskuzius at gmail.com)
+- Justinas Grigas <dev@jstnas.com> (20260524)