dwm-noxz

[fork] suckless dwm - personal fork
git clone https://noxz.tech/git/dwm-noxz.git
Log | Files | README | LICENSE

commit: f1fb34c656fdd7dc17375214deeb3a21ea580148
parent: 8a891e2aa685f1a59505a6e39c382c8e23dcefcb
author: Chris Noxz <chris@noxz.tech>
date:   Mon, 6 Feb 2023 14:34:42 +0100
Add features for a persistent state
Mdwm.c114+++++++++++++++-----
1 file changed, 89 insertions(+), 25 deletions(-)
diff --git a/dwm.c b/dwm.c
@@ -70,7 +70,7 @@ enum { SchemeNorm, SchemeSel, SchemeTagsNorm, SchemeTagsIncl, SchemeTagsSel,
 	SchemeStatusAct, SchemeStatusDist, SchemeStatusNoti }; /* color schemes */
 enum { NetSupported, NetWMName, NetWMState, NetWMCheck,
        NetWMFullscreen, NetActiveWindow, NetWMWindowType,
-       NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+       NetWMWindowTypeDialog, NetClientList, NetClientInfo, NetTagState, NetLast }; /* EWMH atoms */
 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
        ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -206,7 +206,8 @@ static void grabbuttons(Client *c, int focused);
 static void incgaps(const Arg *arg);
 static void incnmaster(const Arg *arg);
 static void killclient(const Arg *arg);
-static void load_xresources(void);
+static void loadxresources(void);
+static void loadstate(int atom_type, Window win, Client *c);
 static void manage(Window w, XWindowAttributes *wa);
 static void maprequest(XEvent *e);
 static void monocle(Monitor *m);
@@ -219,7 +220,7 @@ static Monitor *recttomon(int x, int y, int w, int h);
 static void resize(Client *c, int x, int y, int w, int h, int interact);
 static void resizeclient(Client *c, int x, int y, int w, int h);
 static void resizemouse(const Arg *arg);
-static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
+static void resourceload(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
 static void restack(Monitor *m);
 static void movestack(const Arg *arg);
 static void rotatestack(const Arg *arg);
@@ -228,9 +229,11 @@ static void scan(void);
 static int sendevent(Client *c, Atom proto);
 static void sendmon(Client *c, Monitor *m);
 static void setclientstate(Client *c, long state);
+static void setclienttagprop(Client *c);
 static void setfocus(Client *c);
 static void setfullscreen(Client *c, int fullscreen);
 static void setlayout(const Arg *arg);
+static void settagstate(void);
 static void togglelayout(const Arg *arg);
 static void rotatelayout(const Arg *arg);
 static void setup(void);
@@ -948,7 +951,7 @@ drawbar(Monitor *m)
 		tagw[i] = w = TEXTW(masterclientontag[i]);
 		drw_setscheme(drw,
 			scheme[m->tagset[m->seltags] & 1 << i ? SchemeTagsSel                   /* selected tag */
-			: selmon && selmon->sel && selmon->sel->tags & 1 << i ? SchemeTagsIncl   /* client in tag */
+			: selmon && selmon->sel && selmon->sel->tags & 1 << i ? SchemeTagsIncl  /* client in tag */
 			: SchemeTagsNorm]);
 		drw_text(drw, x, 0, w, bh, lrpad / 2, masterclientontag[i], urg & 1 << i);
 		if (m->tagset[m->seltags] & 1 << i)
@@ -1233,6 +1236,53 @@ killclient(const Arg *arg)
 	}
 }
 
+void
+loadxresources(void)
+{
+	Display *display;
+	char *resm;
+	XrmDatabase db;
+	ResourcePref *p;
+
+	display = XOpenDisplay(NULL);
+	resm = XResourceManagerString(display);
+	if (!resm)
+		return;
+
+	db = XrmGetStringDatabase(resm);
+	for (p = resources; p < resources + LENGTH(resources); p++)
+		resourceload(db, p->name, p->type, p->dst);
+	XCloseDisplay(display);
+}
+
+void
+loadstate(int atom_type, Window win, Client *c)
+{
+	int format;
+	unsigned long *data, n, extra, length = (
+		atom_type == NetClientInfo ? 2L
+		: atom_type == NetTagState ? 1L
+		: 0L);
+	Monitor *m;
+	Atom atom, req_type = (
+		atom_type == NetClientInfo ? XA_CARDINAL
+		: atom_type == NetTagState ? XA_INTEGER
+		: AnyPropertyType);
+
+	if (XGetWindowProperty(dpy, win, netatom[atom_type], 0L, length, False, req_type, &atom, &format, &n, &extra, (unsigned char **)&data) == Success) {
+		if (atom_type == NetClientInfo && n == 2) {
+			c->tags = *data;
+			for (m = mons; m; m = m->next)
+				if (m->num == *(data+1) && (c->mon = m) == m)
+					break;
+		} else if (atom_type == NetTagState && n == 1) {
+			selmon->tagset[selmon->seltags] = (unsigned int)*data;
+		}
+	}
+	if (n > 0) /* clean up */
+		XFree(data);
+}
+
 void
 manage(Window w, XWindowAttributes *wa)
 {
@@ -1278,6 +1328,9 @@ manage(Window w, XWindowAttributes *wa)
 	updatewindowtype(c);
 	updatesizehints(c);
 	updatewmhints(c);
+	loadstate(NetClientInfo, c->win, c);
+	setclienttagprop(c);
+
 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 	grabbuttons(c, 0);
 	if (!c->isfloating)
@@ -1726,6 +1779,7 @@ sendmon(Client *c, Monitor *m)
 	c->tags = (m->tagset[m->seltags] ? m->tagset[m->seltags] : 1);
 	attachabove(c);
 	attachstack(c);
+	setclienttagprop(c);
 	focus(NULL);
 	arrange(NULL);
 }
