-- - typedef struct { - const char *class; - const char *instance; -_AT_@ -239,6 +219,9 @@ static int xerror(Display *dpy, XErrorEv - static int xerrordummy(Display *dpy, XErrorEvent *ee); - static int xerrorstart(Display *dpy, XErrorEvent *ee); - static void zoom(const Arg *arg); -+static void mirrorlayout(const Arg *arg); -+static void rotatelayoutaxis(const Arg *arg); -+static void shiftmastersplit(const Arg *arg); - - /* variables */ - static const char broken[] = "broken"; -_AT_@ -276,6 +259,34 @@ static Window root; - - /* compile-time check if all tags fit into an unsigned int bit array. */ - struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; }; -+struct Monitor { -+ char ltsymbol[16]; -+ float mfact; -+ 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]; -+ int curtag; -+ int prevtag; -+ const Layout *lts[LENGTH(tags) + 1]; -+ double mfacts[LENGTH(tags) + 1]; -+ Bool showbars[LENGTH(tags) + 1]; -+ int ltaxis[3]; -+ unsigned int msplit; -+ int ltaxes[LENGTH(tags) + 1][3]; -+ unsigned int msplits[LENGTH(tags) + 1]; -+}; - - /* function implementations */ - void -_AT_@ -617,6 +628,10 @@ createmon(void) { - m->lt[0] = &layouts[0]; - m->lt[1] = &layouts[1 % LENGTH(layouts)]; - strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); -+ m->ltaxis[0] = layoutaxis[0]; -+ m->ltaxis[1] = layoutaxis[1]; -+ m->ltaxis[2] = layoutaxis[2]; -+ m->msplit = mastersplit; - return m; - } - -_AT_@ -1467,7 +1482,7 @@ setlayout(const Arg *arg) { - if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if(arg && arg->v) -- selmon->lt[selmon->sellt] = (Layout *)arg->v; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); - if(selmon->sel) - arrange(selmon); -_AT_@ -1485,14 +1500,16 @@ setmfact(const Arg *arg) { - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; - if(f < 0.1 || f > 0.9) - return; -- selmon->mfact = f; -+ selmon->mfact = selmon->mfacts[selmon->curtag] = f; - arrange(selmon); - } - - void - setup(void) { - XSetWindowAttributes wa; -- -+ Monitor *m; -+ unsigned int i; -+ - /* clean up any zombies immediately */ - sigchld(0); - -_AT_@ -1526,7 +1543,19 @@ setup(void) { - XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); - if(!dc.font.set) - XSetFont(dpy, dc.gc, dc.font.xfont->fid); -- /* init bars */ -+ /* init tags, bars, layouts, axes, msplits and mfacts */ -+ for(m = mons; m; m = m->next) { -+ m->curtag = m->prevtag = 1; -+ for(i=0; i < LENGTH(tags) + 1; i++) { -+ m->showbars[i] = m->showbar; -+ m->lts[i] = &layouts[0]; -+ m->mfacts[i] = m->mfact; -+ m->ltaxes[i][0] = m->ltaxis[0]; -+ m->ltaxes[i][1] = m->ltaxis[1]; -+ m->ltaxes[i][2] = m->ltaxis[2]; -+ m->msplits[i] = m->msplit; -+ } -+ } - updatebars(); - updatestatus(); - /* EWMH support per view */ -_AT_@ -1607,37 +1636,132 @@ textnw(const char *text, unsigned int le - - void - tile(Monitor *m) { -- int x, y, h, w, mw; -- unsigned int i, n; -+ char sym1 = 61, sym2 = 93, sym3 = 61, sym; -+ int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1; -+ int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2; -+ unsigned int i, n, n1, n2; - Client *c; - - for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); -+ if(m->msplit > n) -+ m->msplit = (n == 0) ? 1 : n; -+ if(n == 0 && m->ltaxis[1] != 3) -+ return; -+ /* layout symbol */ -+ if(abs(m->ltaxis[0]) == m->ltaxis[1]) /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */ -+ sym1 = 124; -+ if(abs(m->ltaxis[0]) == m->ltaxis[2]) -+ sym3 = 124; -+ if(m->ltaxis[1] == 3) -+ sym1 = (n == 0) ? 0 : m->msplit; -+ if(m->ltaxis[2] == 3) -+ sym3 = (n == 0) ? 0 : n - m->msplit; -+ if(m->ltaxis[0] < 0) { -+ sym = sym1; -+ sym1 = sym3; -+ sym2 = 91; -+ sym3 = sym; -+ } -+ if(m->msplit == 1) { -+ if(m->ltaxis[0] > 0) -+ sym1 = 91; -+ else -+ sym3 = 93; -+ } -+ if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3); -+ else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0)) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3); -+ else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0)) -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3); -+ else -+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); - if(n == 0) - return; -+ /* master and stack area */ -+ if(abs(m->ltaxis[0]) == 1 && n > m->msplit) { -+ w1 *= m->mfact; -+ w2 -= w1; -+ x1 += (m->ltaxis[0] < 0) ? w2 : 0; -+ x2 += (m->ltaxis[0] < 0) ? 0 : w1; -+ X1 = x1 + w1; -+ X2 = x2 + w2; -+ } else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) { -+ h1 *= m->mfact; -+ h2 -= h1; -+ y1 += (m->ltaxis[0] < 0) ? h2 : 0; -+ y2 += (m->ltaxis[0] < 0) ? 0 : h1; -+ Y1 = y1 + h1; -+ Y2 = y2 + h2; -+ } - /* master */ -- c = nexttiled(m->clients); -- mw = m->mfact * m->ww; -- resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); -- if(--n == 0) -- return; -- /* tile stack */ -- x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; -- y = m->wy; -- w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; -- h = m->wh / n; -- if(h < bh) -- h = m->wh; -- for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { -- resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) -- ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); -- if(h != m->wh) -- y = c->y + HEIGHT(c); -+ n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit; -+ n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit; -+ for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) { -+ resize(c, x1, y1, -+ (m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, -+ (m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False); -+ if(n1 > 1) -+ x1 = c->x + WIDTH(c); -+ if(n2 > 1) -+ y1 = c->y + HEIGHT(c); -+ } -+ /* stack */ -+ if(n > m->msplit) { -+ n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; -+ n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; -+ for(i = 0; c; c = nexttiled(c->next), i++) { -+ resize(c, x2, y2, -+ (m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, -+ (m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False); -+ if(n1 > 1) -+ x2 = c->x + WIDTH(c); -+ if(n2 > 1) -+ y2 = c->y + HEIGHT(c); -+ } - } - } - - void -+mirrorlayout(const Arg *arg) { -+ if(!selmon->lt[selmon->sellt]->arrange) -+ return; -+ selmon->ltaxis[0] *= -1; -+ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0]; -+ arrange(selmon); -+} -+ -+void -+rotatelayoutaxis(const Arg *arg) { -+ if(!selmon->lt[selmon->sellt]->arrange) -+ return; -+ if(arg->i == 0) { -+ if(selmon->ltaxis[0] > 0) -+ selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1; -+ else -+ selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1; -+ } else -+ selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1; -+ selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i]; -+ arrange(selmon); -+} -+ -+void -+shiftmastersplit(const Arg *arg) { -+ unsigned int n; -+ Client *c; -+ -+ for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++); -+ if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n) -+ return; -+ selmon->msplit += arg->i; -+ selmon->msplits[selmon->curtag] = selmon->msplit; -+ arrange(selmon); -+} -+ -+void - togglebar(const Arg *arg) { -- selmon->showbar = !selmon->showbar; -+ selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar; - updatebarpos(selmon); - XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); - arrange(selmon); -_AT_@ -1657,12 +1781,31 @@ togglefloating(const Arg *arg) { - void - toggletag(const Arg *arg) { - unsigned int newtags; -+ unsigned int i; - - if(!selmon->sel) - return; - newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); - if(newtags) { - selmon->sel->tags = newtags; -+ if(newtags == ~0) { -+ selmon->prevtag = selmon->curtag; -+ selmon->curtag = 0; -+ } -+ if(!(newtags & 1 << (selmon->curtag - 1))) { -+ selmon->prevtag = selmon->curtag; -+ for (i=0; !(newtags & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ selmon->sel->tags = newtags; -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; -+ if (selmon->showbar != selmon->showbars[selmon->curtag]) -+ togglebar(NULL); -+ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; -+ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; -+ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; -+ selmon->msplit = selmon->msplits[selmon->curtag]; - arrange(selmon); - } - } -_AT_@ -1929,11 +2072,33 @@ updatewmhints(Client *c) { - - void - view(const Arg *arg) { -+ unsigned int i; -+ - if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - return; - selmon->seltags ^= 1; /* toggle sel tagset */ -- if(arg->ui & TAGMASK) -+ if(arg->ui & TAGMASK) { - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; -+ selmon->prevtag = selmon->curtag; -+ if(arg->ui == ~0) -+ selmon->curtag = 0; -+ else { -+ for (i=0; !(arg->ui & 1 << i); i++); -+ selmon->curtag = i + 1; -+ } -+ } else { -+ selmon->prevtag = selmon->curtag ^ selmon->prevtag; -+ selmon->curtag ^= selmon->prevtag; -+ selmon->prevtag = selmon->curtag ^ selmon->prevtag; -+ } -+ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; -+ selmon->mfact = selmon->mfacts[selmon->curtag]; -+ if(selmon->showbar != selmon->showbars[selmon->curtag]) -+ togglebar(NULL); -+ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; -+ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; -+ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; -+ selmon->msplit = selmon->msplits[selmon->curtag]; - arrange(selmon); - } - diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/flextile-5.8.2.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwm.suckless.org/patches/flextile-5.8.2.diff Fri Jun 11 16:47:32 2010 +0200 _AT_@ -0,0 +1,398 @@ +diff -up ../dwm-5.8.2-0/config.def.h ./config.def.h +--- ../dwm-5.8.2-0/config.def.h 2010-06-10 22:47:51.660949000 +0200 ++++ ./config.def.h 2010-06-10 22:55:53.094322000 +0200 +_AT_@ -16,6 +16,9 @@ static const Bool topbar = Tr + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + ++/* include(s) depending on the tags array */ ++#include "flextile.h" ++ + static const Rule rules[] = { + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, True, -1 }, +_AT_@ -25,6 +28,11 @@ static const Rule rules[] = { + /* layout(s) */ + static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ + static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ ++static const int layoutaxis[] = { ++ 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */ ++ 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ ++ 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ ++}; + + static const Layout layouts[] = { + /* symbol arrange function */ +_AT_@ -81,6 +89,12 @@ static Key keys[] = { + TAGKEYS( XK_8, 7) + TAGKEYS( XK_9, 8) + { MODKEY|ShiftMask, XK_q, quit, {0} }, ++ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0} }, /* 0 = layout axis */ ++ { MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1} }, /* 1 = master axis */ ++ { MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2} }, /* 2 = stack axis */ ++ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} }, ++ { MODKEY|ControlMask, XK_h, shiftmastersplit, {.i = -1} }, /* reduce the number of tiled clients in the master area */ ++ { MODKEY|ControlMask, XK_l, shiftmastersplit, {.i = +1} }, /* increase the number of tiled clients in the master area */ + }; + + /* button definitions */ +diff -up ../dwm-5.8.2-0/dwm.c ./dwm.c +--- ../dwm-5.8.2-0/dwm.c 2010-06-10 22:47:51.669677000 +0200 ++++ ./dwm.c 2010-06-10 22:55:53.128305000 +0200 +_AT_@ -122,26 +122,6 @@ typedef struct { + void (*arrange)(Monitor *); + } Layout; + +-struct Monitor { +- char ltsymbol[16]; +- float mfact; +- 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 { + const char *class; + const char *instance; +_AT_@ -621,6 +601,10 @@ createmon(void) { + m->lt[0] = &layouts[0]; + m->lt[1] = &layouts[1 % LENGTH(layouts)]; + strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); ++ m->ltaxis[0] = layoutaxis[0]; ++ m->ltaxis[1] = layoutaxis[1]; ++ m->ltaxis[2] = layoutaxis[2]; ++ m->msplit = 1; + return m; + } + +_AT_@ -1494,7 +1478,7 @@ setlayout(const Arg *arg) { + if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if(arg && arg->v) +- selmon->lt[selmon->sellt] = (Layout *)arg->v; ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v; + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol); + if(selmon->sel) + arrange(selmon); +_AT_@ -1512,14 +1496,16 @@ setmfact(const Arg *arg) { + f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; + if(f < 0.1 || f > 0.9) + return; +- selmon->mfact = f; ++ selmon->mfact = selmon->mfacts[selmon->curtag] = f; + arrange(selmon); + } + + void + setup(void) { + XSetWindowAttributes wa; +- ++ Monitor *m; ++ unsigned int i; ++ + /* clean up any zombies immediately */ + sigchld(0); + +_AT_@ -1555,7 +1541,19 @@ setup(void) { + XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); + if(!dc.font.set) + XSetFont(dpy, dc.gc, dc.font.xfont->fid); +- /* init bars */ ++ /* init tags, bars, layouts, axes, msplits and mfacts */ ++ for(m = mons; m; m = m->next) { ++ m->curtag = m->prevtag = 1; ++ for(i=0; i < LENGTH(tags) + 1; i++) { ++ m->showbars[i] = m->showbar; ++ m->lts[i] = &layouts[0]; ++ m->mfacts[i] = m->mfact; ++ m->ltaxes[i][0] = m->ltaxis[0]; ++ m->ltaxes[i][1] = m->ltaxis[1]; ++ m->ltaxes[i][2] = m->ltaxis[2]; ++ m->msplits[i] = m->msplit; ++ } ++ } + updatebars(); + updatestatus(); + /* EWMH support per view */ +_AT_@ -1635,38 +1633,8 @@ textnw(const char *text, unsigned int le + } + + void +-tile(Monitor *m) { +- int x, y, h, w, mw; +- unsigned int i, n; +- Client *c; +- +- for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); +- if(n == 0) +- return; +- /* master */ +- c = nexttiled(m->clients); +- mw = m->mfact * m->ww; +- resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False); +- if(--n == 0) +- return; +- /* tile stack */ +- x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw; +- y = m->wy; +- w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw; +- h = m->wh / n; +- if(h < bh) +- h = m->wh; +- for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) { +- resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n) +- ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False); +- if(h != m->wh) +- y = c->y + HEIGHT(c); +- } +-} +- +-void + togglebar(const Arg *arg) { +- selmon->showbar = !selmon->showbar; ++ selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar; + updatebarpos(selmon); + XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh); + arrange(selmon); +_AT_@ -1686,12 +1654,31 @@ togglefloating(const Arg *arg) { + void + toggletag(const Arg *arg) { + unsigned int newtags; ++ unsigned int i; + + if(!selmon->sel) + return; + newtags = selmon->sel->tags ^ (arg->ui & TAGMASK); + if(newtags) { + selmon->sel->tags = newtags; ++ if(newtags == ~0) { ++ selmon->prevtag = selmon->curtag; ++ selmon->curtag = 0; ++ } ++ if(!(newtags & 1 << (selmon->curtag - 1))) { ++ selmon->prevtag = selmon->curtag; ++ for (i=0; !(newtags & 1 << i); i++); ++ selmon->curtag = i + 1; ++ } ++ selmon->sel->tags = newtags; ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; ++ selmon->mfact = selmon->mfacts[selmon->curtag]; ++ if (selmon->showbar != selmon->showbars[selmon->curtag]) ++ togglebar(NULL); ++ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; ++ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; ++ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; ++ selmon->msplit = selmon->msplits[selmon->curtag]; + arrange(selmon); + } + } +_AT_@ -1959,11 +1946,33 @@ updatewmhints(Client *c) { + + void + view(const Arg *arg) { ++ unsigned int i; ++ + if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + return; + selmon->seltags ^= 1; /* toggle sel tagset */ +- if(arg->ui & TAGMASK) ++ if(arg->ui & TAGMASK) { + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; ++ selmon->prevtag = selmon->curtag; ++ if(arg->ui == ~0) ++ selmon->curtag = 0; ++ else { ++ for (i=0; !(arg->ui & 1 << i); i++); ++ selmon->curtag = i + 1; ++ } ++ } else { ++ selmon->prevtag = selmon->curtag ^ selmon->prevtag; ++ selmon->curtag ^= selmon->prevtag; ++ selmon->prevtag = selmon->curtag ^ selmon->prevtag; ++ } ++ selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag]; ++ selmon->mfact = selmon->mfacts[selmon->curtag]; ++ if(selmon->showbar != selmon->showbars[selmon->curtag]) ++ togglebar(NULL); ++ selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0]; ++ selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1]; ++ selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2]; ++ selmon->msplit = selmon->msplits[selmon->curtag]; + arrange(selmon); + } + +diff -up ../dwm-5.8.2-0/flextile.h ./flextile.h +--- ../dwm-5.8.2-0/flextile.h 2010-06-10 23:08:24.000000000 +0200 ++++ ./flextile.h 2010-06-10 22:59:20.632706000 +0200 +_AT_@ -0,0 +1,159 @@ ++/* See LICENSE file for copyright and license details. */ ++/* © 2010 joten <joten_AT_freenet.de> */ ++ ++struct Monitor { ++ char ltsymbol[16]; ++ float mfact; ++ double mfacts[LENGTH(tags) + 1]; ++ int ltaxis[3]; ++ int ltaxes[LENGTH(tags) + 1][3]; ++ int num; ++ int curtag; ++ int prevtag; ++ int by; /* bar geometry */ ++ int mx, my, mw, mh; /* screen size */ ++ int wx, wy, ww, wh; /* window area */ ++ unsigned int msplit; ++ unsigned int msplits[LENGTH(tags) + 1]; ++ unsigned int seltags; ++ unsigned int sellt; ++ unsigned int tagset[2]; ++ Bool showbar; ++ Bool showbars[LENGTH(tags) + 1]; ++ Bool topbar; ++ Client *clients; ++ Client *sel; ++ Client *stack; ++ Monitor *next; ++ Window barwin; ++ const Layout *lt[2]; ++ const Layout *lts[LENGTH(tags) + 1]; ++}; ++ ++/* function declarations */ ++static void mirrorlayout(const Arg *arg); ++static void rotatelayoutaxis(const Arg *arg); ++static void shiftmastersplit(const Arg *arg); ++ ++void ++mirrorlayout(const Arg *arg) { ++ if(!selmon->lt[selmon->sellt]->arrange) ++ return; ++ selmon->ltaxis[0] *= -1; ++ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0]; ++ arrange(selmon); ++} ++ ++void ++rotatelayoutaxis(const Arg *arg) { ++ if(!selmon->lt[selmon->sellt]->arrange) ++ return; ++ if(arg->i == 0) { ++ if(selmon->ltaxis[0] > 0) ++ selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1; ++ else ++ selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1; ++ } else ++ selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1; ++ selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i]; ++ arrange(selmon); ++} ++ ++void ++shiftmastersplit(const Arg *arg) { ++ unsigned int n; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++); ++ if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n) ++ return; ++ selmon->msplit += arg->i; ++ selmon->msplits[selmon->curtag] = selmon->msplit; ++ arrange(selmon); ++} ++ ++void ++tile(Monitor *m) { ++ char sym1 = 61, sym2 = 93, sym3 = 61, sym; ++ int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1; ++ int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2; ++ unsigned int i, n, n1, n2; ++ Client *c; ++ ++ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); ++ if(m->msplit > n) ++ m->msplit = (n == 0) ? 1 : n; ++ /* layout symbol */ ++ if(abs(m->ltaxis[0]) == m->ltaxis[1]) /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */ ++ sym1 = 124; ++ if(abs(m->ltaxis[0]) == m->ltaxis[2]) ++ sym3 = 124; ++ if(m->ltaxis[1] == 3) ++ sym1 = (n == 0) ? 0 : m->msplit; ++ if(m->ltaxis[2] == 3) ++ sym3 = (n == 0) ? 0 : n - m->msplit; ++ if(m->ltaxis[0] < 0) { ++ sym = sym1; ++ sym1 = sym3; ++ sym2 = 91; ++ sym3 = sym; ++ } ++ if(m->msplit == 1) { ++ if(m->ltaxis[0] > 0) ++ sym1 = 91; ++ else ++ sym3 = 93; ++ } ++ if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3); ++ else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0)) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3); ++ else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0)) ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3); ++ else ++ snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3); ++ if(n == 0) ++ return; ++ /* master and stack area */ ++ if(abs(m->ltaxis[0]) == 1 && n > m->msplit) { ++ w1 *= m->mfact; ++ w2 -= w1; ++ x1 += (m->ltaxis[0] < 0) ? w2 : 0; ++ x2 += (m->ltaxis[0] < 0) ? 0 : w1; ++ X1 = x1 + w1; ++ X2 = x2 + w2; ++ } else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) { ++ h1 *= m->mfact; ++ h2 -= h1; ++ y1 += (m->ltaxis[0] < 0) ? h2 : 0; ++ y2 += (m->ltaxis[0] < 0) ? 0 : h1; ++ Y1 = y1 + h1; ++ Y2 = y2 + h2; ++ } ++ /* master */ ++ n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit; ++ n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit; ++ for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) { ++ resize(c, x1, y1, ++ (m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, ++ (m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False); ++ if(n1 > 1) ++ x1 = c->x + WIDTH(c); ++ if(n2 > 1) ++ y1 = c->y + HEIGHT(c); ++ } ++ /* stack */ ++ if(n > m->msplit) { ++ n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; ++ n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit; ++ for(i = 0; c; c = nexttiled(c->next), i++) { ++ resize(c, x2, y2, ++ (m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, ++ (m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False); ++ if(n1 > 1) ++ x2 = c->x + WIDTH(c); ++ if(n2 > 1) ++ y2 = c->y + HEIGHT(c); ++ } ++ } ++} diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/flextile.md --- a/dwm.suckless.org/patches/flextile.md Fri Jun 11 08:39:06 2010 +0000 +++ b/dwm.suckless.org/patches/flextile.md Fri Jun 11 16:47:32 2010 +0200 _AT_@ -2,20 +2,20 @@ ## Description ## -This patch replaces the tile layout with a more flexible version. The features include the following: +This patch replaces the `tile` layout with a more flexible version. The features include the following: * tile like the original version (left single master, right stack) - * left/right/top/bottom n-master, right/left/bottom/top/no stack/deck (deck is like monocle in the stack area) + * left/right/top/bottom n-master, right/left/bottom/top/no stack/deck (deck is like `monocle` in the stack area) * per-tag configuration It therefor provides i. a. the following additional possibilities: - * tile for left-handed people + * `tile` for left-handed people * compare multiple files with one other each at a time without switching between views The patch incorporates and expands the following patches: - * bottom stack (bstack and bstackhoriz) + * bottom stack (`bstack` and `bstackhoriz`) * nmaster * pertag _AT_@ -24,19 +24,23 @@ (1) Download the patch and apply it according to the [general instructions](.). - (2) Transfer the changes made by the patch in 'config.def.h' to your 'config.h', if needed. + (2) Transfer the changes made by the patch in `config.def.h` to your `config.h`, if needed. - In the 'layout(s)' section: + /* tagging */ + ... + /* include(s) depending on the tags array */ + #include "flextile.h" - static const int layoutaxis[] = { - 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */ - 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ - 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ - }; - static const unsigned int mastersplit = 1; /* number of tiled clients in the master area */ + /* layout(s) */ + static const int layoutaxis[] = { + 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */ + 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ + 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */ + }; + static const unsigned int mastersplit = 1; /* number of tiled clients in the master area */ - In the 'keys' array: - + static Key keys[] = { + ... { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0} }, /* 0 = layout axis */ { MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1} }, /* 1 = master axis */ { MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2} }, /* 2 = stack axis */ _AT_@ -47,14 +51,16 @@ ## Usage ## -With the default configuration (see above) the original tile layout is emulated. You can change the layout by adjusting the four parameters 'layout axis', 'master axis', 'stack axis' and 'master split' (description see above) by pressing the appropriate keys. -The original tile layout is only available by setting the above parameters, but not as a discrete layout; the 'monocle' layout is still available by pressing 'ALT+m' (in the default configuration). +With the default configuration (see above) the original tile layout is emulated. You can change the layout by adjusting the four parameters `layout axis`, `master axis`, `stack axis` and `master split` (description see above) by pressing the appropriate keys. +The original `tile` layout is only available by setting the above parameters, but not as a discrete layout; the `monocle` layout is still available by pressing `ALT+m` (in the default configuration). ## Download ## - * [flextile-5.8.1.diff][1] (14k) (20100531, joten <joten (at) freenet (dot) de>) + * [flextile-5.8.1.diff][1] (14k) (20100531, joten (at) freenet (dot) de) + * [flextile-5.8.2.diff][2] (13k, +169 SLOC) (20100611, joten (at) freenet (dot) de) [1]: http://dwm.suckless.org/patches/flextile-5.8.1.diff +[2]: http://dwm.suckless.org/patches/flextile-5.8.2.diff diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes-5.8.2-vim.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwm.suckless.org/patches/keymodes-5.8.2-vim.diff Fri Jun 11 16:47:32 2010 +0200 _AT_@ -0,0 +1,583 @@ +diff -up ../dwm-5.8.2-1/config.def.h ./config.def.h +--- ../dwm-5.8.2-1/config.def.h 2010-06-11 01:10:05.465026000 +0200 ++++ ./config.def.h 2010-06-11 01:13:49.211525000 +0200 +_AT_@ -19,6 +19,9 @@ static const char *tags[] = { "1", "2", + /* include(s) depending on the tags array */ + #include "flextile.h" + ++/* include(s) defining functions */ ++#include "keymodes.pre.h" ++ + static const Rule rules[] = { + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, True, -1 }, +_AT_@ -36,9 +39,9 @@ static const int layoutaxis[] = { + + static const Layout layouts[] = { + /* symbol arrange function */ +- { "[]=", tile }, /* first entry is default */ ++ { "[M]", monocle }, /* first entry is default */ ++ { "[]=", tile }, + { "><>", NULL }, /* no layout function means floating behavior */ +- { "[M]", monocle }, + }; + + /* key definitions */ +_AT_@ -55,9 +58,11 @@ static const Layout layouts[] = { + /* commands */ + static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "uxterm", NULL }; ++static const char *helpcmd[] = { "uxterm", "-e", "man", "dwm", NULL }; + + static Key keys[] = { + /* modifier key function argument */ ++ { MODKEY, XK_Escape, setkeymode, {.ui = COMMANDMODE} }, + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +_AT_@ -68,9 +73,9 @@ static Key keys[] = { + { MODKEY, XK_Return, zoom, {0} }, + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, +- { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, +- { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, ++ { MODKEY, XK_m, setlayout, {.v = &layouts[0]} }, ++ { MODKEY, XK_t, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, XK_f, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, +_AT_@ -97,6 +102,54 @@ static Key keys[] = { + { MODKEY|ControlMask, XK_l, shiftmastersplit, {.i = +1} }, /* increase the number of tiled clients in the master area */ + }; + ++static const int h_master[] = {+1, 2, 2}; ++static const int j_master[] = {-2, 1, 1}; ++static const int k_master[] = {+2, 1, 1}; ++static const int l_master[] = {-1, 2, 2}; ++ ++static Key cmdkeys[] = { ++ /* modifier keys function argument */ ++ { 0, XK_Escape, clearcmd, {0} }, ++ { ControlMask, XK_c, clearcmd, {0} }, ++ { 0, XK_i, setkeymode, {.ui = INSERTMODE} }, ++}; ++static Command commands[] = { ++ /* modifier (4 keys) keysyms (4 keys) function argument */ ++ { {0, 0, 0, 0}, {XK_g, XK_t, 0, 0}, adjacentview, {.i = +1} }, ++ { {0, ShiftMask, 0, 0}, {XK_g, XK_t, 0, 0}, adjacentview, {.i = -1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_c, 0, 0}, closewindow, {0} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_h, 0, 0}, focustiled, {.i = -1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_j, 0, 0}, focustiled, {.i = +2} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_k, 0, 0}, focustiled, {.i = -2} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_l, 0, 0}, focustiled, {.i = +1} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_h, 0, 0}, setmaster, {.v = h_master} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_j, 0, 0}, setmaster, {.v = j_master} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_k, 0, 0}, setmaster, {.v = k_master} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_l, 0, 0}, setmaster, {.v = l_master} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_o, 0, 0}, setlayout, {.v = &layouts[0]} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_o, 0, 0}, onlyclient, {0} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_s, 0, 0}, split, {.ui = 2} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_t, 0, 0}, adjacenttag, {.i = +1} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_t, 0, 0}, adjacenttag, {.i = -1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_v, 0, 0}, split, {.ui = 1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_x, 0, 0}, exchangewindow, {.i = +1} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_x, 0, 0}, exchangewindow, {.i = -1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_w, 0, 0}, focuswindow, {.i = +1} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_w, 0, 0}, focuswindow, {.i = -1} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_less, 0, 0}, resizemaster, {.f = -10.05} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_less, 0, 0}, resizemaster, {.f = +10.05} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_minus, 0, 0}, resizemaster, {.f = -20.05} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_plus, 0, 0}, resizemaster, {.f = +20.05} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_0, 0, 0}, setmfact, {.f = +1.50} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_e, 0, 0}, spawn, {.v = dmenucmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_o, 0, 0}, spawn, {.v = dmenucmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_h, XK_Return, 0}, spawn, {.v = helpcmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_q, XK_Return, 0}, quit, {0} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_b, XK_d, XK_Return}, killclient, {0} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_b, XK_n, XK_Return}, focusstack, {.i = +1} }, ++ { {ShiftMask, 0, ShiftMask, 0}, {XK_period, XK_b, XK_n, XK_Return}, focusstack, {.i = -1} }, ++}; ++ + /* button definitions */ + /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ + static Button buttons[] = { +_AT_@ -114,3 +167,5 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ++/* include(s) depending on the configuration variables */ ++#include "keymodes.post.h" +diff -up ../dwm-5.8.2-1/dwm.c ./dwm.c +--- ../dwm-5.8.2-1/dwm.c 2010-06-11 01:10:05.473958000 +0200 ++++ ./dwm.c 2010-06-11 01:13:49.226865000 +0200 +_AT_@ -954,7 +954,7 @@ grabbuttons(Client *c, Bool focused) { + } + + void +-grabkeys(void) { ++grabdefkeys(void) { + updatenumlockmask(); + { + unsigned int i, j; +_AT_@ -1036,7 +1036,7 @@ isuniquegeom(XineramaScreenInfo *unique, + #endif /* XINERAMA */ + + void +-keypress(XEvent *e) { ++defkeypress(XEvent *e) { + unsigned int i; + KeySym keysym; + XKeyEvent *ev; +diff -up ../dwm-5.8.2-1/keymodes.post.h ./keymodes.post.h +--- ../dwm-5.8.2-1/keymodes.post.h 2010-06-11 01:12:53.000000000 +0200 ++++ ./keymodes.post.h 2010-06-11 01:13:49.287434000 +0200 +_AT_@ -0,0 +1,409 @@ ++/* See LICENSE file for copyright and license details. */ ++/* © 2010 joten <joten_AT_freenet.de> */ ++ ++/* function implementations */ ++void ++adjacenttag(const Arg *arg) { ++ int nexttag = selmon->curtag + arg->i; ++ Arg a; ++ ++ if(nexttag > LENGTH(tags)) ++ nexttag = 1; ++ else if(nexttag < 1) ++ nexttag = LENGTH(tags); ++ a.ui = 1 << (nexttag - 1); ++ tag(&a); ++} ++ ++void ++adjacentview(const Arg *arg) { ++ int nexttag = selmon->curtag + arg->i; ++ Arg a; ++ ++ if(nexttag > LENGTH(tags)) ++ nexttag = 1; ++ else if(nexttag < 1) ++ nexttag = LENGTH(tags); ++ a.ui = 1 << (nexttag - 1); ++ view(&a); ++} ++ ++void ++clearcmd(const Arg *arg) { ++ unsigned int i; ++ ++ for(i = 0; i < LENGTH(cmdkeysym); i++) { ++ cmdkeysym[i] = 0; ++ cmdmod[i] = 0; ++ } ++} ++ ++void ++closewindow(const Arg *arg) { ++ unsigned int j, n; ++ Client *i; ++ ++ if(!selmon->sel || selmon->sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile) ++ return; ++ for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++) ++ if(i == selmon->sel) ++ j = n + 1; ++ if(j == 0 || n < 2) ++ return; ++ if(j <= selmon->msplit) { ++ if(selmon->ltaxis[1] == 3 || selmon->msplit == 1) { ++ selmon->msplits[selmon->curtag] = selmon->msplit = n; ++ selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = selmon->ltaxis[2]; ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3; ++ } else if(j == selmon->msplit && (selmon->ltaxis[2] == 3 || selmon->msplit == n - 1)) { ++ selmon->msplits[selmon->curtag] = selmon->msplit -= 1; ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3; ++ } else ++ selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3; ++ } else { ++ if(selmon->ltaxis[2] == 3 || selmon->msplit == n - 1) ++ selmon->msplits[selmon->curtag] = selmon->msplit = n; ++ else if(j == selmon->msplit + 1 && (selmon->ltaxis[1] == 3 || selmon->msplit == 1)) { ++ selmon->msplits[selmon->curtag] = selmon->msplit += 1; ++ selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3; ++ } else ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3; ++ } ++ arrange(selmon); ++} ++ ++void ++exchangewindow(const Arg *arg) { ++ int j = 0, n; ++ Client *c, *i, *sel = selmon->sel; ++ ++ if(!sel || sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile) ++ return; ++ for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++) ++ if(i == selmon->sel) ++ j = n + 1; ++ if(j == 0 || n < 2 ++ || (j <= selmon->msplit && selmon->ltaxis[1] == 3 && selmon->msplit > 1 && !(j == 1 && arg->i < 0) && !(j == selmon->msplit && arg->i > 0)) ++ || (j > selmon->msplit && selmon->ltaxis[2] == 3 && n - selmon->msplit > 1 && !(j == selmon->msplit + 1 && arg->i < 0) && !(j == n && arg->i > 0))) ++ return; ++ if(arg->i < 0) { ++ if((c = prevtiled(sel))) { ++ /* attach before c */ ++ detach(sel); ++ sel->next = c; ++ if(selmon->clients == c) ++ selmon->clients = sel; ++ else { ++ for(c = selmon->clients; c->next != sel->next; c = c->next); ++ c->next = sel; ++ } ++ } else { ++ /* move to the end */ ++ for(c = sel; c->next; c = c->next); ++ detach(sel); ++ sel->next = NULL; ++ c->next = sel; ++ } ++ } else { ++ if((c = nexttiled(sel->next))) { ++ /* attach after c */ ++ detach(sel); ++ sel->next = c->next; ++ c->next = sel; ++ } else { ++ /* move to the front */ ++ detach(sel); ++ attach(sel); ++ } ++ } ++ focus(sel); ++ arrange(selmon); ++} ++ ++void ++focustiled(const Arg *arg) { ++ float f; ++ unsigned int j = 0, k, n; ++ Client *c = NULL, *i; ++ ++ if(!selmon->sel || selmon->sel->isfloating || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile)) ++ return; ++ for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++) ++ if(i == selmon->sel) ++ j = n + 1; ++ if(n < 2) ++ return; ++ if(arg->i < 0 ++ && ((j > 1 && j <= selmon->msplit && selmon->ltaxis[1] == -(arg->i)) || (j > (selmon->msplit + 1) && j <= n && selmon->ltaxis[2] == -(arg->i)))) { ++ c = prevtiled(selmon->sel); ++ } else if(arg->i > 0 ++ && ((j > 0 && j < selmon->msplit && selmon->ltaxis[1] == arg->i) || (j > selmon->msplit && j < n && selmon->ltaxis[2] == arg->i))) { ++ c = nexttiled(selmon->sel->next); ++ } else if(arg->i < 0 ++ && n > selmon->msplit ++ && j > selmon->msplit && j <= n ++ && (selmon->ltaxis[2] - arg->i) == 3) ++ f = (float)(j - selmon->msplit) / (n - selmon->msplit) * selmon->msplit; ++ else if(arg->i > 0 ++ && n > selmon->msplit ++ && j > 0 && j <= selmon->msplit ++ && (selmon->ltaxis[1] + arg->i) == 3) ++ f = selmon->msplit + (float)j / selmon->msplit * (n - selmon->msplit); ++ if(f > 0) { ++ k = (unsigned int)f; ++ if(f - k > 0) ++ k++; ++ for(j = 1, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), j++) ++ if(j == k) ++ c = i; ++ } ++ if(c) { ++ focus(c); ++ restack(selmon); ++ } ++} ++ ++void ++focuswindow(const Arg *arg) { ++ unsigned int j = 0, k = 0, n; ++ Client *c = NULL, *i; ++ ++ if(!selmon->sel || selmon->sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile) ++ return; ++ for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++) ++ if(i == selmon->sel) ++ j = n + 1; ++ if(j == 0 || n < 2 || (selmon->msplit == n && selmon->ltaxis[1] == 3)) ++ return; ++ if(arg->i < 0) { ++ if((j > 1 && j <= selmon->msplit && selmon->ltaxis[1] == 3) || j == 1) { ++ k = n; ++ } else if(j > selmon->msplit + 1 && j <= n && selmon->ltaxis[2] == 3) { ++ k = selmon->msplit; ++ } else ++ c = prevtiled(selmon->sel); ++ } else { ++ if(j < selmon->msplit && selmon->ltaxis[1] == 3) { ++ k = selmon->msplit + 1; ++ } else if((j > selmon->msplit && j < n && selmon->ltaxis[2] == 3) || j == n) { ++ k = 1; ++ } else ++ c = nexttiled(selmon->sel->next); ++ } ++ if(!c && k) ++ for(j = 1, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), j++) ++ if(j == k) ++ c = i; ++ if(c) { ++ focus(c); ++ restack(selmon); ++ } ++} ++ ++void ++grabkeys(void) { ++ if(keymode == INSERTMODE) { ++ grabdefkeys(); ++ } else if(keymode == COMMANDMODE) { ++ XUngrabKey(dpy, AnyKey, AnyModifier, root); ++ XGrabKey(dpy, AnyKey, AnyModifier, root, ++ True, GrabModeAsync, GrabModeAsync); ++ } ++} ++ ++void ++keypress(XEvent *e) { ++ unsigned int i, j; ++ Arg a = {0}; ++ Bool ismatch = False, maybematch = False; ++ KeySym keysym; ++ XKeyEvent *ev; ++ ++ if(keymode == INSERTMODE) ++ defkeypress(e); ++ else if(keymode == COMMANDMODE) { ++ ev = &e->xkey; ++ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); ++ if(keysym < XK_Shift_L || keysym > XK_Hyper_R) { ++ for(i = 0; i < LENGTH(cmdkeys); i++) ++ if(keysym == cmdkeys[i].keysym ++ && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state) ++ && cmdkeys[i].func) { ++ cmdkeys[i].func(&(cmdkeys[i].arg)); ++ ismatch = True; ++ break; ++ } ++ if(!ismatch) { ++ for(j = 0; j < LENGTH(cmdkeysym); j++) ++ if(cmdkeysym[j] == 0) { ++ cmdkeysym[j] = keysym; ++ cmdmod[j] = ev->state; ++ break; ++ } ++ for(i = 0; i < LENGTH(commands); i++) { ++ for(j = 0; j < LENGTH(cmdkeysym); j++) { ++ if(cmdkeysym[j] == commands[i].keysym[j] ++ && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j])) ++ ismatch = True; ++ else if(cmdkeysym[j] == 0 ++ && cmdmod[j] == 0) { ++ ismatch = False; ++ maybematch = True; ++ break; ++ } else { ++ ismatch = False; ++ break; ++ } ++ } ++ if(ismatch) { ++ if(commands[i].func) ++ commands[i].func(&(commands[i].arg)); ++ clearcmd(&a); ++ break; ++ } ++ ++ } ++ if(!maybematch) ++ clearcmd(&a); ++ } ++ } ++ } ++} ++ ++void ++onlyclient(const Arg *arg) { ++ Client *c; ++ XEvent ev; ++ ++ if(!selmon->sel) ++ return; ++ for(c = selmon->clients; c; c = c->next) ++ if(c != selmon->sel && ISVISIBLE(c)) { ++ if(isprotodel(c)) { ++ ev.type = ClientMessage; ++ ev.xclient.window = c->win; ++ ev.xclient.message_type = wmatom[WMProtocols]; ++ ev.xclient.format = 32; ++ ev.xclient.data.l[0] = wmatom[WMDelete]; ++ ev.xclient.data.l[1] = CurrentTime; ++ XSendEvent(dpy, c->win, False, NoEventMask, &ev); ++ } ++ else { ++ XGrabServer(dpy); ++ XSetErrorHandler(xerrordummy); ++ XSetCloseDownMode(dpy, DestroyAll); ++ XKillClient(dpy, c->win); ++ XSync(dpy, False); ++ XSetErrorHandler(xerror); ++ XUngrabServer(dpy); ++ } ++ } ++} ++ ++Client * ++prevtiled(Client *c) { ++ Client *i, *p; ++ ++ for(i = selmon->clients, p = NULL; i && i != c; i = i->next) ++ if(!i->isfloating && ISVISIBLE(i)) ++ p = i; ++ return p; ++} ++ ++void ++resizemaster(const Arg *arg) { ++ float f; ++ Arg a; ++ ++ if(!arg || selmon->lt[selmon->sellt]->arrange != tile) ++ return; ++ f = (arg->f < 0 ? -arg->f : arg->f) - selmon->ltaxis[0] * 10; ++ if(f < 0 || f > 1.9) ++ return; ++ a.f = arg->f / abs(arg->f) * f; ++ setmfact(&a); ++} ++ ++void ++setkeymode(const Arg *arg) { ++ Arg a = {0}; ++ ++ if(!arg) ++ return; ++ keymode = arg->ui; ++ clearcmd(&a); ++ grabkeys(); ++} ++ ++void ++setmaster(const Arg *arg) { ++ unsigned int i; ++ Arg a; ++ ++ if(!arg || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile)) ++ return; ++ for(i = 0; i < 3; i++) ++ selmon->ltaxes[selmon->curtag][i] = selmon->ltaxis[i] = ((int *)arg->i)[i]; ++ selmon->msplits[selmon->curtag] = selmon->msplit = 1; ++ if(selmon->sel && !selmon->sel->isfloating && selmon->sel != nexttiled(selmon->clients)) { ++ detach(selmon->sel); ++ attach(selmon->sel); ++ focus(selmon->sel); ++ } ++ if(selmon->lt[selmon->sellt]->arrange == monocle) { ++ for(i = 0; i < LENGTH(layouts) && (&layouts[i])->arrange != tile; i++); ++ a.v = &layouts[i]; ++ setlayout(&a); ++ if(!selmon->sel) ++ arrange(selmon); ++ } else ++ arrange(selmon); ++} ++ ++void ++split(const Arg *arg) { ++ unsigned int j = 0, k, n; ++ Arg a; ++ Client *i; ++ ++ if(!arg || !selmon->sel || selmon->sel->isfloating || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile)) ++ return; ++ for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++) ++ if(i == selmon->sel) ++ j = n + 1; ++ if(j == 0 || n < 2) ++ return; ++ if(selmon->lt[selmon->sellt]->arrange == monocle) { ++ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0] = arg->i; ++ selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3; ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3; ++ for(k = 0; k < LENGTH(layouts) && (&layouts[k])->arrange != tile; k++); ++ a.v = &layouts[k]; ++ setlayout(&a); ++ } else if(j <= selmon->msplit) { ++ if(selmon->ltaxis[1] == 3 || selmon->msplit == 1) { ++ selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = arg->i; ++ if(selmon->ltaxis[2] == 3 || selmon->msplit == 1) ++ selmon->msplits[selmon->curtag] = selmon->msplit = 2; ++ arrange(selmon); ++ } else if(selmon->ltaxis[1] == arg->i && selmon->msplit < n) { ++ selmon->msplits[selmon->curtag] = selmon->msplit += 1; ++ arrange(selmon); ++ } else if(selmon->ltaxis[1] + arg->i == 3 && selmon->msplit == n) { ++ selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0] = arg->i; ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3; ++ selmon->msplits[selmon->curtag] = selmon->msplit = n - 1; ++ arrange(selmon); ++ } ++ } else if(n > 2) { ++ if(selmon->ltaxis[2] == 3 || selmon->msplit == n - 1) { ++ selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = arg->i; ++ if(selmon->ltaxis[1] == 3 || selmon->msplit == n - 1) ++ selmon->msplits[selmon->curtag] = selmon->msplit = n - 2; ++ arrange(selmon); ++ } else if(selmon->ltaxis[2] == arg->i && selmon->msplit > 1) { ++ selmon->msplits[selmon->curtag] = selmon->msplit -= 1; ++ arrange(selmon); ++ } ++ } ++} +diff -up ../dwm-5.8.2-1/keymodes.pre.h ./keymodes.pre.h +--- ../dwm-5.8.2-1/keymodes.pre.h 2010-06-11 01:12:49.000000000 +0200 ++++ ./keymodes.pre.h 2010-06-11 01:13:50.660576000 +0200 +_AT_@ -0,0 +1,34 @@ ++/* See LICENSE file for copyright and license details. */ ++/* © 2010 joten <joten_AT_freenet.de> */ ++ ++#define COMMANDMODE 1 ++#define INSERTMODE 2 ++ ++typedef struct { ++ unsigned int mod[4]; ++ KeySym keysym[4]; ++ void (*func)(const Arg *); ++ const Arg arg; ++} Command; ++ ++/* function declarations */ ++static void adjacenttag(const Arg *arg); ++static void adjacentview(const Arg *arg); ++static void clearcmd(const Arg *arg); ++static void closewindow(const Arg *arg); ++static void defkeypress(XEvent *e); ++static void exchangewindow(const Arg *arg); ++static void focustiled(const Arg *arg); ++static void focuswindow(const Arg *arg); ++static void grabdefkeys(void); ++static void onlyclient(const Arg *arg); ++static Client *prevtiled(Client *c); ++static void resizemaster(const Arg *arg); ++static void setkeymode(const Arg *arg); ++static void setmaster(const Arg *arg); ++static void split(const Arg *arg); ++ ++/* variables */ ++static unsigned int cmdmod[4]; ++static unsigned int keymode = COMMANDMODE; ++static KeySym cmdkeysym[4]; diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes-5.8.2.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwm.suckless.org/patches/keymodes-5.8.2.diff Fri Jun 11 16:47:32 2010 +0200 _AT_@ -0,0 +1,239 @@ +diff -up ../dwm-5.8.2-0/config.def.h ./config.def.h +--- ../dwm-5.8.2-0/config.def.h 2010-06-10 22:47:51.660949000 +0200 ++++ ./config.def.h 2010-06-11 00:18:55.082073000 +0200 +_AT_@ -16,6 +16,9 @@ static const Bool topbar = Tr + /* tagging */ + static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + ++/* include(s) defining functions */ ++#include "keymodes.pre.h" ++ + static const Rule rules[] = { + /* class instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, 0, True, -1 }, +_AT_@ -47,9 +50,11 @@ static const Layout layouts[] = { + /* commands */ + static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL }; + static const char *termcmd[] = { "uxterm", NULL }; ++static const char *helpcmd[] = { "uxterm", "-e", "man", "dwm", NULL }; + + static Key keys[] = { + /* modifier key function argument */ ++ { MODKEY, XK_Escape, setkeymode, {.ui = COMMANDMODE} }, + { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, + { MODKEY, XK_b, togglebar, {0} }, +_AT_@ -83,6 +88,30 @@ static Key keys[] = { + { MODKEY|ShiftMask, XK_q, quit, {0} }, + }; + ++static Key cmdkeys[] = { ++ /* modifier keys function argument */ ++ { 0, XK_Escape, clearcmd, {0} }, ++ { ControlMask, XK_c, clearcmd, {0} }, ++ { 0, XK_i, setkeymode, {.ui = INSERTMODE} }, ++}; ++static Command commands[] = { ++ /* modifier (4 keys) keysyms (4 keys) function argument */ ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_h, 0, 0}, setlayout, {.v = &layouts[0]} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_o, 0, 0}, setlayout, {.v = &layouts[2]} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_o, 0, 0}, onlyclient, {0} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_v, 0, 0}, setlayout, {.v = &layouts[0]} }, ++ { {ControlMask, 0, 0, 0}, {XK_w, XK_less, 0, 0}, setmfact, {.f = -0.05} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_less, 0, 0}, setmfact, {.f = +0.05} }, ++ { {ControlMask, ShiftMask, 0, 0}, {XK_w, XK_0, 0, 0}, setmfact, {.f = +1.50} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_e, 0, 0}, spawn, {.v = dmenucmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_o, 0, 0}, spawn, {.v = dmenucmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_h, XK_Return, 0}, spawn, {.v = helpcmd} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_q, XK_Return, 0}, quit, {0} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_b, XK_d, XK_Return}, killclient, {0} }, ++ { {ShiftMask, 0, 0, 0}, {XK_period, XK_b, XK_n, XK_Return}, focusstack, {.i = +1} }, ++ { {ShiftMask, 0, ShiftMask, 0}, {XK_period, XK_b, XK_n, XK_Return}, focusstack, {.i = -1} }, ++}; ++ + /* button definitions */ + /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ + static Button buttons[] = { +_AT_@ -100,3 +129,5 @@ static Button buttons[] = { + { ClkTagBar, MODKEY, Button3, toggletag, {0} }, + }; + ++/* include(s) depending on the configuration variables */ ++#include "keymodes.post.h" +diff -up ../dwm-5.8.2-0/dwm.c ./dwm.c +--- ../dwm-5.8.2-0/dwm.c 2010-06-10 22:47:51.669677000 +0200 ++++ ./dwm.c 2010-06-11 00:18:55.106090000 +0200 +_AT_@ -970,7 +970,7 @@ grabbuttons(Client *c, Bool focused) { + } + + void +-grabkeys(void) { ++grabdefkeys(void) { + updatenumlockmask(); + { + unsigned int i, j; +_AT_@ -1052,7 +1052,7 @@ isuniquegeom(XineramaScreenInfo *unique, + #endif /* XINERAMA */ + + void +-keypress(XEvent *e) { ++defkeypress(XEvent *e) { + unsigned int i; + KeySym keysym; + XKeyEvent *ev; +diff -up ../dwm-5.8.2-0/keymodes.post.h ./keymodes.post.h +--- ../dwm-5.8.2-0/keymodes.post.h 2010-06-11 00:21:46.000000000 +0200 ++++ ./keymodes.post.h 2010-06-11 00:18:55.119222000 +0200 +_AT_@ -0,0 +1,124 @@ ++/* See LICENSE file for copyright and license details. */ ++/* © 2010 joten <joten_AT_freenet.de> */ ++ ++/* function implementations */ ++void ++clearcmd(const Arg *arg) { ++ unsigned int i; ++ ++ for(i = 0; i < LENGTH(cmdkeysym); i++) { ++ cmdkeysym[i] = 0; ++ cmdmod[i] = 0; ++ } ++} ++ ++void ++grabkeys(void) { ++ if(keymode == INSERTMODE) { ++ grabdefkeys(); ++ } else if(keymode == COMMANDMODE) { ++ XUngrabKey(dpy, AnyKey, AnyModifier, root); ++ XGrabKey(dpy, AnyKey, AnyModifier, root, ++ True, GrabModeAsync, GrabModeAsync); ++ } ++} ++ ++void ++keypress(XEvent *e) { ++ unsigned int i, j; ++ Arg a = {0}; ++ Bool ismatch = False, maybematch = False; ++ KeySym keysym; ++ XKeyEvent *ev; ++ ++ if(keymode == INSERTMODE) ++ defkeypress(e); ++ else if(keymode == COMMANDMODE) { ++ ev = &e->xkey; ++ keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); ++ if(keysym < XK_Shift_L || keysym > XK_Hyper_R) { ++ for(i = 0; i < LENGTH(cmdkeys); i++) ++ if(keysym == cmdkeys[i].keysym ++ && CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state) ++ && cmdkeys[i].func) { ++ cmdkeys[i].func(&(cmdkeys[i].arg)); ++ ismatch = True; ++ break; ++ } ++ if(!ismatch) { ++ for(j = 0; j < LENGTH(cmdkeysym); j++) ++ if(cmdkeysym[j] == 0) { ++ cmdkeysym[j] = keysym; ++ cmdmod[j] = ev->state; ++ break; ++ } ++ for(i = 0; i < LENGTH(commands); i++) { ++ for(j = 0; j < LENGTH(cmdkeysym); j++) { ++ if(cmdkeysym[j] == commands[i].keysym[j] ++ && CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j])) ++ ismatch = True; ++ else if(cmdkeysym[j] == 0 ++ && cmdmod[j] == 0) { ++ ismatch = False; ++ maybematch = True; ++ break; ++ } else { ++ ismatch = False; ++ break; ++ } ++ } ++ if(ismatch) { ++ if(commands[i].func) ++ commands[i].func(&(commands[i].arg)); ++ clearcmd(&a); ++ break; ++ } ++ ++ } ++ if(!maybematch) ++ clearcmd(&a); ++ } ++ } ++ } ++} ++ ++void ++onlyclient(const Arg *arg) { ++ Client *c; ++ XEvent ev; ++ ++ if(!selmon->sel) ++ return; ++ for(c = selmon->clients; c; c = c->next) ++ if(c != selmon->sel && ISVISIBLE(c)) { ++ if(isprotodel(c)) { ++ ev.type = ClientMessage; ++ ev.xclient.window = c->win; ++ ev.xclient.message_type = wmatom[WMProtocols]; ++ ev.xclient.format = 32; ++ ev.xclient.data.l[0] = wmatom[WMDelete]; ++ ev.xclient.data.l[1] = CurrentTime; ++ XSendEvent(dpy, c->win, False, NoEventMask, &ev); ++ } ++ else { ++ XGrabServer(dpy); ++ XSetErrorHandler(xerrordummy); ++ XSetCloseDownMode(dpy, DestroyAll); ++ XKillClient(dpy, c->win); ++ XSync(dpy, False); ++ XSetErrorHandler(xerror); ++ XUngrabServer(dpy); ++ } ++ } ++} ++ ++void ++setkeymode(const Arg *arg) { ++ Arg a = {0}; ++ ++ if(!arg) ++ return; ++ keymode = arg->ui; ++ clearcmd(&a); ++ grabkeys(); ++} +diff -up ../dwm-5.8.2-0/keymodes.pre.h ./keymodes.pre.h +--- ../dwm-5.8.2-0/keymodes.pre.h 2010-06-11 00:21:38.000000000 +0200 ++++ ./keymodes.pre.h 2010-06-11 00:18:55.121759000 +0200 +_AT_@ -0,0 +1,24 @@ ++/* See LICENSE file for copyright and license details. */ ++/* © 2010 joten <joten_AT_freenet.de> */ ++ ++#define COMMANDMODE 1 ++#define INSERTMODE 2 ++ ++typedef struct { ++ unsigned int mod[4]; ++ KeySym keysym[4]; ++ void (*func)(const Arg *); ++ const Arg arg; ++} Command; ++ ++/* function declarations */ ++static void clearcmd(const Arg *arg); ++static void defkeypress(XEvent *e); ++static void grabdefkeys(void); ++static void onlyclient(const Arg *arg); ++static void setkeymode(const Arg *arg); ++ ++/* variables */ ++static unsigned int cmdmod[4]; ++static unsigned int keymode = COMMANDMODE; ++static KeySym cmdkeysym[4]; diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwm.suckless.org/patches/keymodes.md Fri Jun 11 16:47:32 2010 +0200 _AT_@ -0,0 +1,56 @@ +# KEYMODES # + +## Description ## + +This patch provides key modes (like in Vim). There are two key modes: + + 1. `COMMANDMODE`: In this mode any key is grabbed and only the registered command keys have any effect. + 2. `INSERTMODE`: This is the normal key mode, in which the original key bindings of dwm and applications are effective and text can be entered. + +With key modes you can use any key binding for window management without risking conflicts with existing key bindings in applications. + +There are two different patches: + + * keymodes: the minimal patch + * vim-keymodes: This patch tries to emulate the key bindings of Vim. Therefor it includes additional functions, which depend on the [flextile patch](../flextile). + + +## Configuration ## + + (1) Download the favoured patch and apply it according to the [general instructions](.). If you choose vim-keymodes you will have to apply the flextile patch first. + + (2) Transfer the changes made by the patch in 'config.def.h' to your 'config.h', if needed; please see the patch file for details. + + (3) Verify the following lines in the aforementioned arrays: + + static Key keys[] = { + /* modifier key function argument */ + { MODKEY, XK_Escape, setkeymode, {.ui = COMMANDMODE} }, + + static Key cmdkeys[] = { + /* modifier keys function argument */ + { 0, XK_Escape, clearcmd, {0} }, + { ControlMask, XK_c, clearcmd, {0} }, + { 0, XK_i, setkeymode, {.ui = INSERTMODE} }, + }; + static Command commands[] = { + /* modifier (4 keys) keysyms (4 keys) function argument */ + ... + }; + + The entries in the `cmdkeys` array are defined like those in the original `keys` array of dwm and take precedence over the key bindings defined in the `commands` array. The modifier and keysym definitions in the `commands` array are themselves arrays with four entries, whereas the first entry in the modifier array corresponds to the first entry in the keysym array and so forth. + + +## Usage ## + +With this patch dwm starts in `COMMANDMODE` and you can use the key bindings as defined in the `commands` array in `config.h`. Press `Escape` or `CTRL+c` to abort a command input and press `i` (in the default configuration) to enter `INSERTMODE` and use dwm normally with the key bindings defined in the `keys` array, navigate in applications and insert text. To get from `INSERTMODE` to `COMMANDMODE` press `ALT+Escape` (in the default configuration). + + +## Download ## + + * [keymodes-5.8.2.diff][1] (8.4k, +152 SLOC) (20100611, joten (at) freenet (dot) de) + * [keymodes-5.8.2-vim.diff][2] (22k, +446 SLOC) (20100611, joten (at) freenet (dot) de) + + +[1]: http://dwm.suckless.org/patches/keymodes-5.8.2.diff +[2]: http://dwm.suckless.org/patches/keymodes-5.8.2-vim.diffReceived on Fri Jun 11 2010 - 16:47:44 CEST
This archive was generated by hypermail 2.3.0 : Thu Sep 13 2012 - 19:31:18 CEST