Re: [dev] [dwm] NetActiveWindow

From: Andreas Amann <amann_AT_physik.tu-berlin.de>
Date: Sun, 17 Apr 2011 01:19:29 +0200

On Fri, Apr 15, 2011 at 08:07:46AM +0000, Anselm R Garbe wrote:
>
> I think the approach has a multi-monitor flaw.
>
> The code should rather do:
>
> if(!ISVISIBLE(c)) {
> c->mon->seltags ^= 1;
> c->mon->tagset[c->mon->seltags] = c->tags;
> }
> detach(c);
> attach(c);
> focus(c);
> arrange(c->mon);o
>
> The focus(c) will update selmon propely, so that this should be fine.
>
> Also, when looking at the above lines and zoom(), we could probably save some
> compressing it into a separate function:
>
> static void
> pop(Client *c) {
> detach(c);
> attach(c);
> focus(c);
> arrange(c->mon);
> }
>

Yes, that makes sense.

In the meantime I noticed that it is quite difficult to reliably
obtain a list of the window ids of managed clients from the
commandline without some help from dwm. In particular "xprop" shows
also windows which are not managed by dwm, which is quite annoying. Is
there a known way around this?

Apparently, some WMs use the xproperty "_NET_CLIENT_LIST" of the root
window to advertise managed window ids. Here is a (not very elegant)
patch which makes dwm comply with this convention:

---------------------
diff --git a/dwm.c b/dwm.c
--- a/dwm.c
+++ b/dwm.c
@@ -58,7 +58,7 @@
 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
 enum { NetSupported, NetWMName, NetWMState,
- NetWMFullscreen, NetActiveWindow, NetLast }; /* EWMH atoms */
+ NetWMFullscreen, NetActiveWindow, NetClientList, NetLast }; /* EWMH atoms */
 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
        ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
@@ -232,6 +232,7 @@
 static Bool updategeom(void);
 static void updatebarpos(Monitor *m);
 static void updatebars(void);
+static void updateclientlist(void);
 static void updatenumlockmask(void);
 static void updatesizehints(Client *c);
 static void updatestatus(void);
@@ -1152,6 +1153,8 @@
         XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
         XMapWindow(dpy, c->win);
         setclientstate(c, NormalState);
+ XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
         arrange(c->mon);
 }
 
@@ -1545,6 +1548,7 @@
         netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
         netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
         netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
+ netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
         /* init cursors */
         cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
         cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
@@ -1567,6 +1571,7 @@
         /* EWMH support per view */
         XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
                         PropModeReplace, (unsigned char *) netatom, NetLast);
+ XDeleteProperty(dpy, root, netatom[NetClientList]);
         /* select for events */
         wa.cursor = cursor[CurNormal];
         wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
@@ -1742,6 +1747,7 @@
         }
         free(c);
         focus(NULL);
+ updateclientlist();
         arrange(m);
 }
 
@@ -1784,6 +1790,19 @@
                 m->by = -bh;
 }
 
+void
+updateclientlist() {
+ Client *c;
+ Monitor *m;
+
+ XDeleteProperty(dpy, root, netatom[NetClientList]);
+ for(m = mons; m; m = m->next)
+ for(c = m->clients; c; c = c->next)
+ XChangeProperty(dpy, root, netatom[NetClientList],
+ XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
+}
+
 Bool
 updategeom(void) {
         Bool dirty = False;
---------------------

With this patch in place the following script now works reliably for me:

---------------------
#!/bin/sh

winlist=$(xprop -root _NET_CLIENT_LIST|cut -d "#" -f 2|tr "," " ")
count=$(echo $winlist|wc -w)
foo=$(for i in $winlist; do
        win_id="${i}"
        win_class=$(xprop -id ${win_id} WM_CLASS | cut -d'"' -f2)
        win_title=$(xprop -id ${win_id} WM_NAME | cut -d'=' -f2-)
        printf "%10.10s | %30.30s | %8.8d\n" "${win_class}" "${win_title}" "${win_id}"
done |sort| dmenu -i -l $count)

if [ $? -eq 0 ]; then
        xdotool windowactivate $(echo $foo | awk -F'|' '{ print $NF }')
fi

---------------------

It is then also possible to use "winctrl" and similar tools which
depend on _NET_CLIENT_LIST.

While this works great for me, I assume that most people might not
care about _NET_CLIENT_LIST, and this patch should probably not be
mainline material.

Andreas
Received on Sun Apr 17 2011 - 01:19:29 CEST

This archive was generated by hypermail 2.2.0 : Sun Apr 17 2011 - 01:24:02 CEST