sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

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