Another copy of my dotfiles. Because I don't completely trust GitHub.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

890 lines
24 KiB

  1. typedef struct {
  2. void (*arrange)(Monitor *, int, int, int, int, int, int, int);
  3. } LayoutArranger;
  4. typedef struct {
  5. void (*arrange)(Monitor *, int, int, int, int, int, int, int, int, int);
  6. } TileArranger;
  7. static const LayoutArranger flexlayouts[] = {
  8. { layout_no_split },
  9. { layout_split_vertical },
  10. { layout_split_horizontal },
  11. { layout_split_centered_vertical },
  12. { layout_split_centered_horizontal },
  13. { layout_split_vertical_dual_stack },
  14. { layout_split_horizontal_dual_stack },
  15. { layout_floating_master },
  16. { layout_split_vertical_fixed },
  17. { layout_split_horizontal_fixed },
  18. { layout_split_centered_vertical_fixed },
  19. { layout_split_centered_horizontal_fixed },
  20. { layout_split_vertical_dual_stack_fixed },
  21. { layout_split_horizontal_dual_stack_fixed },
  22. { layout_floating_master_fixed },
  23. };
  24. static const TileArranger flextiles[] = {
  25. { arrange_top_to_bottom },
  26. { arrange_left_to_right },
  27. { arrange_monocle },
  28. { arrange_gapplessgrid },
  29. { arrange_gapplessgrid_alt1 },
  30. { arrange_gapplessgrid_alt2 },
  31. { arrange_gridmode },
  32. { arrange_horizgrid },
  33. { arrange_dwindle },
  34. { arrange_spiral },
  35. { arrange_tatami },
  36. };
  37. static void
  38. getfactsforrange(Monitor *m, int an, int ai, int size, int *rest, float *fact)
  39. {
  40. int i;
  41. float facts;
  42. Client *c;
  43. int total = 0;
  44. facts = 0;
  45. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  46. if (i >= ai && i < (ai + an))
  47. #if CFACTS_PATCH
  48. facts += c->cfact;
  49. #else
  50. facts += 1;
  51. #endif // CFACTS_PATCH
  52. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  53. if (i >= ai && i < (ai + an))
  54. #if CFACTS_PATCH
  55. total += size * (c->cfact / facts);
  56. #else
  57. total += size / facts;
  58. #endif // CFACTS_PATCH
  59. *rest = size - total;
  60. *fact = facts;
  61. }
  62. #if IPC_PATCH || DWMC_PATCH
  63. static void
  64. setlayoutaxisex(const Arg *arg)
  65. {
  66. int axis, arr;
  67. axis = arg->i & 0x3; // lower two bytes indicates layout, master or stack1-2
  68. arr = ((arg->i & 0xFC) >> 2); // remaining six upper bytes indicate arrangement
  69. if ((axis == 0 && abs(arr) > LAYOUT_LAST)
  70. || (axis > 0 && (arr > AXIS_LAST || arr < 0)))
  71. arr = 0;
  72. selmon->ltaxis[axis] = arr;
  73. #if PERTAG_PATCH
  74. selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis];
  75. #endif // PERTAG_PATCH
  76. arrange(selmon);
  77. }
  78. #endif // IPC_PATCH | DWMC_PATCH
  79. static void
  80. layout_no_split(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  81. {
  82. (&flextiles[m->ltaxis[m->nmaster >= n ? MASTER : STACK]])->arrange(m, x, y, h, w, ih, iv, n, n, 0);
  83. }
  84. static void
  85. layout_split_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  86. {
  87. /* Split master into master + stack if we have enough clients */
  88. if (m->nmaster && n > m->nmaster) {
  89. layout_split_vertical_fixed(m, x, y, h, w, ih, iv, n);
  90. } else {
  91. layout_no_split(m, x, y, h, w, ih, iv, n);
  92. }
  93. }
  94. static void
  95. layout_split_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  96. {
  97. int sw, sx;
  98. sw = (w - iv) * (1 - m->mfact);
  99. w = (w - iv) * m->mfact;
  100. if (m->ltaxis[LAYOUT] < 0) { // mirror
  101. sx = x;
  102. x += sw + iv;
  103. } else {
  104. sx = x + w + iv;
  105. }
  106. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  107. (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, n - m->nmaster, m->nmaster);
  108. }
  109. static void
  110. layout_split_vertical_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  111. {
  112. /* Split master into master + stack if we have enough clients */
  113. if (!m->nmaster || n <= m->nmaster) {
  114. layout_no_split(m, x, y, h, w, ih, iv, n);
  115. } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
  116. layout_split_vertical(m, x, y, h, w, ih, iv, n);
  117. } else {
  118. layout_split_vertical_dual_stack_fixed(m, x, y, h, w, ih, iv, n);
  119. }
  120. }
  121. static void
  122. layout_split_vertical_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  123. {
  124. int sh, sw, sx, oy, sc;
  125. if (m->nstack)
  126. sc = m->nstack;
  127. else
  128. sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
  129. sw = (w - iv) * (1 - m->mfact);
  130. sh = (h - ih) / 2;
  131. w = (w - iv) * m->mfact;
  132. oy = y + sh + ih;
  133. if (m->ltaxis[LAYOUT] < 0) { // mirror
  134. sx = x;
  135. x += sw + iv;
  136. } else {
  137. sx = x + w + iv;
  138. }
  139. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  140. (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, sh, sw, ih, iv, n, sc, m->nmaster);
  141. (&flextiles[m->ltaxis[STACK2]])->arrange(m, sx, oy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
  142. }
  143. static void
  144. layout_split_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  145. {
  146. /* Split master into master + stack if we have enough clients */
  147. if (m->nmaster && n > m->nmaster) {
  148. layout_split_horizontal_fixed(m, x, y, h, w, ih, iv, n);
  149. } else {
  150. layout_no_split(m, x, y, h, w, ih, iv, n);
  151. }
  152. }
  153. static void
  154. layout_split_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  155. {
  156. int sh, sy;
  157. sh = (h - ih) * (1 - m->mfact);
  158. h = (h - ih) * m->mfact;
  159. if (m->ltaxis[LAYOUT] < 0) { // mirror
  160. sy = y;
  161. y += sh + ih;
  162. } else {
  163. sy = y + h + ih;
  164. }
  165. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  166. (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, n - m->nmaster, m->nmaster);
  167. }
  168. static void
  169. layout_split_horizontal_dual_stack(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  170. {
  171. /* Split master into master + stack if we have enough clients */
  172. if (!m->nmaster || n <= m->nmaster) {
  173. layout_no_split(m, x, y, h, w, ih, iv, n);
  174. } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
  175. layout_split_horizontal(m, x, y, h, w, ih, iv, n);
  176. } else {
  177. layout_split_horizontal_dual_stack_fixed(m, x, y, h, w, ih, iv, n);
  178. }
  179. }
  180. static void
  181. layout_split_horizontal_dual_stack_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  182. {
  183. int sh, sy, ox, sc;
  184. if (m->nstack)
  185. sc = m->nstack;
  186. else
  187. sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
  188. sh = (h - ih) * (1 - m->mfact);
  189. h = (h - ih) * m->mfact;
  190. sw = (w - iv) / 2;
  191. ox = x + sw + iv;
  192. if (m->ltaxis[LAYOUT] < 0) { // mirror
  193. sy = y;
  194. y += sh + ih;
  195. } else {
  196. sy = y + h + ih;
  197. }
  198. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  199. (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, sw, ih, iv, n, sc, m->nmaster);
  200. (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, sy, sh, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
  201. }
  202. static void
  203. layout_split_centered_vertical(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  204. {
  205. /* Split master into master + stack if we have enough clients */
  206. if (!m->nmaster || n <= m->nmaster) {
  207. layout_no_split(m, x, y, h, w, ih, iv, n);
  208. } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
  209. layout_split_vertical(m, x, y, h, w, ih, iv, n);
  210. } else {
  211. layout_split_centered_vertical_fixed(m, x, y, h, w, ih, iv, n);
  212. }
  213. }
  214. static void
  215. layout_split_centered_vertical_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  216. {
  217. int sw, sx, ox, sc;
  218. if (m->nstack)
  219. sc = m->nstack;
  220. else
  221. sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
  222. sw = (w - 2*iv) * (1 - m->mfact) / 2;
  223. w = (w - 2*iv) * m->mfact;
  224. if (m->ltaxis[LAYOUT] < 0) { // mirror
  225. sx = x;
  226. x += sw + iv;
  227. ox = x + w + iv;
  228. } else {
  229. ox = x;
  230. x += sw + iv;
  231. sx = x + w + iv;
  232. }
  233. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  234. (&flextiles[m->ltaxis[STACK]])->arrange(m, sx, y, h, sw, ih, iv, n, sc, m->nmaster);
  235. (&flextiles[m->ltaxis[STACK2]])->arrange(m, ox, y, h, sw, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
  236. }
  237. static void
  238. layout_split_centered_horizontal(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  239. {
  240. /* Split master into master + stack if we have enough clients */
  241. if (!m->nmaster || n <= m->nmaster) {
  242. layout_no_split(m, x, y, h, w, ih, iv, n);
  243. } else if (n <= m->nmaster + (m->nstack ? m->nstack : 1)) {
  244. layout_split_horizontal(m, x, y, h, w, ih, iv, n);
  245. } else {
  246. layout_split_centered_horizontal_fixed(m, x, y, h, w, ih, iv, n);
  247. }
  248. }
  249. static void
  250. layout_split_centered_horizontal_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  251. {
  252. int sh, sy, oy, sc;
  253. if (m->nstack)
  254. sc = m->nstack;
  255. else
  256. sc = (n - m->nmaster) / 2 + ((n - m->nmaster) % 2 > 0 ? 1 : 0);
  257. sh = (h - 2*ih) * (1 - m->mfact) / 2;
  258. h = (h - 2*ih) * m->mfact;
  259. if (m->ltaxis[LAYOUT] < 0) { // mirror
  260. sy = y;
  261. y += sh + ih;
  262. oy = y + h + ih;
  263. } else {
  264. oy = y;
  265. y += sh + ih;
  266. sy = y + h + ih;
  267. }
  268. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, h, w, ih, iv, n, m->nmaster, 0);
  269. (&flextiles[m->ltaxis[STACK]])->arrange(m, x, sy, sh, w, ih, iv, n, sc, m->nmaster);
  270. (&flextiles[m->ltaxis[STACK2]])->arrange(m, x, oy, sh, w, ih, iv, n, n - m->nmaster - sc, m->nmaster + sc);
  271. }
  272. static void
  273. layout_floating_master(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  274. {
  275. /* Split master into master + stack if we have enough clients */
  276. if (!m->nmaster || n <= m->nmaster) {
  277. layout_no_split(m, x, y, h, w, ih, iv, n);
  278. } else {
  279. layout_floating_master_fixed(m, x, y, h, w, ih, iv, n);
  280. }
  281. }
  282. static void
  283. layout_floating_master_fixed(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n)
  284. {
  285. int mh, mw;
  286. /* Draw stack area first */
  287. (&flextiles[m->ltaxis[STACK]])->arrange(m, x, y, h, w, ih, iv, n, n - m->nmaster, m->nmaster);
  288. if (w > h) {
  289. mw = w * m->mfact;
  290. mh = h * 0.9;
  291. } else {
  292. mw = w * 0.9;
  293. mh = h * m->mfact;
  294. }
  295. x = x + (w - mw) / 2;
  296. y = y + (h - mh) / 2;
  297. (&flextiles[m->ltaxis[MASTER]])->arrange(m, x, y, mh, mw, ih, iv, n, m->nmaster, 0);
  298. }
  299. static void
  300. arrange_left_to_right(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  301. {
  302. int i, rest;
  303. float facts, fact = 1;
  304. Client *c;
  305. if (ai + an > n)
  306. an = n - ai;
  307. w -= iv * (an - 1);
  308. getfactsforrange(m, an, ai, w, &rest, &facts);
  309. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  310. if (i >= ai && i < (ai + an)) {
  311. #if CFACTS_PATCH
  312. fact = c->cfact;
  313. #endif // CFACTS_PATCH
  314. resize(c, x, y, w * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), h - (2*c->bw), 0);
  315. x += WIDTH(c) + iv;
  316. }
  317. }
  318. }
  319. static void
  320. arrange_top_to_bottom(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  321. {
  322. int i, rest;
  323. float facts, fact = 1;
  324. Client *c;
  325. if (ai + an > n)
  326. an = n - ai;
  327. h -= ih * (an - 1);
  328. getfactsforrange(m, an, ai, h, &rest, &facts);
  329. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  330. if (i >= ai && i < (ai + an)) {
  331. #if CFACTS_PATCH
  332. fact = c->cfact;
  333. #endif // CFACTS_PATCH
  334. resize(c, x, y, w - (2*c->bw), h * (fact / facts) + ((i - ai) < rest ? 1 : 0) - (2*c->bw), 0);
  335. y += HEIGHT(c) + ih;
  336. }
  337. }
  338. }
  339. static void
  340. arrange_monocle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  341. {
  342. int i;
  343. Client *c;
  344. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
  345. if (i >= ai && i < (ai + an))
  346. resize(c, x, y, w - (2*c->bw), h - (2*c->bw), 0);
  347. }
  348. static void
  349. arrange_gridmode(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  350. {
  351. int i, cols, rows, ch, cw, cx, cy, cc, cr, chrest, cwrest; // counters
  352. Client *c;
  353. /* grid dimensions */
  354. for (rows = 0; rows <= an/2; rows++)
  355. if (rows*rows >= an)
  356. break;
  357. cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows;
  358. /* window geoms (cell height/width) */
  359. ch = (h - ih * (rows - 1)) / (rows ? rows : 1);
  360. cw = (w - iv * (cols - 1)) / (cols ? cols : 1);
  361. chrest = h - ih * (rows - 1) - ch * rows;
  362. cwrest = w - iv * (cols - 1) - cw * cols;
  363. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  364. if (i >= ai && i < (ai + an)) {
  365. cc = ((i - ai) / rows); // client column number
  366. cr = ((i - ai) % rows); // client row number
  367. cx = x + cc * (cw + iv) + MIN(cc, cwrest);
  368. cy = y + cr * (ch + ih) + MIN(cr, chrest);
  369. resize(c, cx, cy, cw + (cc < cwrest ? 1 : 0) - 2*c->bw, ch + (cr < chrest ? 1 : 0) - 2*c->bw, False);
  370. }
  371. }
  372. }
  373. static void
  374. arrange_horizgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  375. {
  376. int ntop, nbottom, rh, rest;
  377. /* Exception when there is only one client; don't split into two rows */
  378. if (an == 1) {
  379. arrange_monocle(m, x, y, h, w, ih, iv, n, an, ai);
  380. return;
  381. }
  382. ntop = an / 2;
  383. nbottom = an - ntop;
  384. rh = (h - ih) / 2;
  385. rest = h - ih - rh * 2;
  386. arrange_left_to_right(m, x, y, rh + rest, w, ih, iv, n, ntop, ai);
  387. arrange_left_to_right(m, x, y + rh + ih + rest, rh, w, ih, iv, n, nbottom, ai + ntop);
  388. }
  389. static void
  390. arrange_gapplessgrid(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  391. {
  392. int i, cols, rows, ch, cw, cn, rn, cc, rrest, crest; // counters
  393. Client *c;
  394. /* grid dimensions */
  395. for (cols = 1; cols <= an/2; cols++)
  396. if (cols*cols >= an)
  397. break;
  398. if (an == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
  399. cols = 2;
  400. rows = an/cols;
  401. cn = rn = cc = 0; // reset column no, row no, client count
  402. ch = (h - ih * (rows - 1)) / rows;
  403. rrest = (h - ih * (rows - 1)) - ch * rows;
  404. cw = (w - iv * (cols - 1)) / cols;
  405. crest = (w - iv * (cols - 1)) - cw * cols;
  406. for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
  407. if (i >= ai && i < (ai + an)) {
  408. if (cc/rows + 1 > cols - an%cols) {
  409. rows = an/cols + 1;
  410. ch = (h - ih * (rows - 1)) / rows;
  411. rrest = (h - ih * (rows - 1)) - ch * rows;
  412. }
  413. resize(c,
  414. x,
  415. y + rn*(ch + ih) + MIN(rn, rrest),
  416. cw + (cn < crest ? 1 : 0) - 2*c->bw,
  417. ch + (rn < rrest ? 1 : 0) - 2*c->bw,
  418. 0);
  419. rn++;
  420. cc++;
  421. if (rn >= rows) {
  422. rn = 0;
  423. x += cw + ih + (cn < crest ? 1 : 0);
  424. cn++;
  425. }
  426. }
  427. }
  428. }
  429. /* This version of gappless grid fills rows first */
  430. static void
  431. arrange_gapplessgrid_alt1(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  432. {
  433. int i, cols, rows, rest, ch;
  434. /* grid dimensions */
  435. for (cols = 1; cols <= an/2; cols++)
  436. if (cols*cols >= an)
  437. break;
  438. rows = (cols && (cols - 1) * cols >= an) ? cols - 1 : cols;
  439. ch = (h - ih * (rows - 1)) / (rows ? rows : 1);
  440. rest = (h - ih * (rows - 1)) - ch * rows;
  441. for (i = 0; i < rows; i++) {
  442. arrange_left_to_right(m, x, y, ch + (i < rest ? 1 : 0), w, ih, iv, n, MIN(cols, an - i*cols), ai + i*cols);
  443. y += ch + (i < rest ? 1 : 0) + ih;
  444. }
  445. }
  446. /* This version of gappless grid fills columns first */
  447. static void
  448. arrange_gapplessgrid_alt2(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  449. {
  450. int i, cols, rows, rest, cw;
  451. /* grid dimensions */
  452. for (rows = 0; rows <= an/2; rows++)
  453. if (rows*rows >= an)
  454. break;
  455. cols = (rows && (rows - 1) * rows >= an) ? rows - 1 : rows;
  456. cw = (w - iv * (cols - 1)) / (cols ? cols : 1);
  457. rest = (w - iv * (cols - 1)) - cw * cols;
  458. for (i = 0; i < cols; i++) {
  459. arrange_top_to_bottom(m, x, y, h, cw + (i < rest ? 1 : 0), ih, iv, n, MIN(rows, an - i*rows), ai + i*rows);
  460. x += cw + (i < rest ? 1 : 0) + iv;
  461. }
  462. }
  463. static void
  464. arrange_fibonacci(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai, int s)
  465. {
  466. int i, j, nv, hrest = 0, wrest = 0, nx = x, ny = y, nw = w, nh = h, r = 1;
  467. Client *c;
  468. for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) {
  469. if (j >= ai && j < (ai + an)) {
  470. if (r) {
  471. if ((i % 2 && ((nh - ih) / 2) <= (bh + 2*c->bw)) || (!(i % 2) && ((nw - iv) / 2) <= (bh + 2*c->bw))) {
  472. r = 0;
  473. }
  474. if (r && i < an - 1) {
  475. if (i % 2) {
  476. nv = (nh - ih) / 2;
  477. hrest = nh - 2*nv - ih;
  478. nh = nv;
  479. } else {
  480. nv = (nw - iv) / 2;
  481. wrest = nw - 2*nv - iv;
  482. nw = nv;
  483. }
  484. if ((i % 4) == 2 && !s)
  485. nx += nw + iv;
  486. else if ((i % 4) == 3 && !s)
  487. ny += nh + ih;
  488. }
  489. if ((i % 4) == 0) {
  490. if (s) {
  491. ny += nh + ih;
  492. nh += hrest;
  493. } else {
  494. nh -= hrest;
  495. ny -= nh + ih;
  496. }
  497. } else if ((i % 4) == 1) {
  498. nx += nw + iv;
  499. nw += wrest;
  500. } else if ((i % 4) == 2) {
  501. ny += nh + ih;
  502. nh += hrest;
  503. if (i < n - 1)
  504. nw += wrest;
  505. } else if ((i % 4) == 3) {
  506. if (s) {
  507. nx += nw + iv;
  508. nw -= wrest;
  509. } else {
  510. nw -= wrest;
  511. nx -= nw + iv;
  512. nh += hrest;
  513. }
  514. }
  515. if (i == 0) {
  516. if (an != 1) {
  517. nw = (w - iv) - (w - iv) * (1 - m->mfact);
  518. wrest = 0;
  519. }
  520. ny = y;
  521. } else if (i == 1)
  522. nw = w - nw - iv;
  523. i++;
  524. }
  525. resize(c, nx, ny, nw - 2 * c->bw, nh - 2*c->bw, False);
  526. }
  527. }
  528. }
  529. static void
  530. arrange_dwindle(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  531. {
  532. arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 1);
  533. }
  534. static void
  535. arrange_spiral(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  536. {
  537. arrange_fibonacci(m, x, y, h, w, ih, iv, n, an, ai, 0);
  538. }
  539. static void
  540. arrange_tatami(Monitor *m, int x, int y, int h, int w, int ih, int iv, int n, int an, int ai)
  541. {
  542. unsigned int i, j, nx, ny, nw, nh, tnx, tny, tnw, tnh, nhrest, hrest, wrest, areas, mats, cats;
  543. Client *c;
  544. nx = x;
  545. ny = y;
  546. nw = w;
  547. nh = h;
  548. mats = an / 5;
  549. cats = an % 5;
  550. hrest = 0;
  551. wrest = 0;
  552. areas = mats + (cats > 0);
  553. nh = (h - ih * (areas - 1)) / areas;
  554. nhrest = (h - ih * (areas - 1)) % areas;
  555. for (i = 0, j = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), j++) {
  556. if (j >= ai && j < (ai + an)) {
  557. tnw = nw;
  558. tnx = nx;
  559. tnh = nh;
  560. tny = ny;
  561. if (j < ai + cats) {
  562. /* Arrange cats (all excess clients that can't be tiled as mats). Cats sleep on mats. */
  563. switch (cats) {
  564. case 1: // fill
  565. break;
  566. case 2: // up and down
  567. if ((i % 5) == 0) //up
  568. tnh = (nh - ih) / 2 + (nh - ih) % 2;
  569. else if ((i % 5) == 1) { //down
  570. tny += (nh - ih) / 2 + (nh - ih) % 2 + ih;
  571. tnh = (nh - ih) / 2;
  572. }
  573. break;
  574. case 3: //bottom, up-left and up-right
  575. if ((i % 5) == 0) { // up-left
  576. tnw = (nw - iv) / 2 + (nw - iv) % 2;
  577. tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3;
  578. } else if ((i % 5) == 1) { // up-right
  579. tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv;
  580. tnw = (nw - iv) / 2;
  581. tnh = (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3;
  582. } else if ((i % 5) == 2) { //bottom
  583. tnh = (nh - ih) / 3;
  584. tny += (nh - ih) * 2 / 3 + (nh - ih) * 2 % 3 + ih;
  585. }
  586. break;
  587. case 4: // bottom, left, right and top
  588. if ((i % 5) == 0) { //top
  589. hrest = (nh - 2 * ih) % 4;
  590. tnh = (nh - 2 * ih) / 4 + (hrest ? 1 : 0);
  591. } else if ((i % 5) == 1) { // left
  592. tnw = (nw - iv) / 2 + (nw - iv) % 2;
  593. tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih;
  594. tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0);
  595. } else if ((i % 5) == 2) { // right
  596. tnx += (nw - iv) / 2 + (nw - iv) % 2 + iv;
  597. tnw = (nw - iv) / 2;
  598. tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + ih;
  599. tnh = (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0);
  600. } else if ((i % 5) == 3) { // bottom
  601. tny += (nh - 2 * ih) / 4 + (hrest ? 1 : 0) + (nh - 2 * ih) * 2 / 4 + (hrest > 1 ? 1 : 0) + 2 * ih;
  602. tnh = (nh - 2 * ih) / 4 + (hrest > 2 ? 1 : 0);
  603. }
  604. break;
  605. }
  606. } else {
  607. /* Arrange mats. One mat is a collection of five clients arranged tatami style */
  608. if (((i - cats) % 5) == 0) {
  609. if ((cats > 0) || ((i - cats) >= 5)) {
  610. tny = ny = ny + nh + (nhrest > 0 ? 1 : 0) + ih;
  611. --nhrest;
  612. }
  613. }
  614. switch ((i - cats) % 5) {
  615. case 0: // top-left-vert
  616. wrest = (nw - 2 * iv) % 3;
  617. hrest = (nh - 2 * ih) % 3;
  618. tnw = (nw - 2 * iv) / 3 + (wrest ? 1 : 0);
  619. tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv;
  620. break;
  621. case 1: // top-right-hor
  622. tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv;
  623. tnw = (nw - 2 * iv) * 2 / 3 + (wrest > 1 ? 1 : 0) + iv;
  624. tnh = (nh - 2 * ih) / 3 + (hrest ? 1 : 0);
  625. break;
  626. case 2: // center
  627. tnx += (nw - 2 * iv) / 3 + (wrest ? 1 : 0) + iv;
  628. tnw = (nw - 2 * iv) / 3 + (wrest > 1 ? 1 : 0);
  629. tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih;
  630. tnh = (nh - 2 * ih) / 3 + (hrest > 1 ? 1 : 0);
  631. break;
  632. case 3: // bottom-right-vert
  633. tnx += (nw - 2 * iv) * 2 / 3 + wrest + 2 * iv;
  634. tnw = (nw - 2 * iv) / 3;
  635. tny += (nh - 2 * ih) / 3 + (hrest ? 1 : 0) + ih;
  636. tnh = (nh - 2 * ih) * 2 / 3 + hrest + iv;
  637. break;
  638. case 4: // (oldest) bottom-left-hor
  639. tnw = (nw - 2 * iv) * 2 / 3 + wrest + iv;
  640. tny += (nh - 2 * ih) * 2 / 3 + hrest + 2 * iv;
  641. tnh = (nh - 2 * ih) / 3;
  642. break;
  643. }
  644. }
  645. resize(c, tnx, tny, tnw - 2 * c->bw, tnh - 2 * c->bw, False);
  646. ++i;
  647. }
  648. }
  649. }
  650. static void
  651. flextile(Monitor *m)
  652. {
  653. unsigned int n;
  654. int oh = 0, ov = 0, ih = 0, iv = 0; // gaps outer/inner horizontal/vertical
  655. #if VANITYGAPS_PATCH
  656. getgaps(m, &oh, &ov, &ih, &iv, &n);
  657. #else
  658. Client *c;
  659. for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  660. #endif // VANITYGAPS_PATCH
  661. if (m->lt[m->sellt]->preset.layout != m->ltaxis[LAYOUT] ||
  662. m->lt[m->sellt]->preset.masteraxis != m->ltaxis[MASTER] ||
  663. m->lt[m->sellt]->preset.stack1axis != m->ltaxis[STACK] ||
  664. m->lt[m->sellt]->preset.stack2axis != m->ltaxis[STACK2])
  665. setflexsymbols(m, n);
  666. else if (m->lt[m->sellt]->preset.symbolfunc != NULL)
  667. m->lt[m->sellt]->preset.symbolfunc(m, n);
  668. if (n == 0)
  669. return;
  670. #if VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH
  671. /* No outer gap if full screen monocle */
  672. if (abs(m->ltaxis[MASTER]) == MONOCLE && (abs(m->ltaxis[LAYOUT]) == NO_SPLIT || n <= m->nmaster)) {
  673. oh = 0;
  674. ov = 0;
  675. }
  676. #endif // VANITYGAPS_PATCH && !VANITYGAPS_MONOCLE_PATCH
  677. (&flexlayouts[abs(m->ltaxis[LAYOUT])])->arrange(m, m->wx + ov, m->wy + oh, m->wh - 2*oh, m->ww - 2*ov, ih, iv, n);
  678. return;
  679. }
  680. static void
  681. setflexsymbols(Monitor *m, unsigned int n)
  682. {
  683. int l;
  684. char sym1, sym2, sym3;
  685. Client *c;
  686. if (n == 0)
  687. for (c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
  688. l = abs(m->ltaxis[LAYOUT]);
  689. if (m->ltaxis[MASTER] == MONOCLE && (l == NO_SPLIT || !m->nmaster || n <= m->nmaster)) {
  690. monoclesymbols(m, n);
  691. return;
  692. }
  693. if (m->ltaxis[STACK] == MONOCLE && (l == SPLIT_VERTICAL || l == SPLIT_HORIZONTAL_FIXED)) {
  694. decksymbols(m, n);
  695. return;
  696. }
  697. /* Layout symbols */
  698. if (l == NO_SPLIT || !m->nmaster) {
  699. sym1 = sym2 = sym3 = (int)tilesymb[m->ltaxis[MASTER]];
  700. } else {
  701. sym2 = layoutsymb[l];
  702. if (m->ltaxis[LAYOUT] < 0) {
  703. sym1 = tilesymb[m->ltaxis[STACK]];
  704. sym3 = tilesymb[m->ltaxis[MASTER]];
  705. } else {
  706. sym1 = tilesymb[m->ltaxis[MASTER]];
  707. sym3 = tilesymb[m->ltaxis[STACK]];
  708. }
  709. }
  710. snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3);
  711. }
  712. static void
  713. monoclesymbols(Monitor *m, unsigned int n)
  714. {
  715. if (n > 0)
  716. snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
  717. else
  718. snprintf(m->ltsymbol, sizeof m->ltsymbol, "[M]");
  719. }
  720. static void
  721. decksymbols(Monitor *m, unsigned int n)
  722. {
  723. if (n > m->nmaster)
  724. snprintf(m->ltsymbol, sizeof m->ltsymbol, "[]%d", n);
  725. else
  726. snprintf(m->ltsymbol, sizeof m->ltsymbol, "[D]");
  727. }
  728. /* Mirror layout axis for flextile */
  729. void
  730. mirrorlayout(const Arg *arg)
  731. {
  732. if (!selmon->lt[selmon->sellt]->arrange)
  733. return;
  734. selmon->ltaxis[LAYOUT] *= -1;
  735. #if PERTAG_PATCH
  736. selmon->pertag->ltaxis[selmon->pertag->curtag][0] = selmon->ltaxis[LAYOUT];
  737. #endif // PERTAG_PATCH
  738. arrange(selmon);
  739. }
  740. /* Rotate layout axis for flextile */
  741. void
  742. rotatelayoutaxis(const Arg *arg)
  743. {
  744. int incr = (arg->i > 0 ? 1 : -1);
  745. int axis = abs(arg->i) - 1;
  746. if (!selmon->lt[selmon->sellt]->arrange)
  747. return;
  748. if (axis == LAYOUT) {
  749. if (selmon->ltaxis[LAYOUT] >= 0) {
  750. selmon->ltaxis[LAYOUT] += incr;
  751. if (selmon->ltaxis[LAYOUT] >= LAYOUT_LAST)
  752. selmon->ltaxis[LAYOUT] = 0;
  753. else if (selmon->ltaxis[LAYOUT] < 0)
  754. selmon->ltaxis[LAYOUT] = LAYOUT_LAST - 1;
  755. } else {
  756. selmon->ltaxis[LAYOUT] -= incr;
  757. if (selmon->ltaxis[LAYOUT] <= -LAYOUT_LAST)
  758. selmon->ltaxis[LAYOUT] = 0;
  759. else if (selmon->ltaxis[LAYOUT] > 0)
  760. selmon->ltaxis[LAYOUT] = -LAYOUT_LAST + 1;
  761. }
  762. } else {
  763. selmon->ltaxis[axis] += incr;
  764. if (selmon->ltaxis[axis] >= AXIS_LAST)
  765. selmon->ltaxis[axis] = 0;
  766. else if (selmon->ltaxis[axis] < 0)
  767. selmon->ltaxis[axis] = AXIS_LAST - 1;
  768. }
  769. #if PERTAG_PATCH
  770. selmon->pertag->ltaxis[selmon->pertag->curtag][axis] = selmon->ltaxis[axis];
  771. #endif // PERTAG_PATCH
  772. arrange(selmon);
  773. setflexsymbols(selmon, 0);
  774. }
  775. void
  776. incnstack(const Arg *arg)
  777. {
  778. #if PERTAG_PATCH
  779. selmon->nstack = selmon->pertag->nstacks[selmon->pertag->curtag] = MAX(selmon->nstack + arg->i, 0);
  780. #else
  781. selmon->nstack = MAX(selmon->nstack + arg->i, 0);
  782. #endif // PERTAG_PATCH
  783. arrange(selmon);
  784. }