dwm-ewmhtags-6.8.diff (6833B)
1 From 5eb9764bde3c9678a1802131ddb320dc2cb7c635 Mon Sep 17 00:00:00 2001 2 From: Damien aka Rad <nad2000@gmail.com> 3 Date: Wed, 1 Jul 2026 13:28:51 +1200 4 Subject: [PATCH] A 6.8 update and extension to current desktop. adds EWMH 5 support for _NET_NUMBER_OF_DESKTOPS, _NET_CURRENT_DESKTOP, 6 _NET_DESKTOP_NAMES, _NET_DESKTOP_VIEWPORT, and _NET_WM_DESKTOP which allows 7 for compatibility with other bars and programs that request workspace 8 information. for example, polybar's xworkspaces module. 9 10 --- 11 dwm.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 12 1 file changed, 66 insertions(+), 2 deletions(-) 13 14 diff --git a/dwm.c b/dwm.c 15 index ab3a84c..b56e18b 100644 16 --- a/dwm.c 17 +++ b/dwm.c 18 @@ -54,6 +54,7 @@ 19 #define WIDTH(X) ((X)->w + 2 * (X)->bw) 20 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 21 #define TAGMASK ((1 << LENGTH(tags)) - 1) 22 +#define TAGSLENGTH (LENGTH(tags)) 23 #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) 24 25 /* enums */ 26 @@ -61,7 +62,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 27 enum { SchemeNorm, SchemeSel }; /* color schemes */ 28 enum { NetSupported, NetWMName, NetWMState, NetWMCheck, 29 NetWMFullscreen, NetActiveWindow, NetWMWindowType, 30 - NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ 31 + NetWMWindowTypeDialog, NetClientList, NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop, NetWMDesktop, NetLast }; /* EWMH atoms */ 32 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 33 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 34 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 35 @@ -197,11 +198,15 @@ static void scan(void); 36 static int sendevent(Client *c, Atom proto); 37 static void sendmon(Client *c, Monitor *m); 38 static void setclientstate(Client *c, long state); 39 +static void setcurrentdesktop(void); 40 +static void setdesktopnames(void); 41 static void setfocus(Client *c); 42 static void setfullscreen(Client *c, int fullscreen); 43 static void setlayout(const Arg *arg); 44 static void setmfact(const Arg *arg); 45 +static void setnumdesktops(void); 46 static void setup(void); 47 +static void setviewport(void); 48 static void seturgent(Client *c, int urg); 49 static void showhide(Client *c); 50 static void spawn(const Arg *arg); 51 @@ -215,6 +220,7 @@ static void toggleview(const Arg *arg); 52 static void unfocus(Client *c, int setfocus); 53 static void unmanage(Client *c, int destroyed); 54 static void unmapnotify(XEvent *e); 55 +static void updatecurrentdesktop(void); 56 static void updatebarpos(Monitor *m); 57 static void updatebars(void); 58 static void updateclientlist(void); 59 @@ -1086,6 +1092,7 @@ manage(Window w, XWindowAttributes *wa) 60 arrange(c->mon); 61 XMapWindow(dpy, c->win); 62 focus(NULL); 63 + updateclientlist(); 64 } 65 66 void 67 @@ -1433,6 +1440,7 @@ sendmon(Client *c, Monitor *m) 68 resizeclient(c, m->mx, m->my, m->mw, m->mh); 69 focus(NULL); 70 arrange(NULL); 71 + updateclientlist(); 72 } 73 74 void 75 @@ -1443,6 +1451,16 @@ setclientstate(Client *c, long state) 76 XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, 77 PropModeReplace, (unsigned char *)data, 2); 78 } 79 +void 80 +setcurrentdesktop(void){ 81 + long data[] = { 0 }; 82 + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 83 +} 84 +void setdesktopnames(void){ 85 + XTextProperty text; 86 + Xutf8TextListToTextProperty(dpy, (char **)tags, TAGSLENGTH, XUTF8StringStyle, &text); 87 + XSetTextProperty(dpy, root, &text, netatom[NetDesktopNames]); 88 +} 89 90 int 91 sendevent(Client *c, Atom proto) 92 @@ -1469,6 +1487,12 @@ sendevent(Client *c, Atom proto) 93 return exists; 94 } 95 96 +void 97 +setnumdesktops(void){ 98 + long data[] = { TAGSLENGTH }; 99 + XChangeProperty(dpy, root, netatom[NetNumberOfDesktops], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 100 +} 101 + 102 void 103 setfocus(Client *c) 104 { 105 @@ -1579,6 +1603,12 @@ setup(void) 106 netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); 107 netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); 108 netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); 109 + netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False); 110 + netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False); 111 + netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False); 112 + netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False); 113 + netatom[NetWMDesktop] = XInternAtom(dpy, "_NET_WM_DESKTOP", False); 114 + 115 /* init cursors */ 116 cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); 117 cursor[CurResize] = drw_cur_create(drw, XC_sizing); 118 @@ -1601,6 +1631,10 @@ setup(void) 119 /* EWMH support per view */ 120 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, 121 PropModeReplace, (unsigned char *) netatom, NetLast); 122 + setnumdesktops(); 123 + setcurrentdesktop(); 124 + setdesktopnames(); 125 + setviewport(); 126 XDeleteProperty(dpy, root, netatom[NetClientList]); 127 /* select events */ 128 wa.cursor = cursor[CurNormal]->cursor; 129 @@ -1612,6 +1646,11 @@ setup(void) 130 grabkeys(); 131 focus(NULL); 132 } 133 +void 134 +setviewport(void){ 135 + long data[] = { 0, 0 }; 136 + XChangeProperty(dpy, root, netatom[NetDesktopViewport], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 2); 137 +} 138 139 void 140 seturgent(Client *c, int urg) 141 @@ -1748,6 +1787,8 @@ toggletag(const Arg *arg) 142 focus(NULL); 143 arrange(selmon); 144 } 145 + updatecurrentdesktop(); 146 + updateclientlist(); 147 } 148 149 void 150 @@ -1760,6 +1801,8 @@ toggleview(const Arg *arg) 151 focus(NULL); 152 arrange(selmon); 153 } 154 + updatecurrentdesktop(); 155 + updateclientlist(); 156 } 157 158 void 159 @@ -1855,13 +1898,33 @@ updateclientlist(void) 160 { 161 Client *c; 162 Monitor *m; 163 + unsigned int i; 164 + long unsigned int deckindex = 0; 165 166 XDeleteProperty(dpy, root, netatom[NetClientList]); 167 for (m = mons; m; m = m->next) 168 - for (c = m->clients; c; c = c->next) 169 + for (c = m->clients; c; c = c->next) { 170 XChangeProperty(dpy, root, netatom[NetClientList], 171 XA_WINDOW, 32, PropModeAppend, 172 (unsigned char *) &(c->win), 1); 173 + for (i = 0; i < LENGTH(tags); i++) { 174 + if (c->tags & (1 << i)) { 175 + deckindex = i; 176 + break; 177 + } 178 + } 179 + XChangeProperty(dpy, c->win, netatom[NetWMDesktop], XA_CARDINAL, 32, 180 + PropModeReplace, (unsigned char *)&deckindex, 1); 181 + } 182 +} 183 +void updatecurrentdesktop(void){ 184 + long rawdata[] = { selmon->tagset[selmon->seltags] }; 185 + int i=0; 186 + while(*rawdata >> (i+1)){ 187 + i++; 188 + } 189 + long data[] = { i }; 190 + XChangeProperty(dpy, root, netatom[NetCurrentDesktop], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 191 } 192 193 int 194 @@ -2060,6 +2123,7 @@ view(const Arg *arg) 195 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; 196 focus(NULL); 197 arrange(selmon); 198 + updatecurrentdesktop(); 199 } 200 201 Client * 202 -- 203 2.54.0 204