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.

377 lines
6.3 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
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(void) {
  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(void) {
  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. XEvent ev;
  42. if((c->ismax = !c->ismax)) {
  43. c->rx = c->x; c->x = sx;
  44. c->ry = c->y; c->y = bh;
  45. c->rw = c->w; c->w = sw - 2 * BORDERPX;
  46. c->rh = c->h; c->h = sh - bh - 2 * BORDERPX;
  47. }
  48. else {
  49. c->x = c->rx;
  50. c->y = c->ry;
  51. c->w = c->rw;
  52. c->h = c->rh;
  53. }
  54. resize(c, True, TopLeft);
  55. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  56. }
  57. /* extern */
  58. void (*arrange)(Arg *) = DEFMODE;
  59. StackPos stackpos = STACKPOS;
  60. void
  61. detach(Client *c) {
  62. if(c->prev)
  63. c->prev->next = c->next;
  64. if(c->next)
  65. c->next->prev = c->prev;
  66. if(c == clients)
  67. clients = c->next;
  68. c->next = c->prev = NULL;
  69. }
  70. void
  71. dofloat(Arg *arg) {
  72. Client *c;
  73. for(c = clients; c; c = c->next) {
  74. if(isvisible(c)) {
  75. resize(c, True, TopLeft);
  76. }
  77. else
  78. ban(c);
  79. }
  80. if(!sel || !isvisible(sel)) {
  81. for(c = stack; c && !isvisible(c); c = c->snext);
  82. focus(c);
  83. }
  84. restack();
  85. }
  86. /* This algorithm is based on a (M)aster area and a (S)tacking area.
  87. * It supports following arrangements:
  88. * SSMMM MMMMM MMMSS
  89. * SSMMM SSSSS MMMSS
  90. */
  91. void
  92. dotile(Arg *arg) {
  93. unsigned int i, n, md, stackw, stackh, tw, th;
  94. Client *c;
  95. for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
  96. n++;
  97. if(stackpos == StackBottom) {
  98. md = ((sh - bh) * master) / 1000;
  99. stackw = sw;
  100. stackh = sh - bh - md;
  101. }
  102. else {
  103. md = (sw * master) / 1000;
  104. stackw = sw - md;
  105. stackh = sh - bh;
  106. }
  107. tw = stackw;
  108. if(n > 1)
  109. th = stackh / (n - 1);
  110. else
  111. th = stackh;
  112. for(i = 0, c = clients; c; c = c->next) {
  113. if(isvisible(c)) {
  114. if(c->isfloat) {
  115. resize(c, True, TopLeft);
  116. continue;
  117. }
  118. c->ismax = False;
  119. c->x = sx;
  120. c->y = sy + bh;
  121. if(n == 1) { /* only 1 window */
  122. c->w = sw - 2 * BORDERPX;
  123. c->h = sh - 2 * BORDERPX - bh;
  124. }
  125. else if(i == 0) { /* master window */
  126. if(stackpos == StackLeft)
  127. c->x += stackw;
  128. switch(stackpos) {
  129. case StackLeft:
  130. case StackRight:
  131. c->w = md - 2 * BORDERPX;
  132. c->h = sh - bh - 2 * BORDERPX;
  133. break;
  134. case StackBottom:
  135. c->w = sw - 2 * BORDERPX;
  136. c->h = md - 2 * BORDERPX;
  137. break;
  138. }
  139. }
  140. else { /* tile window */
  141. if(stackpos == StackRight)
  142. c->x += md;
  143. if(th > bh) {
  144. switch(stackpos) {
  145. case StackLeft:
  146. case StackRight:
  147. c->y = sy + (i - 1) * th + bh;
  148. if(i + 1 == n)
  149. c->h = sh - c->y - 2 * BORDERPX;
  150. break;
  151. case StackBottom:
  152. c->y = sy + md + (i - 1) * th + bh;
  153. if(i + 1 == n)
  154. c->h = sh - c->y - 2 * BORDERPX;
  155. break;
  156. }
  157. c->w = tw - 2 * BORDERPX;
  158. c->h = th - 2 * BORDERPX;
  159. }
  160. else { /* fallback if th < bh */
  161. if(stackpos == StackBottom)
  162. c->y += md;
  163. c->w = stackw - 2 * BORDERPX;
  164. c->h = stackh - 2 * BORDERPX;
  165. }
  166. }
  167. resize(c, False, TopLeft);
  168. i++;
  169. }
  170. else
  171. ban(c);
  172. }
  173. if(!sel || !isvisible(sel)) {
  174. for(c = stack; c && !isvisible(c); c = c->snext);
  175. focus(c);
  176. }
  177. restack();
  178. }
  179. void
  180. focusnext(Arg *arg) {
  181. Client *c;
  182. if(!sel)
  183. return;
  184. if(!(c = getnext(sel->next)))
  185. c = getnext(clients);
  186. if(c) {
  187. focus(c);
  188. restack();
  189. }
  190. }
  191. void
  192. focusprev(Arg *arg) {
  193. Client *c;
  194. if(!sel)
  195. return;
  196. if(!(c = getprev(sel->prev))) {
  197. for(c = clients; c && c->next; c = c->next);
  198. c = getprev(c);
  199. }
  200. if(c) {
  201. focus(c);
  202. restack();
  203. }
  204. }
  205. Bool
  206. isvisible(Client *c) {
  207. unsigned int i;
  208. for(i = 0; i < ntags; i++)
  209. if(c->tags[i] && seltag[i])
  210. return True;
  211. return False;
  212. }
  213. void
  214. resizecol(Arg *arg) {
  215. unsigned int n;
  216. Client *c;
  217. for(n = 0, c = clients; c; c = c->next)
  218. if(isvisible(c) && !c->isfloat)
  219. n++;
  220. if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
  221. return;
  222. if(sel == getnext(clients)) {
  223. if(master + arg->i > 95 || master + arg->i < 5)
  224. return;
  225. master += arg->i;
  226. }
  227. else {
  228. if(master - arg->i > 95 || master - arg->i < 5)
  229. return;
  230. master -= arg->i;
  231. }
  232. arrange(NULL);
  233. }
  234. void
  235. restack(void) {
  236. Client *c;
  237. XEvent ev;
  238. if(!sel) {
  239. drawstatus();
  240. return;
  241. }
  242. if(sel->isfloat || arrange == dofloat) {
  243. XRaiseWindow(dpy, sel->win);
  244. XRaiseWindow(dpy, sel->twin);
  245. }
  246. if(arrange != dofloat) {
  247. if(!sel->isfloat) {
  248. XLowerWindow(dpy, sel->twin);
  249. XLowerWindow(dpy, sel->win);
  250. }
  251. for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
  252. if(c == sel)
  253. continue;
  254. XLowerWindow(dpy, c->twin);
  255. XLowerWindow(dpy, c->win);
  256. }
  257. }
  258. drawall();
  259. XSync(dpy, False);
  260. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  261. }
  262. void
  263. togglemode(Arg *arg) {
  264. arrange = (arrange == dofloat) ? dotile : dofloat;
  265. if(sel)
  266. arrange(NULL);
  267. else
  268. drawstatus();
  269. }
  270. void
  271. toggleview(Arg *arg) {
  272. unsigned int i;
  273. seltag[arg->i] = !seltag[arg->i];
  274. for(i = 0; i < ntags && !seltag[i]; i++);
  275. if(i == ntags)
  276. seltag[arg->i] = True; /* cannot toggle last view */
  277. reorder();
  278. arrange(NULL);
  279. }
  280. void
  281. togglestackpos(Arg *arg) {
  282. if(arrange == dofloat)
  283. return;
  284. if(stackpos == StackBottom)
  285. stackpos = STACKPOS;
  286. else
  287. stackpos = StackBottom;
  288. arrange(NULL);
  289. }
  290. void
  291. view(Arg *arg) {
  292. unsigned int i;
  293. for(i = 0; i < ntags; i++)
  294. seltag[i] = False;
  295. seltag[arg->i] = True;
  296. reorder();
  297. arrange(NULL);
  298. }
  299. void
  300. viewall(Arg *arg) {
  301. unsigned int i;
  302. for(i = 0; i < ntags; i++)
  303. seltag[i] = True;
  304. reorder();
  305. arrange(NULL);
  306. }
  307. void
  308. zoom(Arg *arg) {
  309. unsigned int n;
  310. Client *c;
  311. if(!sel)
  312. return;
  313. if(sel->isfloat || (arrange == dofloat)) {
  314. togglemax(sel);
  315. return;
  316. }
  317. for(n = 0, c = clients; c; c = c->next)
  318. if(isvisible(c) && !c->isfloat)
  319. n++;
  320. if(n < 2 || (arrange == dofloat))
  321. return;
  322. if((c = sel) == nexttiled(clients))
  323. if(!(c = nexttiled(c->next)))
  324. return;
  325. detach(c);
  326. if(clients)
  327. clients->prev = c;
  328. c->next = clients;
  329. clients = c;
  330. focus(c);
  331. arrange(NULL);
  332. }