Skip to content

Instantly share code, notes, and snippets.

@ropery
Created November 11, 2011 11:24
Show Gist options
  • Save ropery/1357788 to your computer and use it in GitHub Desktop.
Save ropery/1357788 to your computer and use it in GitHub Desktop.
diff -r 183cedbebe52 config.def.h
--- a/config.def.h Fri Nov 04 20:02:35 2011 +0100
+++ b/config.def.h Fri Nov 11 18:13:10 2011 +0800
@@ -32,6 +32,9 @@
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
+ { "TTT", bstack },
+ { "|||", col },
+ { "[]@", spiral },
};
/* key definitions */
@@ -66,6 +69,9 @@
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
+ { MODKEY, XK_s, setlayout, {.v = &layouts[3]} },
+ { MODKEY, XK_c, setlayout, {.v = &layouts[4]} },
+ { MODKEY, XK_e, setlayout, {.v = &layouts[5]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
diff -r 183cedbebe52 dwm.c
--- a/dwm.c Fri Nov 04 20:02:35 2011 +0100
+++ b/dwm.c Fri Nov 11 18:13:10 2011 +0800
@@ -55,6 +55,7 @@
#define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height)
/* enums */
+enum { CutLeft, CutTop, CutRight, CutBottom };
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
enum { NetSupported, NetWMName, NetWMState,
@@ -123,26 +124,9 @@
void (*arrange)(Monitor *);
} Layout;
-struct Monitor {
- char ltsymbol[16];
- float mfact;
- int nmaster;
- int num;
- int by; /* bar geometry */
- int mx, my, mw, mh; /* screen size */
- int wx, wy, ww, wh; /* window area */
- unsigned int seltags;
- unsigned int sellt;
- unsigned int tagset[2];
- Bool showbar;
- Bool topbar;
- Client *clients;
- Client *sel;
- Client *stack;
- Monitor *next;
- Window barwin;
- const Layout *lt[2];
-};
+typedef struct {
+ int x, y, w, h;
+} Rect;
typedef struct {
const char *class;
@@ -154,22 +138,29 @@
} Rule;
/* function declarations */
+static void applymslts(Monitor *m, int cut,
+ void (*mltf)(Client **, Rect *, unsigned int), /* master layout function */
+ void (*sltf)(Client **, Rect *, unsigned int)); /* slave layout function */
static void applyrules(Client *c);
static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
static void attach(Client *c);
+static void attachslave(Client *c);
static void attachstack(Client *c);
+static void bstack(Monitor *);
static void buttonpress(XEvent *e);
static void checkotherwm(void);
static void cleanup(void);
static void cleanupmon(Monitor *mon);
static void clearurgent(Client *c);
static void clientmessage(XEvent *e);
+static void col(Monitor *);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static Monitor *createmon(void);
+static void cutrect(int cut, float fact, Rect *r, Rect *t);
static void destroynotify(XEvent *e);
static void detach(Client *c);
static void detachstack(Client *c);
@@ -195,6 +186,9 @@
static void initfont(const char *fontstr);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
+static void lt_stackh(Client **c, Rect *r, unsigned int n);
+static void lt_stackv(Client **c, Rect *r, unsigned int n);
+static void lt_spiral(Client **c, Rect *r, unsigned int n);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void maprequest(XEvent *e);
@@ -208,6 +202,7 @@
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
+static void resizetocut(Client *c, int cut, float fact, Rect *r);
static void restack(Monitor *m);
static void run(void);
static void scan(void);
@@ -221,6 +216,7 @@
static void showhide(Client *c);
static void sigchld(int unused);
static void spawn(const Arg *arg);
+static void spiral(Monitor *);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static int textnw(const char *text, unsigned int len);
@@ -283,11 +279,70 @@
/* configuration, allows nested code to access above variables */
#include "config.h"
+struct Monitor {
+ char ltsymbol[16];
+ float mfact[LENGTH(layouts)];
+ int nmaster[LENGTH(layouts)];
+ int num;
+ int by; /* bar geometry */
+ int mx, my, mw, mh; /* screen size */
+ int wx, wy, ww, wh; /* window area */
+ unsigned int seltags;
+ unsigned int sellt;
+ unsigned int tagset[2];
+ Bool showbar;
+ Bool topbar;
+ Client *clients;
+ Client *sel;
+ Client *stack;
+ Monitor *next;
+ Window barwin;
+ const Layout *lt[2];
+};
+
/* compile-time check if all tags fit into an unsigned int bit array. */
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
/* function implementations */
void
+applymslts(Monitor *m, int cut,
+ void (*mltf)(Client **, Rect *, unsigned int),
+ void (*sltf)(Client **, Rect *, unsigned int)) {
+ unsigned int i, n;
+ Client *c;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if(n == 0)
+ return;
+
+ int nm;
+ float f;
+
+ i = m->lt[m->sellt] - layouts;
+ if(0 <= i && i < LENGTH(layouts)) {
+ f = m->mfact[i];
+ nm = m->nmaster[i];
+ }
+ else {
+ f = mfact;
+ nm = nmaster;
+ }
+
+ Rect rm, r = { m->wx, m->wy, m->ww, m->wh };
+
+ c = m->clients;
+ if(nm == 0 || mltf == NULL)
+ (*sltf)(&c, &r, n);
+ else if(n > nm) {
+ cutrect(cut, f, &r, &rm);
+ (*mltf)(&c, &rm, nm);
+ (*sltf)(&c, &r, n - nm);
+ }
+ else
+ (*mltf)(&c, &r, n);
+}
+
+void
applyrules(Client *c) {
const char *class, *instance;
unsigned int i;
@@ -419,6 +474,32 @@
c->mon->stack = c;
}
+/* attach as the first slave, if all master seats are taken */
+void
+attachslave(Client *c) {
+ Client *tc;
+ int i, n;
+
+ if(!(tc = nexttiled(c->mon->clients)) || !c->mon->sel || c->isfloating) {
+ attach(c);
+ return;
+ }
+ i = c->mon->lt[c->mon->sellt] - layouts;
+ n = 0 <= i && i < LENGTH(layouts) ? c->mon->nmaster[i] : nmaster;
+ for(i = 1; tc && i < n; tc = nexttiled(tc->next), i++);
+ if(n == 0 || !tc) {
+ attach(c);
+ return;
+ }
+ c->next = tc->next;
+ tc->next = c;
+}
+
+void
+bstack(Monitor *m) {
+ applymslts(m, CutTop, lt_stackh, lt_stackh);
+}
+
void
buttonpress(XEvent *e) {
unsigned int i, x, click;
@@ -567,6 +648,11 @@
}
void
+col(Monitor *m) {
+ applymslts(m, CutLeft, lt_stackh, lt_stackv);
+}
+
+void
configure(Client *c) {
XConfigureEvent ce;
@@ -663,12 +749,15 @@
Monitor *
createmon(void) {
Monitor *m;
+ unsigned int i;
if(!(m = (Monitor *)calloc(1, sizeof(Monitor))))
die("fatal: could not malloc() %u bytes\n", sizeof(Monitor));
m->tagset[0] = m->tagset[1] = 1;
- m->mfact = mfact;
- m->nmaster = nmaster;
+ for(i = 0; i < LENGTH(layouts); i++) {
+ m->mfact[i] = mfact;
+ m->nmaster[i] = nmaster;
+ }
m->showbar = showbar;
m->topbar = topbar;
m->lt[0] = &layouts[0];
@@ -678,6 +767,33 @@
}
void
+cutrect(int cut, float fact, Rect *r, Rect *t) {
+ fact = fact > 1 ? 1 : (fact < 0 ? 0 : fact);
+ t->x = r->x;
+ t->y = r->y;
+ t->w = r->w;
+ t->h = r->h;
+ switch(cut) {
+ case CutLeft:
+ r->x += t->w * fact;
+ r->w += t->x - r->x;
+ t->w -= r->w;
+ break;
+ case CutTop:
+ r->y += t->h * fact;
+ r->h += t->y - r->y;
+ t->h -= r->h;
+ break;
+ case CutRight:
+ cutrect(CutLeft, 1 - fact, t, r);
+ break;
+ case CutBottom:
+ cutrect(CutTop, 1 - fact, t, r);
+ break;
+ }
+}
+
+void
destroynotify(XEvent *e) {
Client *c;
XDestroyWindowEvent *ev = &e->xdestroywindow;
@@ -1030,8 +1146,18 @@
void
incnmaster(const Arg *arg) {
- selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
- arrange(selmon);
+ if(!arg || !selmon->lt[selmon->sellt]->arrange)
+ return;
+ int n;
+ unsigned int i;
+ i = selmon->lt[selmon->sellt] - layouts;
+ if(0 <= i && i < LENGTH(layouts)) {
+ n = MAX(selmon->nmaster[i] + arg->i, 0);
+ if(n != selmon->nmaster[i]) {
+ selmon->nmaster[i] = n;
+ arrange(selmon);
+ }
+ }
}
void
@@ -1110,6 +1236,35 @@
}
void
+lt_stackh(Client **c, Rect *r, unsigned int n) {
+ unsigned int i;
+
+ for(i = 0, *c = nexttiled(*c); *c && i < n; *c = nexttiled((*c)->next), i++) {
+ resizetocut(*c, CutLeft, 1.0 / (n - i), r);
+ }
+}
+
+void
+lt_stackv(Client **c, Rect *r, unsigned int n) {
+ unsigned int i;
+
+ for(i = 0, *c = nexttiled(*c); *c && i < n; *c = nexttiled((*c)->next), i++) {
+ resizetocut(*c, CutTop, 1.0 / (n - i), r);
+ }
+}
+
+void
+lt_spiral(Client **c, Rect *r, unsigned int n) {
+ const float f = 0.5;
+ int cut = CutTop, i;
+
+ for(i = 0, *c = nexttiled(*c); *c && i < n; *c = nexttiled((*c)->next), i++) {
+ resizetocut(*c, cut, n - i == 1 ? 1 : f, r);
+ cut = cut == CutTop ? CutRight : cut == CutRight ? CutBottom : cut == CutBottom ? CutLeft : CutTop;
+ }
+}
+
+void
manage(Window w, XWindowAttributes *wa) {
Client *c, *t = NULL;
Window trans = None;
@@ -1163,7 +1318,7 @@
c->isfloating = c->oldstate = trans != None || c->isfixed;
if(c->isfloating)
XRaiseWindow(dpy, c->win);
- attach(c);
+ attachslave(c);
attachstack(c);
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
setclientstate(c, NormalState);
@@ -1402,6 +1557,39 @@
}
void
+resizetocut(Client *c, int cut, float fact, Rect *r) {
+ int x = r->x, y = r->y, w = r->w, h = r->h;
+
+ fact = fact > 1 ? 1 : (fact < 0 ? 0 : fact);
+ switch(cut) {
+ case CutLeft:
+ resize(c, r->x, r->y, r->w * fact - 2 * c->bw, r->h - 2 * c->bw, False);
+ w = WIDTH(c);
+ r->x += w;
+ r->w -= w;
+ break;
+ case CutTop:
+ resize(c, r->x, r->y, r->w - 2 * c->bw, r->h * fact - 2 * c->bw, False);
+ h = HEIGHT(c);
+ r->y += h;
+ r->h -= h;
+ break;
+ case CutRight:
+ w *= fact;
+ x += r->w - w;
+ r->w -= w;
+ resize(c, x, y, w - 2 * c->bw, h - 2 * c->bw, False);
+ break;
+ case CutBottom:
+ h *= fact;
+ y += r->h - h;
+ r->h -= h;
+ resize(c, x, y, w - 2 * c->bw, h - 2 * c->bw, False);
+ break;
+ }
+}
+
+void
restack(Monitor *m) {
Client *c;
XEvent ev;
@@ -1531,15 +1719,18 @@
/* arg > 1.0 will set mfact absolutly */
void
setmfact(const Arg *arg) {
- float f;
-
if(!arg || !selmon->lt[selmon->sellt]->arrange)
return;
- f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- if(f < 0.1 || f > 0.9)
- return;
- selmon->mfact = f;
- arrange(selmon);
+ float f;
+ unsigned int i;
+ i = selmon->lt[selmon->sellt] - layouts;
+ if(0 <= i && i < LENGTH(layouts)) {
+ f = arg->f < 1.0 ? arg->f + selmon->mfact[i] : arg->f - 1.0;
+ if(f != selmon->mfact[i] && f >= 0.1 && f <= 0.9) {
+ selmon->mfact[i] = f;
+ arrange(selmon);
+ }
+ }
}
void
@@ -1638,6 +1829,11 @@
}
void
+spiral(Monitor *m) {
+ applymslts(m, CutRight, lt_spiral, lt_stackv);
+}
+
+void
tag(const Arg *arg) {
if(selmon->sel && arg->ui & TAGMASK) {
selmon->sel->tags = arg->ui & TAGMASK;
@@ -1666,28 +1862,7 @@
void
tile(Monitor *m) {
- unsigned int i, n, h, mw, my, ty;
- Client *c;
-
- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
- if(n == 0)
- return;
-
- if(n > m->nmaster)
- mw = m->nmaster ? m->ww * m->mfact : 0;
- else
- mw = m->ww;
- for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
- if(i < m->nmaster) {
- h = (m->wh - my) / (MIN(n, m->nmaster) - i);
- resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False);
- my += HEIGHT(c);
- }
- else {
- h = (m->wh - ty) / (n - i);
- resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False);
- ty += HEIGHT(c);
- }
+ applymslts(m, CutLeft, lt_stackv, lt_stackv);
}
void
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment