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.

325 lines
5.0 KiB

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