Greetings comrades,

attached is the patch I proposed some months ago, to add support
for dock windows in dwm, polished for current r1575:b899c8748939.

As you can see on [0], svkbd is now taking a reserved space, which
it inherits on all tags. That way for example an on-screen keyboard
can be shown on-demand and won't overlap with existing windows. In
[1] you see that this is possible for all directions of the screen.
The mangled windows on the left are two instances of svkbd, just
scaled to a different window geometry.


Sincerely,

Christoph Lohmann

[0]
http://www.r-36.net/media/pic/Bildschirmphotos/Screenshot-2011-10-09-21:03:42.png
[1]
http://www.r-36.net/media/pic/Bildschirmphotos/Screenshot-2011-10-09-21:06:41.png
# HG changeset patch
# User Christoph Lohmann <2...@r-36.net>
# Date 1318186431 -7200
# Node ID cb2ba6763beb10359b47629fc18fa8d11c8058c5
# Parent  b899c874893992a70e1017f4c29f64a5de471377
Adding docking support for dwm.

diff --git a/dwm.c b/dwm.c
--- a/dwm.c
+++ b/dwm.c
@@ -58,7 +58,8 @@
 enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
 enum { NetSupported, NetWMName, NetWMState,
-       NetWMFullscreen, NetActiveWindow, NetLast };     /* EWMH atoms */
+       NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+       NetWMWindowTypeDock, NetLast };     /* EWMH atoms */
 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
        ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
@@ -88,7 +89,9 @@
 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
 	int bw, oldbw;
 	unsigned int tags;
-	Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+	unsigned int isdock;
+	Bool isfixed, isfloating, isurgent, neverfocus, oldstate, \
+		isfullscreen;
 	Client *next;
 	Client *snext;
 	Monitor *mon;
@@ -231,10 +234,12 @@
 static void unmapnotify(XEvent *e);
 static Bool updategeom(void);
 static void updatebarpos(Monitor *m);
+static void updatedocks(Monitor *m);
 static void updatebars(void);
 static void updatenumlockmask(void);
 static void updatesizehints(Client *c);
 static void updatestatus(void);
+static void updatewindowtype(Client *c);
 static void updatetitle(Client *c);
 static void updatewmhints(Client *c);
 static void view(const Arg *arg);
@@ -735,6 +740,8 @@
 	Client *c;
 
 	for(c = m->clients; c; c = c->next) {
+		if(c->isdock)
+			continue;
 		occ |= c->tags;
 		if(c->isurgent)
 			urg |= c->tags;
@@ -774,6 +781,7 @@
 			drawtext(NULL, dc.norm, False);
 	}
 	XCopyArea(dpy, dc.drawable, m->barwin, dc.gc, 0, 0, m->ww, bh, 0, 0);
+
 	XSync(dpy, False);
 }
 
@@ -904,17 +912,20 @@
 	if(!selmon->sel)
 		return;
 	if(arg->i > 0) {
-		for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
-		if(!c)
-			for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
+		for(c = selmon->sel->next; c && (!ISVISIBLE(c) \
+				|| c->isdock); c = c->next);
+		if(!c) {
+			for(c = selmon->clients; c && (!ISVISIBLE(c) \
+					|| c->isdock); c = c->next);
+		}
 	}
 	else {
 		for(i = selmon->clients; i != selmon->sel; i = i->next)
-			if(ISVISIBLE(i))
+			if(ISVISIBLE(i) && !i->isdock)
 				c = i;
 		if(!c)
 			for(; i; i = i->next)
-				if(ISVISIBLE(i))
+				if(ISVISIBLE(i) && !i->isdock)
 					c = i;
 	}
 	if(c) {
@@ -1122,6 +1133,8 @@
 	c->w = c->oldw = wa->width;
 	c->h = c->oldh = wa->height;
 	c->oldbw = wa->border_width;
+
+	c->isdock = 0;
 	if(c->w == c->mon->mw && c->h == c->mon->mh) {
 		c->isfloating = True; // regression with flash, XXXX
 		c->x = c->mon->mx;
@@ -1158,6 +1171,7 @@
 	if (c->mon == selmon)
 		unfocus(selmon->sel, False);
 	c->mon->sel = c;
+	updatewindowtype(c);
 	arrange(c->mon);
 	XMapWindow(dpy, c->win);
 	focus(NULL);
@@ -1256,7 +1270,7 @@
 
 Client *
 nexttiled(Client *c) {
-	for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
+	for(; c && (c->isfloating || !ISVISIBLE(c) || c->isdock); c = c->next);
 	return c;
 }
 
@@ -1299,6 +1313,8 @@
 			if(c == c->mon->sel)
 				drawbar(c->mon);
 		}
+		if(ev->atom == netatom[NetWMWindowType])
+			updatewindowtype(c);
 	}
 }
 
