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.

315 lines
5.2 KiB

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