vanitygaps.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. /* Key binding functions */
  2. static void defaultgaps(const Arg *arg);
  3. static void incrgaps(const Arg *arg);
  4. static void incrigaps(const Arg *arg);
  5. static void incrogaps(const Arg *arg);
  6. static void incrohgaps(const Arg *arg);
  7. static void incrovgaps(const Arg *arg);
  8. static void incrihgaps(const Arg *arg);
  9. static void incrivgaps(const Arg *arg);
  10. static void togglegaps(const Arg *arg);
  11. /* Layouts (delete the ones you do not need) */
  12. static void bstack(Monitor *m);
  13. static void bstackhoriz(Monitor *m);
  14. static void centeredmaster(Monitor *m);
  15. static void centeredfloatingmaster(Monitor *m);
  16. static void deck(Monitor *m);
  17. static void dwindle(Monitor *m);
  18. static void fibonacci(Monitor *m, int s);
  19. static void grid(Monitor *m);
  20. static void nrowgrid(Monitor *m);
  21. static void spiral(Monitor *m);
  22. static void tile(Monitor *m);
  23. /* Internals */
  24. static void getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc);
  25. static void getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr);
  26. static void setgaps(int oh, int ov, int ih, int iv);
  27. /* Settings */
  28. #if !PERTAG_PATCH
  29. static int enablegaps = 1;
  30. #endif // PERTAG_PATCH
  31. void
  32. setgaps(int oh, int ov, int ih, int iv)
  33. {
  34. if (oh < 0) oh = 0;
  35. if (ov < 0) ov = 0;
  36. if (ih < 0) ih = 0;
  37. if (iv < 0) iv = 0;
  38. selmon->gappoh = oh;
  39. selmon->gappov = ov;
  40. selmon->gappih = ih;
  41. selmon->gappiv = iv;
  42. arrange(selmon);
  43. }
  44. void
  45. togglegaps(const Arg *arg)
  46. {
  47. #if PERTAG_PATCH
  48. selmon->pertag->enablegaps[selmon->pertag->curtag] = !selmon->pertag->enablegaps[selmon->pertag->curtag];
  49. #else
  50. enablegaps = !enablegaps;
  51. #endif // PERTAG_PATCH
  52. arrange(NULL);
  53. }
  54. void
  55. defaultgaps(const Arg *arg)
  56. {
  57. setgaps(gappoh, gappov, gappih, gappiv);
  58. }
  59. void
  60. incrgaps(const Arg *arg)
  61. {
  62. setgaps(
  63. selmon->gappoh + arg->i,
  64. selmon->gappov + arg->i,
  65. selmon->gappih + arg->i,
  66. selmon->gappiv + arg->i
  67. );
  68. }
  69. void
  70. incrigaps(const Arg *arg)
  71. {
  72. setgaps(
  73. selmon->gappoh,
  74. selmon->gappov,
  75. selmon->gappih + arg->i,
  76. selmon->gappiv + arg->i
  77. );
  78. }
  79. void
  80. incrogaps(const Arg *arg)
  81. {
  82. setgaps(
  83. selmon->gappoh + arg->i,
  84. selmon->gappov + arg->i,
  85. selmon->gappih,
  86. selmon->gappiv
  87. );
  88. }
  89. void
  90. incrohgaps(const Arg *arg)
  91. {
  92. setgaps(
  93. selmon->gappoh + arg->i,
  94. selmon->gappov,
  95. selmon->gappih,
  96. selmon->gappiv
  97. );
  98. }
  99. void
  100. incrovgaps(const Arg *arg)
  101. {
  102. setgaps(
  103. selmon->gappoh,
  104. selmon->gappov + arg->i,
  105. selmon->gappih,
  106. selmon->gappiv
  107. );
  108. }
  109. void
  110. incrihgaps(const Arg *arg)
  111. {
  112. setgaps(
  113. selmon->gappoh,
  114. selmon->gappov,
  115. selmon->gappih + arg->i,
  116. selmon->gappiv
  117. );
  118. }
  119. void
  120. incrivgaps(const Arg *arg)
  121. {
  122. setgaps(
  123. selmon->gappoh,
  124. selmon->gappov,
  125. selmon->gappih,
  126. selmon->gappiv + arg->i
  127. );
  128. }
  129. void
  130. getgaps(Monitor *m, int *oh, int *ov, int *ih, int *iv, unsigned int *nc)
  131. {
  132. unsigned int n, oe, ie;
  133. #if PERTAG_PATCH
  134. oe = ie = selmon->pertag->enablegaps[selmon->pertag->curtag];
  135. #else
  136. oe = ie = enablegaps;
  137. #endif // PERTAG_PATCH
  138. Client *c;
  139. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  140. if (smartgaps && n == 1) {
  141. oe = 0; // outer gaps disabled when only one client
  142. }
  143. *oh = m->gappoh*oe; // outer horizontal gap
  144. *ov = m->gappov*oe; // outer vertical gap
  145. *ih = m->gappih*ie; // inner horizontal gap
  146. *iv = m->gappiv*ie; // inner vertical gap
  147. *nc = n; // number of clients
  148. }
  149. void
  150. getfacts(Monitor *m, int msize, int ssize, float *mf, float *sf, int *mr, int *sr)
  151. {
  152. unsigned int n;
  153. float mfacts, sfacts;
  154. int mtotal = 0, stotal = 0;
  155. Client *c;
  156. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  157. mfacts = MIN(n, m->nmaster);
  158. sfacts = n - m->nmaster;
  159. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
  160. if (n < m->nmaster)
  161. mtotal += msize / mfacts;
  162. else
  163. stotal += ssize / sfacts;
  164. *mf = mfacts; // total factor of master area
  165. *sf = sfacts; // total factor of stack area
  166. *mr = msize - mtotal; // the remainder (rest) of pixels after an even master split
  167. *sr = ssize - stotal; // the remainder (rest) of pixels after an even stack split
  168. }
  169. /***
  170. * Layouts
  171. */
  172. /*
  173. * Bottomstack layout + gaps
  174. * https://dwm.suckless.org/patches/bottomstack/
  175. */
  176. static void
  177. bstack(Monitor *m)
  178. {
  179. unsigned int i, n;
  180. int oh, ov, ih, iv;
  181. int mx = 0, my = 0, mh = 0, mw = 0;
  182. int sx = 0, sy = 0, sh = 0, sw = 0;
  183. float mfacts, sfacts;
  184. int mrest, srest;
  185. Client *c;
  186. getgaps(m, &oh, &ov, &ih, &iv, &n);
  187. if (n == 0)
  188. return;
  189. sx = mx = m->wx + ov;
  190. sy = my = m->wy + oh;
  191. sh = mh = m->wh - 2*oh;
  192. mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
  193. sw = m->ww - 2*ov - iv * (n - m->nmaster - 1);
  194. if (m->nmaster && n > m->nmaster) {
  195. sh = (mh - ih) * (1 - m->mfact);
  196. mh = mh - ih - sh;
  197. sx = mx;
  198. sy = my + mh + ih;
  199. }
  200. getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
  201. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  202. if (i < m->nmaster) {
  203. resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
  204. mx += WIDTH(c) + iv;
  205. } else {
  206. resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
  207. sx += WIDTH(c) + iv;
  208. }
  209. }
  210. }
  211. static void
  212. bstackhoriz(Monitor *m)
  213. {
  214. unsigned int i, n;
  215. int oh, ov, ih, iv;
  216. int mx = 0, my = 0, mh = 0, mw = 0;
  217. int sx = 0, sy = 0, sh = 0, sw = 0;
  218. float mfacts, sfacts;
  219. int mrest, srest;
  220. Client *c;
  221. getgaps(m, &oh, &ov, &ih, &iv, &n);
  222. if (n == 0)
  223. return;
  224. sx = mx = m->wx + ov;
  225. sy = my = m->wy + oh;
  226. mh = m->wh - 2*oh;
  227. sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
  228. mw = m->ww - 2*ov - iv * (MIN(n, m->nmaster) - 1);
  229. sw = m->ww - 2*ov;
  230. if (m->nmaster && n > m->nmaster) {
  231. sh = (mh - ih) * (1 - m->mfact);
  232. mh = mh - ih - sh;
  233. sy = my + mh + ih;
  234. sh = m->wh - mh - 2*oh - ih * (n - m->nmaster);
  235. }
  236. getfacts(m, mw, sh, &mfacts, &sfacts, &mrest, &srest);
  237. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  238. if (i < m->nmaster) {
  239. resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
  240. mx += WIDTH(c) + iv;
  241. } else {
  242. resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
  243. sy += HEIGHT(c) + ih;
  244. }
  245. }
  246. }
  247. /*
  248. * Centred master layout + gaps
  249. * https://dwm.suckless.org/patches/centeredmaster/
  250. */
  251. void
  252. centeredmaster(Monitor *m)
  253. {
  254. unsigned int i, n;
  255. int oh, ov, ih, iv;
  256. int mx = 0, my = 0, mh = 0, mw = 0;
  257. int lx = 0, ly = 0, lw = 0, lh = 0;
  258. int rx = 0, ry = 0, rw = 0, rh = 0;
  259. float mfacts = 0, lfacts = 0, rfacts = 0;
  260. int mtotal = 0, ltotal = 0, rtotal = 0;
  261. int mrest = 0, lrest = 0, rrest = 0;
  262. Client *c;
  263. getgaps(m, &oh, &ov, &ih, &iv, &n);
  264. if (n == 0)
  265. return;
  266. /* initialize areas */
  267. mx = m->wx + ov;
  268. my = m->wy + oh;
  269. mh = m->wh - 2*oh - ih * ((!m->nmaster ? n : MIN(n, m->nmaster)) - 1);
  270. mw = m->ww - 2*ov;
  271. lh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - 1);
  272. rh = m->wh - 2*oh - ih * (((n - m->nmaster) / 2) - ((n - m->nmaster) % 2 ? 0 : 1));
  273. if (m->nmaster && n > m->nmaster) {
  274. /* go mfact box in the center if more than nmaster clients */
  275. if (n - m->nmaster > 1) {
  276. /* ||<-S->|<---M--->|<-S->|| */
  277. mw = (m->ww - 2*ov - 2*iv) * m->mfact;
  278. lw = (m->ww - mw - 2*ov - 2*iv) / 2;
  279. rw = (m->ww - mw - 2*ov - 2*iv) - lw;
  280. mx += lw + iv;
  281. } else {
  282. /* ||<---M--->|<-S->|| */
  283. mw = (mw - iv) * m->mfact;
  284. lw = 0;
  285. rw = m->ww - mw - iv - 2*ov;
  286. }
  287. lx = m->wx + ov;
  288. ly = m->wy + oh;
  289. rx = mx + mw + iv;
  290. ry = m->wy + oh;
  291. }
  292. /* calculate facts */
  293. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) {
  294. if (!m->nmaster || n < m->nmaster)
  295. mfacts += 1;
  296. else if ((n - m->nmaster) % 2)
  297. lfacts += 1; // total factor of left hand stack area
  298. else
  299. rfacts += 1; // total factor of right hand stack area
  300. }
  301. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++)
  302. if (!m->nmaster || n < m->nmaster)
  303. mtotal += mh / mfacts;
  304. else if ((n - m->nmaster) % 2)
  305. ltotal += lh / lfacts;
  306. else
  307. rtotal += rh / rfacts;
  308. mrest = mh - mtotal;
  309. lrest = lh - ltotal;
  310. rrest = rh - rtotal;
  311. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  312. if (!m->nmaster || i < m->nmaster) {
  313. /* nmaster clients are stacked vertically, in the center of the screen */
  314. resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
  315. my += HEIGHT(c) + ih;
  316. } else {
  317. /* stack clients are stacked vertically */
  318. if ((i - m->nmaster) % 2 ) {
  319. resize(c, lx, ly, lw - (2*c->bw), (lh / lfacts) + ((i - 2*m->nmaster) < 2*lrest ? 1 : 0) - (2*c->bw), 0);
  320. ly += HEIGHT(c) + ih;
  321. } else {
  322. resize(c, rx, ry, rw - (2*c->bw), (rh / rfacts) + ((i - 2*m->nmaster) < 2*rrest ? 1 : 0) - (2*c->bw), 0);
  323. ry += HEIGHT(c) + ih;
  324. }
  325. }
  326. }
  327. }
  328. void
  329. centeredfloatingmaster(Monitor *m)
  330. {
  331. unsigned int i, n;
  332. float mfacts, sfacts;
  333. float mivf = 1.0; // master inner vertical gap factor
  334. int oh, ov, ih, iv, mrest, srest;
  335. int mx = 0, my = 0, mh = 0, mw = 0;
  336. int sx = 0, sy = 0, sh = 0, sw = 0;
  337. Client *c;
  338. getgaps(m, &oh, &ov, &ih, &iv, &n);
  339. if (n == 0)
  340. return;
  341. sx = mx = m->wx + ov;
  342. sy = my = m->wy + oh;
  343. sh = mh = m->wh - 2*oh;
  344. mw = m->ww - 2*ov - iv*(n - 1);
  345. sw = m->ww - 2*ov - iv*(n - m->nmaster - 1);
  346. if (m->nmaster && n > m->nmaster) {
  347. mivf = 0.8;
  348. /* go mfact box in the center if more than nmaster clients */
  349. if (m->ww > m->wh) {
  350. mw = m->ww * m->mfact - iv*mivf*(MIN(n, m->nmaster) - 1);
  351. mh = m->wh * 0.9;
  352. } else {
  353. mw = m->ww * 0.9 - iv*mivf*(MIN(n, m->nmaster) - 1);
  354. mh = m->wh * m->mfact;
  355. }
  356. mx = m->wx + (m->ww - mw) / 2;
  357. my = m->wy + (m->wh - mh - 2*oh) / 2;
  358. sx = m->wx + ov;
  359. sy = m->wy + oh;
  360. sh = m->wh - 2*oh;
  361. }
  362. getfacts(m, mw, sw, &mfacts, &sfacts, &mrest, &srest);
  363. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  364. if (i < m->nmaster) {
  365. /* nmaster clients are stacked horizontally, in the center of the screen */
  366. resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
  367. mx += WIDTH(c) + iv*mivf;
  368. } else {
  369. /* stack clients are stacked horizontally */
  370. resize(c, sx, sy, (sw / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
  371. sx += WIDTH(c) + iv;
  372. }
  373. }
  374. /*
  375. * Deck layout + gaps
  376. * https://dwm.suckless.org/patches/deck/
  377. */
  378. void
  379. deck(Monitor *m)
  380. {
  381. unsigned int i, n;
  382. int oh, ov, ih, iv;
  383. int mx = 0, my = 0, mh = 0, mw = 0;
  384. int sx = 0, sy = 0, sh = 0, sw = 0;
  385. float mfacts, sfacts;
  386. int mrest, srest;
  387. Client *c;
  388. getgaps(m, &oh, &ov, &ih, &iv, &n);
  389. if (n == 0)
  390. return;
  391. sx = mx = m->wx + ov;
  392. sy = my = m->wy + oh;
  393. sh = mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
  394. sw = mw = m->ww - 2*ov;
  395. if (m->nmaster && n > m->nmaster) {
  396. sw = (mw - iv) * (1 - m->mfact);
  397. mw = mw - iv - sw;
  398. sx = mx + mw + iv;
  399. sh = m->wh - 2*oh;
  400. }
  401. getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
  402. if (n - m->nmaster > 0) /* override layout symbol */
  403. snprintf(m->ltsymbol, sizeof m->ltsymbol, "D %d", n - m->nmaster);
  404. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  405. if (i < m->nmaster) {
  406. resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
  407. my += HEIGHT(c) + ih;
  408. } else {
  409. resize(c, sx, sy, sw - (2*c->bw), sh - (2*c->bw), 0);
  410. }
  411. }
  412. /*
  413. * Fibonacci layout + gaps
  414. * https://dwm.suckless.org/patches/fibonacci/
  415. */
  416. void
  417. fibonacci(Monitor *m, int s)
  418. {
  419. unsigned int i, n;
  420. int nx, ny, nw, nh;
  421. int oh, ov, ih, iv;
  422. int nv, hrest = 0, wrest = 0, r = 1;
  423. Client *c;
  424. getgaps(m, &oh, &ov, &ih, &iv, &n);
  425. if (n == 0)
  426. return;
  427. nx = m->wx + ov;
  428. ny = m->wy + oh;
  429. nw = m->ww - 2*ov;
  430. nh = m->wh - 2*oh;
  431. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next)) {
  432. if (r) {
  433. if ((i % 2 && (nh - ih) / 2 <= (bh + 2*c->bw))
  434. || (!(i % 2) && (nw - iv) / 2 <= (bh + 2*c->bw))) {
  435. r = 0;
  436. }
  437. if (r && i < n - 1) {
  438. if (i % 2) {
  439. nv = (nh - ih) / 2;
  440. hrest = nh - 2*nv - ih;
  441. nh = nv;
  442. } else {
  443. nv = (nw - iv) / 2;
  444. wrest = nw - 2*nv - iv;
  445. nw = nv;
  446. }
  447. if ((i % 4) == 2 && !s)
  448. nx += nw + iv;
  449. else if ((i % 4) == 3 && !s)
  450. ny += nh + ih;
  451. }
  452. if ((i % 4) == 0) {
  453. if (s) {
  454. ny += nh + ih;
  455. nh += hrest;
  456. }
  457. else {
  458. nh -= hrest;
  459. ny -= nh + ih;
  460. }
  461. }
  462. else if ((i % 4) == 1) {
  463. nx += nw + iv;
  464. nw += wrest;
  465. }
  466. else if ((i % 4) == 2) {
  467. ny += nh + ih;
  468. nh += hrest;
  469. if (i < n - 1)
  470. nw += wrest;
  471. }
  472. else if ((i % 4) == 3) {
  473. if (s) {
  474. nx += nw + iv;
  475. nw -= wrest;
  476. } else {
  477. nw -= wrest;
  478. nx -= nw + iv;
  479. nh += hrest;
  480. }
  481. }
  482. if (i == 0) {
  483. if (n != 1) {
  484. nw = (m->ww - iv - 2*ov) - (m->ww - iv - 2*ov) * (1 - m->mfact);
  485. wrest = 0;
  486. }
  487. ny = m->wy + oh;
  488. }
  489. else if (i == 1)
  490. nw = m->ww - nw - iv - 2*ov;
  491. i++;
  492. }
  493. resize(c, nx, ny, nw - (2*c->bw), nh - (2*c->bw), False);
  494. }
  495. }
  496. void
  497. dwindle(Monitor *m)
  498. {
  499. fibonacci(m, 1);
  500. }
  501. void
  502. spiral(Monitor *m)
  503. {
  504. fibonacci(m, 0);
  505. }
  506. /*
  507. * Gappless grid layout + gaps (ironically)
  508. * https://dwm.suckless.org/patches/gaplessgrid/
  509. */
  510. void
  511. gaplessgrid(Monitor *m)
  512. {
  513. unsigned int i, n;
  514. int x, y, cols, rows, ch, cw, cn, rn, rrest, crest; // counters
  515. int oh, ov, ih, iv;
  516. Client *c;
  517. getgaps(m, &oh, &ov, &ih, &iv, &n);
  518. if (n == 0)
  519. return;
  520. /* grid dimensions */
  521. for (cols = 0; cols <= n/2; cols++)
  522. if (cols*cols >= n)
  523. break;
  524. if (n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
  525. cols = 2;
  526. rows = n/cols;
  527. cn = rn = 0; // reset column no, row no, client count
  528. ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
  529. cw = (m->ww - 2*ov - iv * (cols - 1)) / cols;
  530. rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
  531. crest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
  532. x = m->wx + ov;
  533. y = m->wy + oh;
  534. for (i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
  535. if (i/rows + 1 > cols - n%cols) {
  536. rows = n/cols + 1;
  537. ch = (m->wh - 2*oh - ih * (rows - 1)) / rows;
  538. rrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
  539. }
  540. resize(c,
  541. x,
  542. y + rn*(ch + ih) + MIN(rn, rrest),
  543. cw + (cn < crest ? 1 : 0) - 2*c->bw,
  544. ch + (rn < rrest ? 1 : 0) - 2*c->bw,
  545. 0);
  546. rn++;
  547. if (rn >= rows) {
  548. rn = 0;
  549. x += cw + ih + (cn < crest ? 1 : 0);
  550. cn++;
  551. }
  552. }
  553. }
  554. /*
  555. * Gridmode layout + gaps
  556. * https://dwm.suckless.org/patches/gridmode/
  557. */
  558. void
  559. grid(Monitor *m)
  560. {
  561. unsigned int i, n;
  562. int cx, cy, cw, ch, cc, cr, chrest, cwrest, cols, rows;
  563. int oh, ov, ih, iv;
  564. Client *c;
  565. getgaps(m, &oh, &ov, &ih, &iv, &n);
  566. /* grid dimensions */
  567. for (rows = 0; rows <= n/2; rows++)
  568. if (rows*rows >= n)
  569. break;
  570. cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
  571. /* window geoms (cell height/width) */
  572. ch = (m->wh - 2*oh - ih * (rows - 1)) / (rows ? rows : 1);
  573. cw = (m->ww - 2*ov - iv * (cols - 1)) / (cols ? cols : 1);
  574. chrest = (m->wh - 2*oh - ih * (rows - 1)) - ch * rows;
  575. cwrest = (m->ww - 2*ov - iv * (cols - 1)) - cw * cols;
  576. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  577. cc = i / rows;
  578. cr = i % rows;
  579. cx = m->wx + ov + cc * (cw + iv) + MIN(cc, cwrest);
  580. cy = m->wy + oh + cr * (ch + ih) + MIN(cr, chrest);
  581. resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
  582. }
  583. }
  584. /*
  585. * Horizontal grid layout + gaps
  586. * https://dwm.suckless.org/patches/horizgrid/
  587. */
  588. void
  589. horizgrid(Monitor *m) {
  590. Client *c;
  591. unsigned int n, i;
  592. int oh, ov, ih, iv;
  593. int mx = 0, my = 0, mh = 0, mw = 0;
  594. int sx = 0, sy = 0, sh = 0, sw = 0;
  595. int ntop, nbottom = 1;
  596. float mfacts, sfacts;
  597. int mrest, srest;
  598. /* Count windows */
  599. getgaps(m, &oh, &ov, &ih, &iv, &n);
  600. if (n == 0)
  601. return;
  602. if (n <= 2)
  603. ntop = n;
  604. else {
  605. ntop = n / 2;
  606. nbottom = n - ntop;
  607. }
  608. sx = mx = m->wx + ov;
  609. sy = my = m->wy + oh;
  610. sh = mh = m->wh - 2*oh;
  611. sw = mw = m->ww - 2*ov;
  612. if (n > ntop) {
  613. sh = (mh - ih) / 2;
  614. mh = mh - ih - sh;
  615. sy = my + mh + ih;
  616. mw = m->ww - 2*ov - iv * (ntop - 1);
  617. sw = m->ww - 2*ov - iv * (nbottom - 1);
  618. }
  619. mfacts = ntop;
  620. sfacts = nbottom;
  621. mrest = mw - (mw / ntop) * ntop;
  622. srest = sw - (sw / nbottom) * nbottom;
  623. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  624. if (i < ntop) {
  625. resize(c, mx, my, (mw / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), mh - (2*c->bw), 0);
  626. mx += WIDTH(c) + iv;
  627. } else {
  628. resize(c, sx, sy, (sw / sfacts) + ((i - ntop) < srest ? 1 : 0) - (2*c->bw), sh - (2*c->bw), 0);
  629. sx += WIDTH(c) + iv;
  630. }
  631. }
  632. /*
  633. * nrowgrid layout + gaps
  634. * https://dwm.suckless.org/patches/nrowgrid/
  635. */
  636. void
  637. nrowgrid(Monitor *m)
  638. {
  639. unsigned int n;
  640. int ri = 0, ci = 0; /* counters */
  641. int oh, ov, ih, iv; /* vanitygap settings */
  642. unsigned int cx, cy, cw, ch; /* client geometry */
  643. unsigned int uw = 0, uh = 0, uc = 0; /* utilization trackers */
  644. unsigned int cols, rows = m->nmaster + 1;
  645. Client *c;
  646. /* count clients */
  647. getgaps(m, &oh, &ov, &ih, &iv, &n);
  648. /* nothing to do here */
  649. if (n == 0)
  650. return;
  651. /* force 2 clients to always split vertically */
  652. if (FORCE_VSPLIT && n == 2)
  653. rows = 1;
  654. /* never allow empty rows */
  655. if (n < rows)
  656. rows = n;
  657. /* define first row */
  658. cols = n / rows;
  659. uc = cols;
  660. cy = m->wy + oh;
  661. ch = (m->wh - 2*oh - ih*(rows - 1)) / rows;
  662. uh = ch;
  663. for (c = nexttiled(m->clients); c; c = nexttiled(c->next), ci++) {
  664. if (ci == cols) {
  665. uw = 0;
  666. ci = 0;
  667. ri++;
  668. /* next row */
  669. cols = (n - uc) / (rows - ri);
  670. uc += cols;
  671. cy = m->wy + oh + uh + ih;
  672. uh += ch + ih;
  673. }
  674. cx = m->wx + ov + uw;
  675. cw = (m->ww - 2*ov - uw) / (cols - ci);
  676. uw += cw + iv;
  677. resize(c, cx, cy, cw - (2*c->bw), ch - (2*c->bw), 0);
  678. }
  679. }
  680. /*
  681. * Default tile layout + gaps
  682. */
  683. static void
  684. tile(Monitor *m)
  685. {
  686. unsigned int i, n;
  687. int oh, ov, ih, iv;
  688. int mx = 0, my = 0, mh = 0, mw = 0;
  689. int sx = 0, sy = 0, sh = 0, sw = 0;
  690. float mfacts, sfacts;
  691. int mrest, srest;
  692. Client *c;
  693. getgaps(m, &oh, &ov, &ih, &iv, &n);
  694. if (n == 0)
  695. return;
  696. sx = mx = m->wx + ov;
  697. sy = my = m->wy + oh;
  698. mh = m->wh - 2*oh - ih * (MIN(n, m->nmaster) - 1);
  699. sh = m->wh - 2*oh - ih * (n - m->nmaster - 1);
  700. sw = mw = m->ww - 2*ov;
  701. if (m->nmaster && n > m->nmaster) {
  702. sw = (mw - iv) * (1 - m->mfact);
  703. mw = mw - iv - sw;
  704. sx = mx + mw + iv;
  705. }
  706. getfacts(m, mh, sh, &mfacts, &sfacts, &mrest, &srest);
  707. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  708. if (i < m->nmaster) {
  709. resize(c, mx, my, mw - (2*c->bw), (mh / mfacts) + (i < mrest ? 1 : 0) - (2*c->bw), 0);
  710. my += HEIGHT(c) + ih;
  711. } else {
  712. resize(c, sx, sy, sw - (2*c->bw), (sh / sfacts) + ((i - m->nmaster) < srest ? 1 : 0) - (2*c->bw), 0);
  713. sy += HEIGHT(c) + ih;
  714. }
  715. }