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.

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