@@ -1739,6 +1793,14 @@ setclientstate(Client *c, long state)
 		PropModeReplace, (unsigned char *)data, 2);
 }
 
+void
+setclienttagprop(Client *c)
+{
+	long data[] = { (long) c->tags, (long) c->mon->num };
+	XChangeProperty(dpy, c->win, netatom[NetClientInfo], XA_CARDINAL, 32,
+			PropModeReplace, (unsigned char *) data, 2);
+}
+
 int
 sendevent(Client *c, Atom proto)
 {
@@ -1818,6 +1880,15 @@ setlayout(const Arg *arg)
 		drawbar(selmon);
 }
 
+void
+settagstate(void)
+{
+	if (running) {
+		long data[] = { (long)selmon->tagset[selmon->seltags] };
+		XChangeProperty(dpy, root, netatom[NetTagState], XA_INTEGER, 32, PropModeReplace, (unsigned char *) data, 1);
+	}
+}
+
 void
 togglelayout(const Arg *arg)
 {
@@ -1896,6 +1967,8 @@ setup(void)
 	netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
 	netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
 	netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
+	netatom[NetClientInfo] = XInternAtom(dpy, "_NET_CLIENT_INFO", False);
+	netatom[NetTagState] = XInternAtom(dpy, "_NET_TAG_STATE", False);
 	/* init cursors */
 	cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
 	cursor[CurResize] = drw_cur_create(drw, XC_sizing);
@@ -1919,6 +1992,7 @@ setup(void)
 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
 		PropModeReplace, (unsigned char *) netatom, NetLast);
 	XDeleteProperty(dpy, root, netatom[NetClientList]);
+	XDeleteProperty(dpy, root, netatom[NetClientInfo]);
 	/* select events */
 	wa.cursor = cursor[CurNormal]->cursor;
 	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
@@ -1928,6 +2002,9 @@ setup(void)
 	XSelectInput(dpy, root, wa.event_mask);
 	focus(NULL);
 
+	/* load tag state */
+	loadstate(NetTagState, root, NULL);
+
 	/* fifo */
 	mkfifo(dwmfifo, 0600);
 	fifofd = open(dwmfifo, O_RDWR | O_NONBLOCK);
@@ -1993,6 +2070,7 @@ tag(const Arg *arg)
 {
 	if (selmon->sel && arg->ui & TAGMASK) {
 		selmon->sel->tags = arg->ui & TAGMASK;
+		setclienttagprop(selmon->sel);
 		focus(NULL);
 		arrange(selmon);
 		if (viewontag)
@@ -2171,6 +2249,7 @@ toggletag(const Arg *arg)
 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
 	if (newtags) {
 		selmon->sel->tags = newtags;
+		setclienttagprop(selmon->sel);
 		focus(NULL);
 		arrange(selmon);
 	}
@@ -2208,6 +2287,8 @@ toggleview(const Arg *arg)
 		focus(NULL);
 		arrange(selmon);
 	}
+
+	settagstate();
 }
 
 void
@@ -2531,6 +2612,8 @@ view(const Arg *arg)
 		togglebar(NULL);
 	focus(NULL);
 	arrange(selmon);
+
+	settagstate();
 }
 
 Client *
@@ -2614,7 +2697,7 @@ zoom(const Arg *arg)
 }
 
 void
-resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+resourceload(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
 {
 	char *sdst = NULL;
 	int *idst = NULL;
@@ -2648,25 +2731,6 @@ resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
 	}
 }
 
-void
-load_xresources(void)
-{
-	Display *display;
-	char *resm;
-	XrmDatabase db;
-	ResourcePref *p;
-
-	display = XOpenDisplay(NULL);
-	resm = XResourceManagerString(display);
-	if (!resm)
-		return;
-
-	db = XrmGetStringDatabase(resm);
-	for (p = resources; p < resources + LENGTH(resources); p++)
-		resource_load(db, p->name, p->type, p->dst);
-	XCloseDisplay(display);
-}
-
 int
 main(int argc, char *argv[])
 {
@@ -2680,7 +2744,7 @@ main(int argc, char *argv[])
 		die("dwm: cannot open display");
 	checkotherwm();
 	XrmInitialize();
-	load_xresources();
+	loadxresources();
 	setup();
 #ifdef __OpenBSD__
 	if (pledge("stdio rpath proc exec", NULL) == -1)