@@ -1553,6 +1569,8 @@
 	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[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+	netatom[NetWMWindowTypeDock] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
 	/* init cursors */
 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
@@ -1740,6 +1758,8 @@
 	/* The server grab construct avoids race conditions. */
 	detach(c);
 	detachstack(c);
+	if(c->isdock)
+		updatebarpos(m);
 	if(!destroyed) {
 		wc.border_width = c->oldbw;
 		XGrabServer(dpy);
@@ -1797,6 +1817,75 @@
 	}
 	else
 		m->by = -bh;
+
+	updatedocks(m);
+}
+
+void
+updatedocks(Monitor *m) {
+	Client *c;
+
+	m->wx = m->mx;
+	m->ww = m->mw;
+
+	for(c = m->clients; c; c = c->next) {
+		if(!c->isdock)
+			continue;
+
+		/* Decide about where to position the dock. */
+		if(c->isdock == 1) {
+			if(c->w / c->h >= 1) {
+				/* horizontal */
+				if(c->y < m->mh / 2) {
+					/* top */
+					c->isdock = 2;
+				}
+				else {
+					/* bottom */
+					c->isdock = 3;
+				}
+			}
+			else {
+				/* vertical */
+				if(c->x < m->mw / 2) {
+					/* left */
+					c->isdock = 4;
+				}
+				else {
+					/* right */
+					c->isdock = 5;
+				}
+			}
+		}
+
+		switch(c->isdock) {
+		case 2:
+			/* top */
+			resize(c, m->wx, m->wy, m->ww, c->h, True);
+			m->wy += c->h;
+			m->wh -= c->h;
+			break;
+		default:
+		case 3:
+			/* bottom */
+			resize(c, m->wx, m->wy + m->wh - c->h, m->ww, \
+					c->h, True);
+			m->wh -= c->h;
+			break;
+		case 4:
+			/* left */
+			resize(c, m->wx, m->wy, c->w, m->wh, True);
+			m->wx += c->w;
+			m->ww -= c->w;
+			break;
+		case 5:
+			/* right */
+			resize(c, m->wx + m->ww - c->w, m->wy, c->w, \
+					m->wh, True);
+			m->ww -= c->w;
+			break;
+		}
+	}
 }
 
 Bool
@@ -1871,13 +1960,14 @@
 			dirty = True;
 			mons->mw = mons->ww = sw;
 			mons->mh = mons->wh = sh;
-			updatebarpos(mons);
 		}
 	}
 	if(dirty) {
 		selmon = mons;
 		selmon = wintomon(root);
 	}
+
+	updatebarpos(mons);
 	return dirty;
 }
 
@@ -1947,6 +2037,29 @@
 }
 
 void
+updatewindowtype(Client *c)
+{
+	Atom wtype, real;
+	int format;
+	unsigned long n, extra;
+	unsigned char *p = NULL;
+
+	if(XGetWindowProperty(dpy, c->win, netatom[NetWMWindowType], 0L,
+				sizeof(Atom), False, XA_ATOM, &real, &format,
+				&n, &extra, (unsigned char **)&p) == Success
+			&& p) {
+		wtype = *(Atom *)p;
+		XFree(p);
+
+		if(wtype == netatom[NetWMWindowTypeDock]) {
+			c->isdock = 1;
+			c->tags = 0xFFFFFFFF;
+			updatebarpos(c->mon);
+		}
+	}
+}
+
+void
 updatetitle(Client *c) {
 	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
 		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);

Reply via email to