dwm-stacker-6.0.diff (6401B)
1 diff --git a/config.def.h b/config.def.h 2 index 77ff358..566e0c7 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -41,6 +41,14 @@ static const Layout layouts[] = { 6 { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 7 { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 8 { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, 9 +#define STACKKEYS(MOD,ACTION) \ 10 + { MOD, XK_j, ACTION##stack, {.i = INC(+1) } }, \ 11 + { MOD, XK_k, ACTION##stack, {.i = INC(-1) } }, \ 12 + { MOD, XK_grave, ACTION##stack, {.i = PREVSEL } }, \ 13 + { MOD, XK_q, ACTION##stack, {.i = 0 } }, \ 14 + { MOD, XK_a, ACTION##stack, {.i = 1 } }, \ 15 + { MOD, XK_z, ACTION##stack, {.i = 2 } }, \ 16 + { MOD, XK_x, ACTION##stack, {.i = -1 } }, 17 18 /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 19 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 20 @@ -54,8 +62,8 @@ static Key keys[] = { 21 { MODKEY, XK_p, spawn, {.v = dmenucmd } }, 22 { MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } }, 23 { MODKEY, XK_b, togglebar, {0} }, 24 - { MODKEY, XK_j, focusstack, {.i = +1 } }, 25 - { MODKEY, XK_k, focusstack, {.i = -1 } }, 26 + STACKKEYS(MODKEY, focus) 27 + STACKKEYS(MODKEY|ShiftMask, push) 28 { MODKEY, XK_i, incnmaster, {.i = +1 } }, 29 { MODKEY, XK_d, incnmaster, {.i = -1 } }, 30 { MODKEY, XK_h, setmfact, {.f = -0.05} }, 31 @@ -83,7 +91,7 @@ static Key keys[] = { 32 TAGKEYS( XK_7, 6) 33 TAGKEYS( XK_8, 7) 34 TAGKEYS( XK_9, 8) 35 - { MODKEY|ShiftMask, XK_q, quit, {0} }, 36 + { MODKEY|ShiftMask, XK_BackSpace, quit, {0} }, 37 }; 38 39 /* button definitions */ 40 diff --git a/dwm.c b/dwm.c 41 index 1d78655..6129f56 100644 42 --- a/dwm.c 43 +++ b/dwm.c 44 @@ -43,17 +43,23 @@ 45 /* macros */ 46 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) 47 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) 48 +#define GETINC(X) ((X) - 2000) 49 +#define INC(X) ((X) + 2000) 50 #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 51 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 52 +#define ISINC(X) ((X) > 1000 && (X) < 3000) 53 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) 54 +#define PREVSEL 3000 55 #define LENGTH(X) (sizeof X / sizeof X[0]) 56 #define MAX(A, B) ((A) > (B) ? (A) : (B)) 57 #define MIN(A, B) ((A) < (B) ? (A) : (B)) 58 +#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) 59 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) 60 #define WIDTH(X) ((X)->w + 2 * (X)->bw) 61 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 62 #define TAGMASK ((1 << LENGTH(tags)) - 1) 63 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) 64 +#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) 65 66 /* enums */ 67 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 68 @@ -205,6 +211,7 @@ static void movemouse(const Arg *arg); 69 static Client *nexttiled(Client *c); 70 static void pop(Client *); 71 static void propertynotify(XEvent *e); 72 +static void pushstack(const Arg *arg); 73 static void quit(const Arg *arg); 74 static Monitor *recttomon(int x, int y, int w, int h); 75 static void resize(Client *c, int x, int y, int w, int h, Bool interact); 76 @@ -224,6 +231,7 @@ static void setup(void); 77 static void showhide(Client *c); 78 static void sigchld(int unused); 79 static void spawn(const Arg *arg); 80 +static int stackpos(const Arg *arg); 81 static void tag(const Arg *arg); 82 static void tagmon(const Arg *arg); 83 static int textnw(const char *text, unsigned int len); 84 @@ -887,28 +895,16 @@ focusmon(const Arg *arg) { 85 86 void 87 focusstack(const Arg *arg) { 88 - Client *c = NULL, *i; 89 + int i = stackpos(arg); 90 + Client *c, *p; 91 92 - if(!selmon->sel) 93 + if(i < 0) 94 return; 95 - if(arg->i > 0) { 96 - for(c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); 97 - if(!c) 98 - for(c = selmon->clients; c && !ISVISIBLE(c); c = c->next); 99 - } 100 - else { 101 - for(i = selmon->clients; i != selmon->sel; i = i->next) 102 - if(ISVISIBLE(i)) 103 - c = i; 104 - if(!c) 105 - for(; i; i = i->next) 106 - if(ISVISIBLE(i)) 107 - c = i; 108 - } 109 - if(c) { 110 - focus(c); 111 - restack(selmon); 112 - } 113 + 114 + for(p = NULL, c = selmon->clients; c && (i || !ISVISIBLE(c)); 115 + i -= ISVISIBLE(c) ? 1 : 0, p = c, c = c->next); 116 + focus(c ? c : p); 117 + restack(selmon); 118 } 119 120 Atom 121 @@ -1324,6 +1320,29 @@ propertynotify(XEvent *e) { 122 } 123 124 void 125 +pushstack(const Arg *arg) { 126 + int i = stackpos(arg); 127 + Client *sel = selmon->sel, *c, *p; 128 + 129 + if(i < 0) 130 + return; 131 + else if(i == 0) { 132 + detach(sel); 133 + attach(sel); 134 + } 135 + else { 136 + for(p = NULL, c = selmon->clients; c; p = c, c = c->next) 137 + if(!(i -= (ISVISIBLE(c) && c != sel))) 138 + break; 139 + c = c ? c : p; 140 + detach(sel); 141 + sel->next = c->next; 142 + c->next = sel; 143 + } 144 + arrange(selmon); 145 +} 146 + 147 +void 148 quit(const Arg *arg) { 149 running = False; 150 } 151 @@ -1674,6 +1693,36 @@ spawn(const Arg *arg) { 152 } 153 } 154 155 +int 156 +stackpos(const Arg *arg) { 157 + int n, i; 158 + Client *c, *l; 159 + 160 + if(!selmon->clients) 161 + return -1; 162 + 163 + if(arg->i == PREVSEL) { 164 + for(l = selmon->stack; l && (!ISVISIBLE(l) || l == selmon->sel); l = l->snext); 165 + if(!l) 166 + return -1; 167 + for(i = 0, c = selmon->clients; c != l; i += ISVISIBLE(c) ? 1 : 0, c = c->next); 168 + return i; 169 + } 170 + else if(ISINC(arg->i)) { 171 + if(!selmon->sel) 172 + return -1; 173 + for(i = 0, c = selmon->clients; c != selmon->sel; i += ISVISIBLE(c) ? 1 : 0, c = c->next); 174 + for(n = i; c; n += ISVISIBLE(c) ? 1 : 0, c = c->next); 175 + return MOD(i + GETINC(arg->i), n); 176 + } 177 + else if(arg->i < 0) { 178 + for(i = 0, c = selmon->clients; c; i += ISVISIBLE(c) ? 1 : 0, c = c->next); 179 + return MAX(i + arg->i, 0); 180 + } 181 + else 182 + return arg->i; 183 +} 184 + 185 void 186 tag(const Arg *arg) { 187 if(selmon->sel && arg->ui & TAGMASK) {