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.

322 lines
5.2 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
  2. * See LICENSE file for license details.
  3. */
  4. #include "dwm.h"
  5. /* static */
  6. static Client *
  7. nexttiled(Client *c) {
  8. for(c = getnext(c); c && c->isfloat; c = getnext(c->next));
  9. return c;
  10. }
  11. static Bool
  12. ismaster(Client *c) {
  13. Client *cl;
  14. unsigned int i;
  15. for(cl = nexttiled(clients), i = 0; cl && cl != c; cl = nexttiled(cl->next), i++);
  16. return i < nmaster;
  17. }
  18. static void
  19. pop(Client *c) {
  20. detach(c);
  21. if(clients)
  22. clients->prev = c;
  23. c->next = clients;
  24. clients = c;
  25. }
  26. static void
  27. swap(Client *c1, Client *c2) {
  28. Client tmp = *c1;
  29. Client *c1p = c1->prev;
  30. Client *c1n = c1->next;
  31. Client *c2p = c2->prev;
  32. Client *c2n = c2->next;
  33. *c1 = *c2;
  34. *c2 = tmp;
  35. c1->prev = c1p;
  36. c1->next = c1n;
  37. c2->prev = c2p;
  38. c2->next = c2n;
  39. }
  40. static void
  41. togglemax(Client *c) {
  42. XEvent ev;
  43. if(c->isfixed)
  44. return;
  45. if((c->ismax = !c->ismax)) {
  46. c->rx = c->x; c->x = wax;
  47. c->ry = c->y; c->y = way;
  48. c->rw = c->w; c->w = waw - 2 * BORDERPX;
  49. c->rh = c->h; c->h = wah - 2 * BORDERPX;
  50. }
  51. else {
  52. c->x = c->rx;
  53. c->y = c->ry;
  54. c->w = c->rw;
  55. c->h = c->rh;
  56. }
  57. resize(c, True, TopLeft);
  58. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  59. }
  60. static Client *
  61. topofstack() {
  62. Client *c;
  63. unsigned int i;
  64. for(c = nexttiled(clients), i = 0; c && i < nmaster; c = nexttiled(c->next), i++);
  65. return (i < nmaster) ? NULL : c;
  66. }
  67. /* extern */
  68. void (*arrange)(void) = DEFMODE;
  69. void
  70. detach(Client *c) {
  71. if(c->prev)
  72. c->prev->next = c->next;
  73. if(c->next)
  74. c->next->prev = c->prev;
  75. if(c == clients)
  76. clients = c->next;
  77. c->next = c->prev = NULL;
  78. }
  79. void
  80. dofloat(void) {
  81. Client *c;
  82. for(c = clients; c; c = c->next) {
  83. if(isvisible(c)) {
  84. resize(c, True, TopLeft);
  85. }
  86. else
  87. ban(c);
  88. }
  89. if(!sel || !isvisible(sel)) {
  90. for(c = stack; c && !isvisible(c); c = c->snext);
  91. focus(c);
  92. }
  93. restack();
  94. }
  95. void
  96. dotile(void) {
  97. unsigned int i, n, mw, mh, tw, th;
  98. Client *c;
  99. for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  100. n++;
  101. /* window geoms */
  102. mw = (n > nmaster) ? (waw * master) / 1000 : waw;
  103. mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
  104. tw = waw - mw;
  105. th = (n > nmaster) ? wah / (n - nmaster) : 0;
  106. for(i = 0, c = clients; c; c = c->next)
  107. if(isvisible(c)) {
  108. if(c->isfloat) {
  109. resize(c, True, TopLeft);
  110. continue;
  111. }
  112. c->ismax = False;
  113. c->x = wax;
  114. c->y = way;
  115. if(i < nmaster) {
  116. c->y += i * mh;
  117. c->w = mw - 2 * BORDERPX;
  118. c->h = mh - 2 * BORDERPX;
  119. }
  120. else { /* tile window */
  121. c->x += mw;
  122. c->w = tw - 2 * BORDERPX;
  123. if(th > bh) {
  124. c->y += (i - nmaster) * th;
  125. c->h = th - 2 * BORDERPX;
  126. }
  127. else /* fallback if th < bh */
  128. c->h = wah - 2 * BORDERPX;
  129. }
  130. resize(c, False, TopLeft);
  131. i++;
  132. }
  133. else
  134. ban(c);
  135. if(!sel || !isvisible(sel)) {
  136. for(c = stack; c && !isvisible(c); c = c->snext);
  137. focus(c);
  138. }
  139. restack();
  140. }
  141. void
  142. focusnext(Arg *arg) {
  143. Client *c;
  144. if(!sel)
  145. return;
  146. if(!(c = getnext(sel->next)))
  147. c = getnext(clients);
  148. if(c) {
  149. focus(c);
  150. restack();
  151. }
  152. }
  153. void
  154. focusprev(Arg *arg) {
  155. Client *c;
  156. if(!sel)
  157. return;
  158. if(!(c = getprev(sel->prev))) {
  159. for(c = clients; c && c->next; c = c->next);
  160. c = getprev(c);
  161. }
  162. if(c) {
  163. focus(c);
  164. restack();
  165. }
  166. }
  167. void
  168. incnmaster(Arg *arg) {
  169. if((nmaster + arg->i < 1) || (wah / (nmaster + arg->i) < bh))
  170. return;
  171. nmaster += arg->i;
  172. arrange();
  173. }
  174. Bool
  175. isvisible(Client *c) {
  176. unsigned int i;
  177. for(i = 0; i < ntags; i++)
  178. if(c->tags[i] && seltag[i])
  179. return True;
  180. return False;
  181. }
  182. void
  183. resizemaster(Arg *arg) {
  184. if(arg->i == 0)
  185. master = MASTER;
  186. else {
  187. if(master + arg->i > 950 || master + arg->i < 50)
  188. return;
  189. master += arg->i;
  190. }
  191. arrange();
  192. }
  193. void
  194. restack(void) {
  195. Client *c;
  196. XEvent ev;
  197. if(!sel) {
  198. drawstatus();
  199. return;
  200. }
  201. if(sel->isfloat || arrange == dofloat) {
  202. XRaiseWindow(dpy, sel->win);
  203. XRaiseWindow(dpy, sel->twin);
  204. }
  205. if(arrange != dofloat) {
  206. if(!sel->isfloat) {
  207. XLowerWindow(dpy, sel->twin);
  208. XLowerWindow(dpy, sel->win);
  209. }
  210. for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
  211. if(c == sel)
  212. continue;
  213. XLowerWindow(dpy, c->twin);
  214. XLowerWindow(dpy, c->win);
  215. }
  216. }
  217. drawall();
  218. XSync(dpy, False);
  219. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  220. }
  221. void
  222. togglefloat(Arg *arg) {
  223. if (!sel || arrange == dofloat)
  224. return;
  225. sel->isfloat = !sel->isfloat;
  226. arrange();
  227. }
  228. void
  229. togglemode(Arg *arg) {
  230. arrange = (arrange == dofloat) ? dotile : dofloat;
  231. if(sel)
  232. arrange();
  233. else
  234. drawstatus();
  235. }
  236. void
  237. toggleview(Arg *arg) {
  238. unsigned int i;
  239. seltag[arg->i] = !seltag[arg->i];
  240. for(i = 0; i < ntags && !seltag[i]; i++);
  241. if(i == ntags)
  242. seltag[arg->i] = True; /* cannot toggle last view */
  243. arrange();
  244. }
  245. void
  246. view(Arg *arg) {
  247. unsigned int i;
  248. for(i = 0; i < ntags; i++)
  249. seltag[i] = (arg->i == -1) ? True : False;
  250. if(arg->i >= 0 && arg->i < ntags)
  251. seltag[arg->i] = True;
  252. arrange();
  253. }
  254. void
  255. zoom(Arg *arg) {
  256. unsigned int n;
  257. Client *c;
  258. if(!sel)
  259. return;
  260. if(sel->isfloat || (arrange == dofloat)) {
  261. togglemax(sel);
  262. return;
  263. }
  264. for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  265. n++;
  266. c = sel;
  267. if(arrange == dofloat)
  268. return;
  269. else if(n <= nmaster)
  270. pop(c);
  271. else if(ismaster(sel)) {
  272. if(!(c = topofstack()))
  273. return;
  274. swap(c, sel);
  275. c = sel;
  276. }
  277. else
  278. pop(c);
  279. focus(c);
  280. arrange();
  281. }