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.

309 lines
4.5 KiB

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