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.

385 lines
6.5 KiB

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