dwm-6.0-xtile.diff (11859B)
1 diff --git a/config.def.h b/config.def.h 2 index 77ff358..ac895db 100644 3 --- a/config.def.h 4 +++ b/config.def.h 5 @@ -23,7 +23,8 @@ static const Rule rules[] = { 6 }; 7 8 /* layout(s) */ 9 -static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */ 10 +static const int dirs[3] = { DirHor, DirVer, DirVer }; /* tiling dirs */ 11 +static const float facts[3] = { 1.1, 1.1, 1.1 }; /* tiling facts */ 12 static const int nmaster = 1; /* number of clients in master area */ 13 static const Bool resizehints = True; /* True means respect size hints in tiled resizals */ 14 15 @@ -41,6 +42,10 @@ static const Layout layouts[] = { 16 { MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \ 17 { MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \ 18 { MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} }, 19 +#define TILEKEYS(MOD,G,M,S) \ 20 + { MOD, XK_r, setdirs, {.v = (int[]) { INC(G * +1), INC(M * +1), INC(S * +1) } } }, \ 21 + { MOD, XK_h, setfacts, {.v = (float[]){ INC(G * -0.1), INC(M * -0.1), INC(S * -0.1) } } }, \ 22 + { MOD, XK_l, setfacts, {.v = (float[]){ INC(G * +0.1), INC(M * +0.1), INC(S * +0.1) } } }, 23 24 /* helper for spawning shell commands in the pre dwm-5.0 fashion */ 25 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } 26 @@ -58,8 +63,6 @@ static Key keys[] = { 27 { MODKEY, XK_k, focusstack, {.i = -1 } }, 28 { MODKEY, XK_i, incnmaster, {.i = +1 } }, 29 { MODKEY, XK_d, incnmaster, {.i = -1 } }, 30 - { MODKEY, XK_h, setmfact, {.f = -0.05} }, 31 - { MODKEY, XK_l, setmfact, {.f = +0.05} }, 32 { MODKEY, XK_Return, zoom, {0} }, 33 { MODKEY, XK_Tab, view, {0} }, 34 { MODKEY|ShiftMask, XK_c, killclient, {0} }, 35 @@ -67,6 +70,12 @@ static Key keys[] = { 36 { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, 37 { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, 38 { MODKEY, XK_space, setlayout, {0} }, 39 + TILEKEYS(MODKEY, 1, 0, 0) 40 + TILEKEYS(MODKEY|ShiftMask, 0, 1, 0) 41 + TILEKEYS(MODKEY|ControlMask, 0, 0, 1) 42 + TILEKEYS(MODKEY|ShiftMask|ControlMask, 1, 1, 1) 43 + { MODKEY|ShiftMask, XK_t, setdirs, {.v = (int[]){ DirHor, DirVer, DirVer } } }, 44 + { MODKEY|ControlMask, XK_t, setdirs, {.v = (int[]){ DirVer, DirHor, DirHor } } }, 45 { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, 46 { MODKEY, XK_0, view, {.ui = ~0 } }, 47 { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, 48 diff --git a/dwm.c b/dwm.c 49 index c9ad1f2..9cae5b5 100644 50 --- a/dwm.c 51 +++ b/dwm.c 52 @@ -43,17 +43,22 @@ 53 /* macros */ 54 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) 55 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) 56 +#define GETINC(X) ((X) - 2000) 57 +#define INC(X) ((X) + 2000) 58 #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ 59 * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) 60 +#define ISINC(X) ((X) > 1000 && (X) < 3000) 61 #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) 62 #define LENGTH(X) (sizeof X / sizeof X[0]) 63 #define MAX(A, B) ((A) > (B) ? (A) : (B)) 64 #define MIN(A, B) ((A) < (B) ? (A) : (B)) 65 +#define MOD(N,M) ((N)%(M) < 0 ? (N)%(M) + (M) : (N)%(M)) 66 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) 67 #define WIDTH(X) ((X)->w + 2 * (X)->bw) 68 #define HEIGHT(X) ((X)->h + 2 * (X)->bw) 69 #define TAGMASK ((1 << LENGTH(tags)) - 1) 70 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) 71 +#define TRUNC(X,A,B) (MAX((A), MIN((X), (B)))) 72 73 /* enums */ 74 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ 75 @@ -64,6 +69,7 @@ enum { NetSupported, NetWMName, NetWMState, 76 enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ 77 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, 78 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ 79 +enum { DirHor, DirVer, DirRotHor, DirRotVer, DirLast }; /* tiling dirs */ 80 81 typedef union { 82 int i; 83 @@ -73,6 +79,11 @@ typedef union { 84 } Arg; 85 86 typedef struct { 87 + unsigned int x, y, fx, fy, n, dir; 88 + float fact; 89 +} Area; 90 + 91 +typedef struct { 92 unsigned int click; 93 unsigned int mask; 94 unsigned int button; 95 @@ -127,7 +138,6 @@ typedef struct { 96 typedef struct Pertag Pertag; 97 struct Monitor { 98 char ltsymbol[16]; 99 - float mfact; 100 int nmaster; 101 int num; 102 int by; /* bar geometry */ 103 @@ -218,10 +228,11 @@ static void scan(void); 104 static Bool sendevent(Client *c, Atom proto); 105 static void sendmon(Client *c, Monitor *m); 106 static void setclientstate(Client *c, long state); 107 +static void setdirs(const Arg *arg); 108 +static void setfacts(const Arg *arg); 109 static void setfocus(Client *c); 110 static void setfullscreen(Client *c, Bool fullscreen); 111 static void setlayout(const Arg *arg); 112 -static void setmfact(const Arg *arg); 113 static void setup(void); 114 static void showhide(Client *c); 115 static void sigchld(int unused); 116 @@ -292,7 +303,7 @@ static Window root; 117 struct Pertag { 118 unsigned int curtag, prevtag; /* current and previous tag */ 119 int nmasters[LENGTH(tags) + 1]; /* number of windows in master area */ 120 - float mfacts[LENGTH(tags) + 1]; /* mfacts per tag */ 121 + Area areas[LENGTH(tags) + 1][3]; /* tiling areas */ 122 unsigned int sellts[LENGTH(tags) + 1]; /* selected layouts */ 123 const Layout *ltidxs[LENGTH(tags) + 1][2]; /* matrix of tags and layouts indexes */ 124 Bool showbars[LENGTH(tags) + 1]; /* display bar for the current tag */ 125 @@ -543,6 +554,7 @@ void 126 clientmessage(XEvent *e) { 127 XClientMessageEvent *cme = &e->xclient; 128 Client *c = wintoclient(cme->window); 129 + int i; 130 131 if(!c) 132 return; 133 @@ -553,8 +565,8 @@ clientmessage(XEvent *e) { 134 } 135 else if(cme->message_type == netatom[NetActiveWindow]) { 136 if(!ISVISIBLE(c)) { 137 - c->mon->seltags ^= 1; 138 - c->mon->tagset[c->mon->seltags] = c->tags; 139 + for(i=0; !(c->tags & 1 << i); i++); 140 + view(&(Arg){.ui = 1 << i}); 141 } 142 pop(c); 143 } 144 @@ -657,12 +669,11 @@ configurerequest(XEvent *e) { 145 Monitor * 146 createmon(void) { 147 Monitor *m; 148 - int i; 149 + int i, j; 150 151 if(!(m = (Monitor *)calloc(1, sizeof(Monitor)))) 152 die("fatal: could not malloc() %u bytes\n", sizeof(Monitor)); 153 m->tagset[0] = m->tagset[1] = 1; 154 - m->mfact = mfact; 155 m->nmaster = nmaster; 156 m->showbar = showbar; 157 m->topbar = topbar; 158 @@ -676,8 +687,11 @@ createmon(void) { 159 /* init nmaster */ 160 m->pertag->nmasters[i] = m->nmaster; 161 162 - /* init mfacts */ 163 - m->pertag->mfacts[i] = m->mfact; 164 + /* init tiling dirs and facts */ 165 + for(j = 0; j < 3; j++) { 166 + m->pertag->areas[i][j].dir = MIN(dirs[j], ((int[]){ 3, 1, 1 }[j])); 167 + m->pertag->areas[i][j].fact = TRUNC(facts[j], 0.1, 10); 168 + } 169 170 /* init layouts */ 171 m->pertag->ltidxs[i][0] = m->lt[0]; 172 @@ -1524,6 +1538,31 @@ setclientstate(Client *c, long state) { 173 PropModeReplace, (unsigned char *)data, 2); 174 } 175 176 +void 177 +setdirs(const Arg *arg) { 178 + int *dirs = (int *)arg->v, i, n; 179 + Area *areas = selmon->pertag->areas[selmon->pertag->curtag]; 180 + 181 + for(i = 0; i < 3; i++) { 182 + n = (int[]){ 4, 2, 2 }[i]; 183 + areas[i].dir = ISINC(dirs[i]) ? 184 + MOD((int)areas[i].dir + GETINC(dirs[i]), n) : TRUNC(dirs[i], 0, n - 1); 185 + } 186 + arrange(selmon); 187 +} 188 + 189 +void 190 +setfacts(const Arg *arg) { 191 + float *facts = (float *)arg->v; 192 + Area *areas = selmon->pertag->areas[selmon->pertag->curtag]; 193 + int i; 194 + 195 + for(i = 0; i < 3; i++) 196 + areas[i].fact = TRUNC(ISINC(facts[i]) ? 197 + areas[i].fact + GETINC(facts[i]) : facts[i], 0.1, 10); 198 + arrange(selmon); 199 +} 200 + 201 Bool 202 sendevent(Client *c, Atom proto) { 203 int n; 204 @@ -1599,20 +1638,6 @@ setlayout(const Arg *arg) { 205 drawbar(selmon); 206 } 207 208 -/* arg > 1.0 will set mfact absolutly */ 209 -void 210 -setmfact(const Arg *arg) { 211 - float f; 212 - 213 - if(!arg || !selmon->lt[selmon->sellt]->arrange) 214 - return; 215 - f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0; 216 - if(f < 0.1 || f > 0.9) 217 - return; 218 - selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f; 219 - arrange(selmon); 220 -} 221 - 222 void 223 setup(void) { 224 XSetWindowAttributes wa; 225 @@ -1736,28 +1761,41 @@ textnw(const char *text, unsigned int len) { 226 227 void 228 tile(Monitor *m) { 229 - unsigned int i, n, h, mw, my, ty; 230 Client *c; 231 + Area *ga = m->pertag->areas[m->pertag->curtag], *ma = ga + 1, *sa = ga + 2, *a; 232 + unsigned int n, i, w, h, ms, ss; 233 + float f; 234 235 + /* print layout symbols */ 236 + snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", 237 + (char[]){ '<', '^', '>', 'v' }[ga->dir], 238 + (char[]){ '-', '|' }[ma->dir], 239 + (char[]){ '-', '|' }[sa->dir]); 240 + /* calculate number of clients */ 241 for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++); 242 if(n == 0) 243 return; 244 - 245 - if(n > m->nmaster) 246 - mw = m->nmaster ? m->ww * m->mfact : 0; 247 + ma->n = MIN(n, m->nmaster), sa->n = n - ma->n; 248 + /* calculate area rectangles */ 249 + f = ma->n == 0 ? 0 : (sa->n == 0 ? 1 : ga->fact / 2); 250 + if(ga->dir == DirHor || ga->dir == DirRotHor) 251 + ms = f * m->ww, ss = m->ww - ms, 252 + ma->x = ga->dir == DirHor ? 0 : ss, ma->y = 0, ma->fx = ma->x + ms, ma->fy = m->wh, 253 + sa->x = ga->dir == DirHor ? ms : 0, sa->y = 0, sa->fx = sa->x + ss, sa->fy = m->wh; 254 else 255 - mw = m->ww; 256 - for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) 257 - if(i < m->nmaster) { 258 - h = (m->wh - my) / (MIN(n, m->nmaster) - i); 259 - resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), False); 260 - my += HEIGHT(c); 261 - } 262 - else { 263 - h = (m->wh - ty) / (n - i); 264 - resize(c, m->wx + mw, m->wy + ty, m->ww - mw - (2*c->bw), h - (2*c->bw), False); 265 - ty += HEIGHT(c); 266 - } 267 + ms = f * m->wh, ss = m->wh - ms, 268 + ma->x = 0, ma->y = ga->dir == DirVer ? 0 : ss, ma->fx = m->ww, ma->fy = ma->y + ms, 269 + sa->x = 0, sa->y = ga->dir == DirVer ? ms : 0, sa->fx = m->ww, sa->fy = sa->y + ss; 270 + /* tile clients */ 271 + for(c = nexttiled(m->clients), i = 0; i < n; c = nexttiled(c->next), i++) { 272 + a = ma->n > 0 ? ma : sa; 273 + f = i == 0 || ma->n == 0 ? a->fact : 1, f /= --a->n + f; 274 + w = (a->dir == DirVer ? 1 : f) * (a->fx - a->x); 275 + h = (a->dir == DirHor ? 1 : f) * (a->fy - a->y); 276 + resize(c, m->wx + a->x, m->wy + a->y, w - 2 * c->bw, h - 2 * c->bw, False); 277 + a->x += a->dir == DirHor ? w : 0; 278 + a->y += a->dir == DirVer ? h : 0; 279 + } 280 } 281 282 void 283 @@ -1813,7 +1851,6 @@ toggleview(const Arg *arg) { 284 285 /* apply settings for this view */ 286 selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; 287 - selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; 288 selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; 289 selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; 290 selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1]; 291 @@ -2117,7 +2154,6 @@ view(const Arg *arg) { 292 selmon->pertag->curtag = tmptag; 293 } 294 selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag]; 295 - selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag]; 296 selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag]; 297 selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt]; 298 selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];