Hello,

I'm switching from larswm to dwm and I made an attempt at porting the
features I use most.

So, here's the "pile" layout, which is a tiled layout where the tiles
are not resized to fit in screen - windows are just moved to the
right and stacked like a pile of cards.  There's an option to choose
whether the top-left ("piletop" layout) or bottom-left ("pilebottom")
corner of tiled windows should be left visible.  I use the bottom
variant, since it keeps the status lines of mutt, emacs and shell
prompts on screen.

Attached is the patch against dwm-4.0 sources.

Kudos to Anselm R. Garbe for the very clean code: it was easier to
port "pilebottom" to dwm than to write the original patch for larswm;
also, thanks to Ross Mohn for the bstack patch, which I took as a
starting point.

Ciao,
Riccardo
diff -BEbur dwm.orig/config.default.h dwm+pile/config.default.h
--- dwm.orig/config.default.h	2007-05-06 21:43:32.000000000 +0200
+++ dwm+pile/config.default.h	2007-05-08 21:41:55.000000000 +0200
@@ -31,6 +31,8 @@
 static Layout layout[] = { \
 	/* symbol		function */ \
 	{ "[]=",		tile }, /* first entry is default */ \
+        { "[]_",                pilebottom }, \
+        { "[]^",                piletop }, \
 	{ "><>",		floating }, \
 };
 #define MASTERWIDTH		600		/* master width per thousand */
@@ -53,6 +55,7 @@
 	{ MODKEY,			XK_k,		focusclient,	"-1" }, \
 	{ MODKEY,			XK_m,		togglemax,	NULL }, \
 	{ MODKEY,			XK_Return,	zoom,		NULL }, \
+        { MODKEY,                       XK_t,           top,            NULL }, \
 	{ MODKEY|ShiftMask,		XK_space,	togglefloating,	NULL }, \
 	{ MODKEY|ShiftMask,		XK_c,		killclient,	NULL }, \
 	{ MODKEY,			XK_0,		view,		NULL }, \
diff -BEbur dwm.orig/dwm.h dwm+pile/dwm.h
--- dwm.orig/dwm.h	2007-05-06 21:43:32.000000000 +0200
+++ dwm+pile/dwm.h	2007-05-08 21:43:23.000000000 +0200
@@ -127,6 +127,7 @@
 void restack(void);			/* restores z layers of all clients */
 void setlayout(const char *arg);		/* sets layout, -1 toggles */
 void togglemax(const char *arg);		/* toggles maximization of floating client */
+void top(const char* arg);              /* move selected window to top of visibility stack */
 void zoom(const char *arg);		/* zooms the focused client to master area, arg is ignored */
 
 /* main.c */
diff -BEbur dwm.orig/layout.c dwm+pile/layout.c
--- dwm.orig/layout.c	2007-05-06 21:43:32.000000000 +0200
+++ dwm+pile/layout.c	2007-05-08 21:19:40.000000000 +0200
@@ -65,6 +65,93 @@
 	restack();
 }
 
+static void
+_pile(const Bool top_visible) {
+        unsigned int i, n, np, nx, ny, nw, nh, mw, mh, tw, th;
+        Client *c;
+        Window *winstack;
+
+        for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
+                n++;
+        /* window geoms */
+        mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
+        mw = (n > nmaster) ? (waw * masterw) / 1000 : waw;
+        th = (n > nmaster) ? wah / (n - nmaster) : wah;
+        tw = waw - mw;
+
+        winstack = emallocz((n+1)*sizeof(Window));
+        winstack[0] = barwin; /* barwin always on top */
+        np = 0;
+        for(i = 0, c = clients; c; c = c->next)
+                if(isvisible(c)) {
+                        if(c->isbanned)
+                                XMoveWindow(dpy, c->win, c->x, c->y);
+                        c->isbanned = False;
+                        if(c->isfloating)
+                                continue;
+                        c->ismax = False;
+                        nx = wax;
+                        if(i < nmaster) {
+                                ny = way + i * mh;
+                                nw = mw - 2 * c->border;
+                                nh = mh - 2 * c->border;
+                        }
+                        else {  /* pile window */
+                          nx += mw;
+                          if (top_visible) {
+                            if(th > 2 * c->border)
+                              ny = way + wah - (i - nmaster + 1) * th;
+                            else
+                              ny = way;
+                          }
+                          else {
+                            if(th > 2 * c->border)
+                              {
+                                ny = way + (i - nmaster + 1) * th - mh;
+                              }
+                            else
+                              ny = way + wah - mh;
+                          }
+                          nw = mw - 2 * c->border;
+                          nh = mh - 2 * c->border;
+                          winstack[++np] = c->win;
+                        }
+                        resize(c, nx, ny, nw, nh, False);
+                        /* FIXME: if `resize(c, nx, ny, nw, nh,
+                        *  False);` only is used here, then windows
+                        *  are not moved back to the master area when
+                        *  the client in master area is
+                        *  killed.... why??
+                        */
+                        XMoveResizeWindow(dpy, c->win, nx, ny, nw, nh);
+                        i++;
+                }
+                else {
+                        c->isbanned = True;
+                        XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
+                }
+        if(!sel || !isvisible(sel)) {
+                for(c = stack; c && !isvisible(c); c = c->snext);
+                focus(c);
+        }
+        restack();
+
+        /* restack piled windows */
+        if (np > 0)
+          XRestackWindows(dpy, winstack, np+1);
+        free(winstack);
+}
+
+static void
+piletop(void) {
+  _pile(True);
+}
+
+static void 
+pilebottom(void) {
+  _pile(False);
+}
+
 LAYOUTS
 
 /* extern */
@@ -112,14 +199,13 @@
 	}
 	if(c) {
 		focus(c);
-		restack();
 	}
 }
 
 void
 incmasterw(const char *arg) {
 	int i;
-	if(lt->arrange != tile)
+        if(lt->arrange == floating)
 		return;
 	if(!arg)
 		masterw = MASTERWIDTH;
@@ -141,7 +227,7 @@
 		nmaster = NMASTER;
 	else {
 		i = atoi(arg);
-		if((lt->arrange != tile) || (nmaster + i < 1)
+                if(lt->arrange == floating || (nmaster + i < 1)
 		|| (wah / (nmaster + i) <= 2 * BORDERPX))
 			return;
 		nmaster += i;
@@ -181,15 +267,6 @@
 		return;
 	if(sel->isfloating || lt->arrange == floating)
 		XRaiseWindow(dpy, sel->win);
-	if(lt->arrange != floating) {
-		if(!sel->isfloating)
-			XLowerWindow(dpy, sel->win);
-		for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
-			if(c == sel)
-				continue;
-			XLowerWindow(dpy, c->win);
-		}
-	}
 	XSync(dpy, False);
 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 }
@@ -241,7 +318,7 @@
 	unsigned int n;
 	Client *c;
 
-	if(!sel || lt->arrange != tile || sel->isfloating)
+        if(!sel || lt->arrange == floating || sel->isfloating)
 		return;
 	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
 		n++;
@@ -253,3 +330,8 @@
 	focus(c);
 	lt->arrange();
 }
+
+void
+top(const char* arg) {
+  XRaiseWindow(dpy, sel->win);
+}

Reply via email to