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.

404 lines
6.8 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
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. int i, n, 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. stackw = sw;
  99. stackh = sh - bh - master;
  100. }
  101. else {
  102. stackw = sw - master;
  103. stackh = sh - bh;
  104. }
  105. tw = stackw;
  106. if(n > 1)
  107. th = stackh / (n - 1);
  108. else
  109. th = stackh;
  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. if(n == 1) { /* only 1 window */
  118. c->x = sx;
  119. c->y = sy + bh;
  120. c->w = sw - 2 * BORDERPX;
  121. c->h = sh - 2 * BORDERPX - bh;
  122. }
  123. else if(i == 0) { /* master window */
  124. switch(stackpos) {
  125. case StackLeft:
  126. c->x = sx + stackw;
  127. c->y = sy + bh;
  128. c->w = master - 2 * BORDERPX;
  129. c->h = sh - bh - 2 * BORDERPX;
  130. break;
  131. case StackBottom:
  132. c->x = sx;
  133. c->y = sy + bh;
  134. c->w = sw - 2 * BORDERPX;
  135. c->h = master - 2 * BORDERPX;
  136. break;
  137. case StackRight:
  138. c->x = sx;
  139. c->y = sy + bh;
  140. c->w = master - 2 * BORDERPX;
  141. c->h = sh - bh - 2 * BORDERPX;
  142. break;
  143. }
  144. }
  145. else if(th > bh) {
  146. /* tile window */
  147. c->w = tw - 2 * BORDERPX;
  148. c->h = th - 2 * BORDERPX;
  149. switch(stackpos) {
  150. case StackLeft:
  151. c->x = sx;
  152. c->y = sy + (i - 1) * th + bh;
  153. if(i + 1 == n)
  154. c->h = sh - c->y - 2 * BORDERPX;
  155. break;
  156. case StackBottom:
  157. c->x = sx;
  158. c->y = sy + master + (i - 1) * th + bh;
  159. if(i + 1 == n)
  160. c->h = sh - c->y - 2 * BORDERPX;
  161. break;
  162. case StackRight:
  163. c->x = sx + master;
  164. c->y = sy + (i - 1) * th + bh;
  165. if(i + 1 == n)
  166. c->h = sh - c->y - 2 * BORDERPX;
  167. break;
  168. }
  169. }
  170. else { /* fallback if th < bh */
  171. c->w = stackw - 2 * BORDERPX;
  172. c->h = stackh - 2 * BORDERPX;
  173. switch(stackpos) {
  174. case StackLeft:
  175. c->x = sx;
  176. c->y = sy + bh;
  177. break;
  178. case StackBottom:
  179. c->x = sx;
  180. c->y = sy + master + bh;
  181. break;
  182. case StackRight:
  183. c->x = sx + master;
  184. c->y = sy + bh;
  185. break;
  186. }
  187. }
  188. resize(c, False, TopLeft);
  189. i++;
  190. }
  191. else
  192. ban(c);
  193. }
  194. if(!sel || !isvisible(sel)) {
  195. for(c = stack; c && !isvisible(c); c = c->snext);
  196. focus(c);
  197. }
  198. restack();
  199. }
  200. void
  201. focusnext(Arg *arg) {
  202. Client *c;
  203. if(!sel)
  204. return;
  205. if(!(c = getnext(sel->next)))
  206. c = getnext(clients);
  207. if(c) {
  208. focus(c);
  209. restack();
  210. }
  211. }
  212. void
  213. focusprev(Arg *arg) {
  214. Client *c;
  215. if(!sel)
  216. return;
  217. if(!(c = getprev(sel->prev))) {
  218. for(c = clients; c && c->next; c = c->next);
  219. c = getprev(c);
  220. }
  221. if(c) {
  222. focus(c);
  223. restack();
  224. }
  225. }
  226. Bool
  227. isvisible(Client *c) {
  228. unsigned int i;
  229. for(i = 0; i < ntags; i++)
  230. if(c->tags[i] && seltag[i])
  231. return True;
  232. return False;
  233. }
  234. void
  235. resizecol(Arg *arg) {
  236. unsigned int n;
  237. Client *c;
  238. for(n = 0, c = clients; c; c = c->next)
  239. if(isvisible(c) && !c->isfloat)
  240. n++;
  241. if(!sel || sel->isfloat || n < 2 || (arrange == dofloat))
  242. return;
  243. if(sel == getnext(clients)) {
  244. if(master + arg->i > sw - MINW || master + arg->i < MINW)
  245. return;
  246. master += arg->i;
  247. }
  248. else {
  249. if(master - arg->i > sw - MINW || master - arg->i < MINW)
  250. return;
  251. master -= arg->i;
  252. }
  253. arrange(NULL);
  254. }
  255. void
  256. restack(void) {
  257. Client *c;
  258. XEvent ev;
  259. if(!sel) {
  260. drawstatus();
  261. return;
  262. }
  263. if(sel->isfloat || arrange == dofloat) {
  264. XRaiseWindow(dpy, sel->win);
  265. XRaiseWindow(dpy, sel->twin);
  266. }
  267. if(arrange != dofloat) {
  268. if(!sel->isfloat) {
  269. XLowerWindow(dpy, sel->twin);
  270. XLowerWindow(dpy, sel->win);
  271. }
  272. for(c = nexttiled(clients); c; c = nexttiled(c->next)) {
  273. if(c == sel)
  274. continue;
  275. XLowerWindow(dpy, c->twin);
  276. XLowerWindow(dpy, c->win);
  277. }
  278. }
  279. drawall();
  280. XSync(dpy, False);
  281. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  282. }
  283. void
  284. togglemode(Arg *arg) {
  285. arrange = (arrange == dofloat) ? dotile : dofloat;
  286. if(sel)
  287. arrange(NULL);
  288. else
  289. drawstatus();
  290. }
  291. void
  292. toggleview(Arg *arg) {
  293. unsigned int i;
  294. seltag[arg->i] = !seltag[arg->i];
  295. for(i = 0; i < ntags && !seltag[i]; i++);
  296. if(i == ntags)
  297. seltag[arg->i] = True; /* cannot toggle last view */
  298. reorder();
  299. arrange(NULL);
  300. }
  301. void
  302. togglestackpos(Arg *arg) {
  303. if(arrange == dofloat)
  304. return;
  305. if(stackpos == StackBottom)
  306. stackpos = STACKPOS;
  307. else
  308. stackpos = StackBottom;
  309. updatemaster();
  310. arrange(NULL);
  311. }
  312. void
  313. updatemaster(void) {
  314. master = ((stackpos == StackBottom ? sh - bh : sw) * MASTER) / 100;
  315. }
  316. void
  317. view(Arg *arg) {
  318. unsigned int i;
  319. for(i = 0; i < ntags; i++)
  320. seltag[i] = False;
  321. seltag[arg->i] = True;
  322. reorder();
  323. arrange(NULL);
  324. }
  325. void
  326. viewall(Arg *arg) {
  327. unsigned int i;
  328. for(i = 0; i < ntags; i++)
  329. seltag[i] = True;
  330. reorder();
  331. arrange(NULL);
  332. }
  333. void
  334. zoom(Arg *arg) {
  335. unsigned int n;
  336. Client *c;
  337. if(!sel)
  338. return;
  339. if(sel->isfloat || (arrange == dofloat)) {
  340. togglemax(sel);
  341. return;
  342. }
  343. for(n = 0, c = clients; c; c = c->next)
  344. if(isvisible(c) && !c->isfloat)
  345. n++;
  346. if(n < 2 || (arrange == dofloat))
  347. return;
  348. if((c = sel) == nexttiled(clients))
  349. if(!(c = nexttiled(c->next)))
  350. return;
  351. detach(c);
  352. if(clients)
  353. clients->prev = c;
  354. c->next = clients;
  355. clients = c;
  356. focus(c);
  357. arrange(NULL);
  358. }