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);
+}