layout.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. /*
  2. * layout.c
  3. * Copyright © 2008, 2009 Martin Duquesnoy <xorg62@gmail.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of the nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. #include "wmfs.h"
  33. /** Arrange All
  34. */
  35. void
  36. arrange(int screen, Bool update_layout)
  37. {
  38. Client *c;
  39. if(screen < 0 || screen > screen_count())
  40. screen = screen_get_sel();
  41. for(c = clients; c; c = c->next)
  42. if(c->screen == screen)
  43. {
  44. if(!ishide(c, screen))
  45. client_unhide(c);
  46. else
  47. client_hide(c);
  48. }
  49. if(update_layout)
  50. tags[screen][seltag[screen]].layout.func(screen);
  51. infobar_draw(screen);
  52. return;
  53. }
  54. /** The free layout function
  55. */
  56. void
  57. freelayout(int screen)
  58. {
  59. Client *c;
  60. for(c = clients; c; c = c->next)
  61. if(!ishide(c, selscreen)
  62. && c->screen == screen_get_sel()
  63. && !(c->flags & MaxFlag))
  64. {
  65. client_moveresize(c, c->free_geo, True);
  66. c->flags &= ~(TileFlag | LMaxFlag);
  67. }
  68. ewmh_update_current_tag_prop();
  69. return;
  70. }
  71. /** Layout switching function
  72. * \param b Bool True : next False : previous
  73. */
  74. void
  75. layoutswitch(Bool b)
  76. {
  77. int i;
  78. Client *c;
  79. screen_get_sel();
  80. if(tags[selscreen][seltag[selscreen]].layout.func == freelayout)
  81. for(c = clients; c && (c->tag != seltag[selscreen] && c->screen != selscreen); c = c->next)
  82. {
  83. c->ogeo = c->geo;
  84. c->free_geo = c->geo;
  85. }
  86. for(i = 0; i < conf.nlayout; ++i)
  87. {
  88. if(tags[selscreen][seltag[selscreen]].layout.func == conf.layout[i].func
  89. && tags[selscreen][seltag[selscreen]].layout.symbol == conf.layout[i].symbol)
  90. {
  91. if(b)
  92. tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + 1) % conf.nlayout];
  93. else
  94. tags[selscreen][seltag[selscreen]].layout = conf.layout[(i + conf.nlayout - 1) % conf.nlayout];
  95. break;
  96. }
  97. }
  98. ewmh_update_current_tag_prop();
  99. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  100. infobar_draw(selscreen);
  101. return;
  102. }
  103. /** Set the next layout
  104. * \param cmd uicb_t type unused
  105. */
  106. void
  107. uicb_layout_next(uicb_t cmd)
  108. {
  109. layoutswitch(True);
  110. return;
  111. }
  112. /** Set the previous layout
  113. * \param cmd uicb_t type unused
  114. */
  115. void
  116. uicb_layout_prev(uicb_t cmd)
  117. {
  118. layoutswitch(False);
  119. return;
  120. }
  121. /** Max layout function
  122. */
  123. void
  124. maxlayout(int screen)
  125. {
  126. Client *c;
  127. int i;
  128. for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
  129. {
  130. c->flags &= ~TileFlag;
  131. c->flags |= LMaxFlag;
  132. client_maximize(c);
  133. }
  134. ewmh_update_current_tag_prop();
  135. return;
  136. }
  137. /** Sort all the client that can be
  138. * tiled
  139. * \param c Client pointer
  140. * \return a client pointer
  141. */
  142. Client*
  143. tiled_client(int screen, Client *c)
  144. {
  145. for(;c && ((c->flags & MaxFlag)
  146. || (c->flags & FreeFlag)
  147. || (c->flags & FSSFlag)
  148. || (c->flags & AboveFlag)
  149. || c->screen != screen
  150. || ishide(c, screen)); c = c->next);
  151. return c;
  152. }
  153. /** Set the mwfact
  154. * \param cmd Mwfact (string)
  155. */
  156. void
  157. uicb_set_mwfact(uicb_t cmd)
  158. {
  159. double c;
  160. screen_get_sel();
  161. CHECK((sscanf(cmd, "%lf", &c)));
  162. if(tags[selscreen][seltag[selscreen]].mwfact + c > 0.95
  163. || tags[selscreen][seltag[selscreen]].mwfact + c < 0.05)
  164. return;
  165. tags[selscreen][seltag[selscreen]].mwfact += c;
  166. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  167. ewmh_update_current_tag_prop();
  168. return;
  169. }
  170. /** Set the nmaster
  171. * \param cmd Nmaster (string)
  172. */
  173. void
  174. uicb_set_nmaster(uicb_t cmd)
  175. {
  176. int nc, n = atoi(cmd);
  177. Client *c;
  178. screen_get_sel();
  179. for(nc = 0, c = tiled_client(selscreen, clients); c; c = tiled_client(selscreen, c->next), ++nc);
  180. if(!nc || tags[selscreen][seltag[selscreen]].nmaster + n == 0
  181. || tags[selscreen][seltag[selscreen]].nmaster + n > nc)
  182. return;
  183. tags[selscreen][seltag[selscreen]].nmaster += n;
  184. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  185. ewmh_update_current_tag_prop();
  186. return;
  187. }
  188. void
  189. uicb_set_client_layer(uicb_t cmd)
  190. {
  191. int n = atoi(cmd);
  192. screen_get_sel();
  193. CHECK(sel);
  194. if(sel->layer + n < 1
  195. || sel->layer + n > tags[selscreen][seltag[selscreen]].layers)
  196. return;
  197. sel->layer += n;
  198. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  199. return;
  200. }
  201. void
  202. uicb_set_layer(uicb_t cmd)
  203. {
  204. int n = atoi(cmd);
  205. screen_get_sel();
  206. if(tags[selscreen][seltag[selscreen]].layers + n < 1)
  207. return;
  208. tags[selscreen][seltag[selscreen]].layers += n;
  209. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  210. return;
  211. }
  212. /** Grid layout function
  213. */
  214. void
  215. grid(int screen)
  216. {
  217. Client *c;
  218. XRectangle sg = sgeo[screen];
  219. XRectangle cgeo = {sg.x, sg.y, 0, 0};
  220. unsigned int i, n, cols, rows, cpcols = 0;
  221. for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
  222. CHECK(n);
  223. for(rows = 0; rows <= n / 2; ++rows)
  224. if(rows * rows >= n)
  225. break;
  226. cols = (rows && ((rows - 1) * rows) >= n)
  227. ? rows - 1
  228. : rows;
  229. for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
  230. {
  231. /* Set client property */
  232. c->flags &= ~(MaxFlag | LMaxFlag);
  233. c->flags |= TileFlag;
  234. ++cpcols;
  235. cgeo.width = (sg.width / cols) - (BORDH * 2);
  236. cgeo.height = (sg.height / rows) - BORDH;
  237. /* Last row's and last client remainder */
  238. if(cpcols == rows || i + 1 == n)
  239. cgeo.height = sg.y + sg.height - cgeo.y - BORDH;
  240. /* Last column's client remainder */
  241. if(i >= rows * (cols - 1))
  242. cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
  243. /* Resize */
  244. client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
  245. /* Set all the other size with current client info */
  246. cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
  247. if(cpcols + 1 > rows)
  248. {
  249. cpcols = 0;
  250. cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
  251. cgeo.y = sg.y;
  252. }
  253. }
  254. ewmh_update_current_tag_prop();
  255. return;
  256. }
  257. /** Multi tile function
  258. * \param type Postion type { Top, Bottom, Left, Right }
  259. */
  260. void
  261. multi_tile(int screen, Position type)
  262. {
  263. Client *c;
  264. XRectangle sg = sgeo[screen];
  265. XRectangle mastergeo = {sg.x, sg.y, 0, 0};
  266. XRectangle cgeo = {sg.x, sg.y, 0, 0};
  267. uint i, n, tilesize, mwfact, nmaster = tags[screen][seltag[screen]].nmaster;
  268. for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
  269. CHECK(n);
  270. /* FIX NMASTER */
  271. nmaster = (n < nmaster) ? n : nmaster;
  272. /* SET MWFACT */
  273. mwfact = (type == Top || type == Bottom)
  274. ? tags[screen][seltag[screen]].mwfact * sg.height
  275. : tags[screen][seltag[screen]].mwfact * sg.width;
  276. /* MASTER SIZE */
  277. if(type == Top || type == Bottom)
  278. {
  279. if(type == Top)
  280. mastergeo.y = (n <= nmaster) ? sg.y : sg.y + (sg.height - mwfact) - BORDH;
  281. mastergeo.width = (sg.width / nmaster) - (BORDH * 4);
  282. mastergeo.height = (n <= nmaster) ? sg.height - BORDH : mwfact;
  283. }
  284. else
  285. {
  286. if(type == Left)
  287. mastergeo.x = (n <= nmaster) ? sg.x : (sg.x + sg.width) - mwfact - (BORDH * 2);
  288. mastergeo.width = (n <= nmaster) ? sg.width - (BORDH * 2) : mwfact;
  289. mastergeo.height = (sg.height / nmaster) - BORDH;
  290. }
  291. /* TILED SIZE */
  292. if(n > nmaster)
  293. {
  294. if(type == Top || type == Bottom)
  295. tilesize = sg.width / (n - nmaster) - (BORDH * 4);
  296. else
  297. tilesize = sg.height / (n - nmaster) - ((BORDH * 2) + TBARH);
  298. }
  299. for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
  300. {
  301. /* Set client property */
  302. c->flags &= ~(MaxFlag | LMaxFlag);
  303. c->flags |= TileFlag;
  304. /* MASTER */
  305. if(i < nmaster)
  306. {
  307. cgeo.width = mastergeo.width;
  308. cgeo.height = mastergeo.height;
  309. if(type == Top || type == Bottom)
  310. cgeo.y = mastergeo.y;
  311. else
  312. {
  313. cgeo.x = mastergeo.x;
  314. cgeo.height -= (TBARH + BORDH);
  315. }
  316. }
  317. /* TILED */
  318. else
  319. {
  320. if(i == nmaster)
  321. {
  322. switch(type)
  323. {
  324. case Top:
  325. case Left:
  326. cgeo.y = sg.y;
  327. cgeo.x = sg.x;
  328. break;
  329. case Bottom:
  330. cgeo.y += mastergeo.height + TBARH + BORDH;
  331. cgeo.x = sg.x;
  332. break;
  333. default:
  334. case Right:
  335. cgeo.x += mastergeo.width + (BORDH * 2);
  336. cgeo.y = sg.y;
  337. break;
  338. }
  339. }
  340. if(type == Top || type == Bottom)
  341. {
  342. cgeo.width = tilesize;
  343. cgeo.height = sg.height - mastergeo.height - TBARH - (BORDH * 2);
  344. }
  345. else
  346. {
  347. cgeo.width = sg.width - mastergeo.width - (BORDH * 4);
  348. cgeo.height = tilesize;
  349. }
  350. }
  351. /* REMAINDER */
  352. if(i + 1 == n || i + 1 == (n < nmaster ? n : nmaster))
  353. {
  354. if(type == Top || type == Bottom)
  355. cgeo.width = sg.width - (cgeo.x - (sg.x - (BORDH * 2)));
  356. else
  357. cgeo.height = (sg.y + sg.height) - cgeo.y - BORDH;
  358. }
  359. /* Magic instant */
  360. client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
  361. /* Set the position of the next client */
  362. if(type == Top || type == Bottom)
  363. cgeo.x = c->geo.x + c->geo.width + (BORDH * 2);
  364. else
  365. cgeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
  366. }
  367. ewmh_update_current_tag_prop();
  368. return;
  369. }
  370. /** Mirror layout function
  371. * \param screen Screen to execute this function
  372. * \param horizont To specify the mirror mode (vertical/horizontal)
  373. */
  374. void
  375. mirror(int screen, Bool horizontal)
  376. {
  377. Client *c;
  378. XRectangle sg = sgeo[screen];
  379. XRectangle mastergeo = {sg.x, sg.y, sg.width, sg.height};
  380. XRectangle cgeo = {sg.x, sg.y , sg.width, sg.height};
  381. XRectangle nextg[2] = { {0} };
  382. uint i, n, tilesize, mwfact;
  383. uint nmaster = tags[screen][seltag[screen]].nmaster;
  384. int pa, imp;
  385. Bool isp = 0;
  386. for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
  387. CHECK(n);
  388. /* Fix nmaster */
  389. nmaster = (n < nmaster) ? n : nmaster;
  390. imp = ((n - (nmaster - 1)) / 2);
  391. pa = ((n - (nmaster - 1)) / 2) - (((n - (nmaster - 1)) % 2) ? 0 : 1);
  392. /* Set mwfact */
  393. if(tags[screen][seltag[screen]].mwfact < 0.55)
  394. tags[screen][seltag[screen]].mwfact = 0.55;
  395. mwfact = tags[screen][seltag[screen]].mwfact * ((horizontal) ? sg.height : sg.width);
  396. /* Master size */
  397. if(horizontal)
  398. {
  399. mastergeo.width = (sg.width / nmaster) - (BORDH * 2);
  400. mastergeo.height -= BORDH;
  401. }
  402. else
  403. {
  404. mastergeo.width -= BORDH * 2;
  405. mastergeo.height = (sg.height / nmaster) - (TBARH + (BORDH * 2));
  406. }
  407. if(n == nmaster + 1)
  408. {
  409. if(horizontal)
  410. {
  411. mastergeo.height = mwfact - ((BORDH * 2) + TBARH);
  412. tilesize = (sg.height - mastergeo.height) - ((BORDH * 2) + TBARH);
  413. }
  414. else
  415. {
  416. mastergeo.width = mwfact - (BORDH * 3);
  417. tilesize = (sg.width - mastergeo.width) - (BORDH * 4);
  418. }
  419. }
  420. if(n > nmaster + 1)
  421. {
  422. if(horizontal)
  423. {
  424. mastergeo.y = (sg.y + (sg.height - mwfact)) + TBARH + BORDH;
  425. mastergeo.height = (2 * mwfact - sg.height) - ((BORDH * 3) + (TBARH * 2));
  426. tilesize = (mwfact - mastergeo.height) - ((BORDH * 3) + (TBARH * 2));
  427. }
  428. else
  429. {
  430. mastergeo.x = (sg.x + (sg.width - mwfact)) + BORDH;
  431. mastergeo.width = ((2 * mwfact - sg.width) - (BORDH * 4));
  432. tilesize = (mwfact - mastergeo.width) - (BORDH * 5);
  433. }
  434. }
  435. for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
  436. {
  437. /* Set client property */
  438. c->flags &= ~(MaxFlag | LMaxFlag);
  439. c->flags |= TileFlag;
  440. if(i < nmaster)
  441. {
  442. cgeo = mastergeo;
  443. /* Master remainder */
  444. if(i + 1 == nmaster)
  445. {
  446. if(horizontal)
  447. cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
  448. else
  449. cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
  450. }
  451. }
  452. else
  453. {
  454. if(horizontal)
  455. cgeo.height = tilesize;
  456. else
  457. cgeo.width = tilesize;
  458. if((i + nmaster) % 2)
  459. {
  460. isp = 1;
  461. if(horizontal)
  462. {
  463. cgeo.y = sg.y;
  464. cgeo.width = (sg.width / pa) - (BORDH * 2);
  465. }
  466. else
  467. {
  468. cgeo.x = sg.x;
  469. cgeo.height = (sg.height / pa) - (TBARH + (BORDH * 2));
  470. }
  471. }
  472. else
  473. {
  474. isp = 0;
  475. if(horizontal)
  476. {
  477. cgeo.y = (sg.y + mwfact) - BORDH;
  478. cgeo.width = (sg.width / imp) - (BORDH * 2);
  479. }
  480. else
  481. {
  482. cgeo.x = (sg.x + mwfact) - BORDH;
  483. cgeo.height = (sg.height / imp) - (TBARH + (BORDH * 2));
  484. }
  485. }
  486. /* Remainder */
  487. if(i + 1 == n || i + 1 == n - 1)
  488. {
  489. if(horizontal)
  490. cgeo.width = (sg.x + sg.width) - (cgeo.x + (BORDH * 2));
  491. else
  492. cgeo.height = (sg.y + sg.height) - (cgeo.y + BORDH);
  493. }
  494. }
  495. client_moveresize(c, cgeo, tags[screen][seltag[screen]].resizehint);
  496. if(i >= nmaster)
  497. nextg[!isp] = c->geo;
  498. /* Next y/x position */
  499. if(i >= nmaster - 1)
  500. {
  501. if(horizontal)
  502. {
  503. if(i == nmaster || i == nmaster - 1)
  504. cgeo.x = sg.x;
  505. else
  506. cgeo.x = nextg[isp].x + nextg[isp].width + BORDH * 2;
  507. }
  508. else
  509. {
  510. if(i == nmaster || i == nmaster - 1)
  511. cgeo.y = sg.y;
  512. else
  513. cgeo.y = nextg[isp].y + nextg[isp].height + BORDH + TBARH;
  514. }
  515. }
  516. else if (i <= nmaster - 1)
  517. {
  518. if(horizontal)
  519. mastergeo.x = c->geo.x + c->geo.width + BORDH * 2;
  520. else
  521. mastergeo.y = c->geo.y + c->geo.height + BORDH + TBARH;
  522. }
  523. }
  524. ewmh_update_current_tag_prop();
  525. return;
  526. }
  527. /** Layer layout function
  528. */
  529. void
  530. layer(int screen)
  531. {
  532. Client *c;
  533. XRectangle geo = { 0 };
  534. XRectangle sg = sgeo[screen];
  535. int n, i, l = tags[screen][seltag[screen]].layers;
  536. int *x = NULL;
  537. int *nl = NULL;
  538. int *ncl = NULL;
  539. for(n = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++n);
  540. CHECK(n);
  541. x = emalloc(l + 1, sizeof(int));
  542. nl = emalloc(l + 1, sizeof(int));
  543. ncl = emalloc(l + 1, sizeof(int));
  544. for(i = 0; i < l + 1; ++i)
  545. {
  546. x[i] = sg.x;
  547. nl[i] = 0;
  548. ncl[i] = 0;
  549. }
  550. for(c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next))
  551. {
  552. for(; c->layer > l; --(c->layer));
  553. ++nl[c->layer];
  554. }
  555. for(i = 0, c = tiled_client(screen, clients); c; c = tiled_client(screen, c->next), ++i)
  556. {
  557. /* Set client property */
  558. c->flags &= ~(MaxFlag | LMaxFlag);
  559. c->flags |= TileFlag;
  560. ++ncl[c->layer];
  561. geo.x = x[c->layer];
  562. geo.height = (sg.height / l) - (BORDH + TBARH);
  563. geo.width = (sg.width / ((nl[c->layer]) ? nl[c->layer] : 1)) - BORDH * 2;
  564. geo.y = sg.y + ((geo.height + TBARH + BORDH) * c->layer) - (geo.height + TBARH + BORDH);
  565. if(c->layer == l)
  566. geo.height = (sg.y + sg.height) - geo.y - BORDH;
  567. if(ncl[c->layer] == nl[c->layer])
  568. geo.width = sg.width - (geo.x - (sg.x - (BORDH * 2)));
  569. client_moveresize(c, geo, False);
  570. x[c->layer] = geo.x + geo.width + BORDH * 2;
  571. }
  572. free(x);
  573. free(nl);
  574. free(ncl);
  575. ewmh_update_current_tag_prop();
  576. return;
  577. }
  578. /** Tile Right function
  579. */
  580. void
  581. tile(int screen)
  582. {
  583. multi_tile(screen, Right);
  584. return;
  585. }
  586. /** Tile Left function
  587. */
  588. void
  589. tile_left(int screen)
  590. {
  591. multi_tile(screen, Left);
  592. return;
  593. }
  594. /** Tile Top function
  595. */
  596. void
  597. tile_top(int screen)
  598. {
  599. multi_tile(screen, Top);
  600. return;
  601. }
  602. /** Tile Bottom function
  603. */
  604. void
  605. tile_bottom(int screen)
  606. {
  607. multi_tile(screen, Bottom);
  608. return;
  609. }
  610. /** Mirror tile vertical function
  611. */
  612. void
  613. mirror_vertical(int screen)
  614. {
  615. mirror(screen, False);
  616. return;
  617. }
  618. /** Mirror tile horizontal function
  619. */
  620. void
  621. mirror_horizontal(int screen)
  622. {
  623. mirror(screen, True);
  624. return;
  625. }
  626. /** Put the selected client to the master postion
  627. * \param cmd uicb_t type unused
  628. */
  629. void
  630. uicb_tile_switch(uicb_t cmd)
  631. {
  632. layout_set_client_master (sel);
  633. return;
  634. }
  635. /** Toggle the selected client to free
  636. * \param cmd uicb_t type unused
  637. */
  638. void
  639. uicb_togglefree(uicb_t cmd)
  640. {
  641. if(!sel || sel->screen != screen_get_sel() || (sel->flags & FSSFlag))
  642. return;
  643. sel->flags ^= FreeFlag;
  644. if((sel->flags & FreeFlag))
  645. {
  646. sel->flags &= ~(TileFlag | MaxFlag | LMaxFlag);
  647. client_moveresize(sel, sel->free_geo, True);
  648. client_raise(sel);
  649. }
  650. else
  651. {
  652. sel->free_geo = sel->geo;
  653. sel->ogeo = sel->geo;
  654. }
  655. client_update_attributes(sel);
  656. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  657. return;
  658. }
  659. /** Toggle the selected client to max
  660. * \param cmd uicb_t type unused
  661. */
  662. void
  663. uicb_togglemax(uicb_t cmd)
  664. {
  665. if(!sel || ishide(sel, selscreen)
  666. || (sel->flags & HintFlag)|| (sel->flags & FSSFlag))
  667. return;
  668. if(!(sel->flags & MaxFlag))
  669. {
  670. sel->ogeo = sel->geo;
  671. sel->free_geo = sel->geo;
  672. sel->flags &= ~(TileFlag | FreeFlag);
  673. client_maximize(sel);
  674. client_raise(sel);
  675. sel->flags |= MaxFlag;
  676. }
  677. else
  678. {
  679. sel->geo = sel->free_geo;
  680. client_moveresize(sel, sel->geo, True);
  681. sel->flags &= ~MaxFlag;
  682. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  683. }
  684. return;
  685. }
  686. /** Toggle the resizehint
  687. * \param cmd uicb_t type
  688. */
  689. void
  690. uicb_toggle_resizehint(uicb_t cmd)
  691. {
  692. screen_get_sel();
  693. tags[selscreen][seltag[selscreen]].resizehint = !tags[selscreen][seltag[selscreen]].resizehint;
  694. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  695. return;
  696. }
  697. /** Toggle abovefc option
  698. *\param cmd uicb_t type
  699. */
  700. void
  701. uicb_toggle_abovefc(uicb_t cmd)
  702. {
  703. Client *c;
  704. screen_get_sel();
  705. if(!(tags[selscreen][seltag[selscreen]].abovefc = !tags[selscreen][seltag[selscreen]].abovefc))
  706. {
  707. for(c = clients; c; c = c->next)
  708. if(c->flags & AboveFlag
  709. && c->screen == selscreen
  710. && c->tag == seltag[selscreen])
  711. {
  712. c->flags &= ~AboveFlag;
  713. break;
  714. }
  715. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  716. }
  717. client_focus(sel);
  718. return;
  719. }
  720. /** Set the layout
  721. * \param cmd uicb_t type
  722. */
  723. void
  724. uicb_set_layout(uicb_t cmd)
  725. {
  726. int i, j, n;
  727. screen_get_sel();
  728. /* Set layout_list lenght */
  729. for(n = 0; layout_list[n].name != NULL && layout_list[n].func != NULL; ++n);
  730. for(i = 0; i < n; ++i)
  731. if(!strcmp(cmd, _strdup(layout_list[i].name)))
  732. for(j = 0; j < LEN(conf.layout); ++j)
  733. if(layout_list[i].func == conf.layout[j].func)
  734. tags[selscreen][seltag[selscreen]].layout = conf.layout[j];
  735. arrange(selscreen, True);
  736. return;
  737. }
  738. /** Set the client as master
  739. * \param c Client
  740. */
  741. void
  742. layout_set_client_master(Client *c)
  743. {
  744. screen_get_sel();
  745. if(!c || (c->flags & HintFlag) || !(c->flags & TileFlag)
  746. || (c->flags & FSSFlag))
  747. return;
  748. if(c == tiled_client(selscreen, clients))
  749. CHECK((c = tiled_client(selscreen, c->next)));
  750. client_detach(c);
  751. client_attach(c);
  752. client_focus(c);
  753. tags[selscreen][seltag[selscreen]].layout.func(selscreen);
  754. return;
  755. }