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.

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