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.0 KiB

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. #include <regex.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <X11/Xutil.h>
  12. typedef struct {
  13. const char *clpattern;
  14. const char *tpattern;
  15. Bool isfloat;
  16. } Rule;
  17. typedef struct {
  18. regex_t *clregex;
  19. regex_t *tregex;
  20. } RReg;
  21. /* static */
  22. TAGS
  23. RULES
  24. static RReg *rreg = NULL;
  25. static unsigned int len = 0;
  26. void (*arrange)(Arg *) = DEFMODE;
  27. /* extern */
  28. void
  29. appendtag(Arg *arg)
  30. {
  31. Client *c = sel;
  32. if(!c)
  33. return;
  34. c->tags[arg->i] = True;
  35. arrange(NULL);
  36. focus(c);
  37. restack();
  38. }
  39. void
  40. dofloat(Arg *arg)
  41. {
  42. Client *c;
  43. for(c = clients; c; c = c->next) {
  44. c->ismax = False;
  45. if(isvisible(c)) {
  46. resize(c, True, TopLeft);
  47. }
  48. else
  49. ban(c);
  50. }
  51. if((sel = getnext(clients))) {
  52. focus(sel);
  53. restack();
  54. }
  55. else
  56. XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
  57. }
  58. void
  59. dotile(Arg *arg)
  60. {
  61. int h, i, n, w;
  62. Client *c;
  63. w = sw - mw;
  64. for(n = 0, c = clients; c; c = c->next)
  65. if(isvisible(c) && !c->isfloat)
  66. n++;
  67. if(n > 1)
  68. h = (sh - bh) / (n - 1);
  69. else
  70. h = sh - bh;
  71. for(i = 0, c = clients; c; c = c->next) {
  72. c->ismax = False;
  73. if(isvisible(c)) {
  74. if(c->isfloat) {
  75. resize(c, True, TopLeft);
  76. continue;
  77. }
  78. if(n == 1) {
  79. c->x = sx;
  80. c->y = sy + bh;
  81. c->w = sw - 2;
  82. c->h = sh - 2 - bh;
  83. }
  84. else if(i == 0) {
  85. c->x = sx;
  86. c->y = sy + bh;
  87. c->w = mw - 2;
  88. c->h = sh - 2 - bh;
  89. }
  90. else if(h > bh) {
  91. c->x = sx + mw;
  92. c->y = sy + (i - 1) * h + bh;
  93. c->w = w - 2;
  94. if(i + 1 == n)
  95. c->h = sh - c->y - 2;
  96. else
  97. c->h = h - 2;
  98. }
  99. else { /* fallback if h < bh */
  100. c->x = sx + mw;
  101. c->y = sy + bh;
  102. c->w = w - 2;
  103. c->h = sh - 2 - bh;
  104. }
  105. resize(c, False, TopLeft);
  106. i++;
  107. }
  108. else
  109. ban(c);
  110. }
  111. if((sel = getnext(clients)))
  112. focus(sel);
  113. else
  114. XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
  115. restack();
  116. }
  117. Client *
  118. getnext(Client *c)
  119. {
  120. for(; c && !isvisible(c); c = c->next);
  121. return c;
  122. }
  123. Client *
  124. getprev(Client *c)
  125. {
  126. for(; c && !isvisible(c); c = c->prev);
  127. return c;
  128. }
  129. void
  130. initrregs()
  131. {
  132. unsigned int i;
  133. regex_t *reg;
  134. if(rreg)
  135. return;
  136. len = sizeof(rule) / sizeof(rule[0]);
  137. rreg = emallocz(len * sizeof(RReg));
  138. for(i = 0; i < len; i++) {
  139. if(rule[i].clpattern) {
  140. reg = emallocz(sizeof(regex_t));
  141. if(regcomp(reg, rule[i].clpattern, 0))
  142. free(reg);
  143. else
  144. rreg[i].clregex = reg;
  145. }
  146. if(rule[i].tpattern) {
  147. reg = emallocz(sizeof(regex_t));
  148. if(regcomp(reg, rule[i].tpattern, 0))
  149. free(reg);
  150. else
  151. rreg[i].tregex = reg;
  152. }
  153. }
  154. }
  155. Bool
  156. isvisible(Client *c)
  157. {
  158. unsigned int i;
  159. for(i = 0; i < ntags; i++)
  160. if(c->tags[i] && seltag[i])
  161. return True;
  162. return False;
  163. }
  164. void
  165. replacetag(Arg *arg)
  166. {
  167. int i;
  168. if(!sel)
  169. return;
  170. for(i = 0; i < ntags; i++)
  171. sel->tags[i] = False;
  172. appendtag(arg);
  173. }
  174. void
  175. restack()
  176. {
  177. static unsigned int nwins = 0;
  178. static Window *wins = NULL;
  179. unsigned int f, fi, m, mi, n;
  180. Client *c;
  181. XEvent ev;
  182. for(f = 0, m = 0, c = clients; c; c = c->next)
  183. if(isvisible(c)) {
  184. if(c->isfloat || arrange == dofloat)
  185. f++;
  186. else
  187. m++;
  188. }
  189. if(!(n = 2 * (f + m))) {
  190. drawstatus();
  191. return;
  192. }
  193. if(nwins < n) {
  194. nwins = n;
  195. wins = erealloc(wins, nwins * sizeof(Window));
  196. }
  197. fi = 0;
  198. mi = 2 * f;
  199. if(sel->isfloat || arrange == dofloat) {
  200. wins[fi++] = sel->title;
  201. wins[fi++] = sel->win;
  202. }
  203. else {
  204. wins[mi++] = sel->title;
  205. wins[mi++] = sel->win;
  206. }
  207. for(c = clients; c; c = c->next)
  208. if(isvisible(c) && c != sel) {
  209. if(c->isfloat || arrange == dofloat) {
  210. wins[fi++] = c->title;
  211. wins[fi++] = c->win;
  212. }
  213. else {
  214. wins[mi++] = c->title;
  215. wins[mi++] = c->win;
  216. }
  217. }
  218. XRestackWindows(dpy, wins, n);
  219. drawall();
  220. XSync(dpy, False);
  221. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  222. }
  223. void
  224. settags(Client *c)
  225. {
  226. char classinst[256];
  227. unsigned int i, j;
  228. regmatch_t tmp;
  229. Bool matched = False;
  230. XClassHint ch;
  231. if(XGetClassHint(dpy, c->win, &ch)) {
  232. snprintf(classinst, sizeof(classinst), "%s:%s",
  233. ch.res_class ? ch.res_class : "",
  234. ch.res_name ? ch.res_name : "");
  235. for(i = 0; !matched && i < len; i++)
  236. if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
  237. c->isfloat = rule[i].isfloat;
  238. for(j = 0; rreg[i].tregex && j < ntags; j++) {
  239. if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
  240. matched = True;
  241. c->tags[j] = True;
  242. }
  243. }
  244. }
  245. if(ch.res_class)
  246. XFree(ch.res_class);
  247. if(ch.res_name)
  248. XFree(ch.res_name);
  249. }
  250. if(!matched)
  251. for(i = 0; i < ntags; i++)
  252. c->tags[i] = seltag[i];
  253. }
  254. void
  255. togglemode(Arg *arg)
  256. {
  257. arrange = arrange == dofloat ? dotile : dofloat;
  258. arrange(NULL);
  259. }
  260. void
  261. view(Arg *arg)
  262. {
  263. unsigned int i;
  264. for(i = 0; i < ntags; i++)
  265. seltag[i] = False;
  266. seltag[arg->i] = True;
  267. arrange(NULL);
  268. }
  269. void
  270. toggleview(Arg *arg)
  271. {
  272. unsigned int i;
  273. seltag[arg->i] = !seltag[arg->i];
  274. for(i = 0; !seltag[i] && i < ntags; i++);
  275. if(i == ntags)
  276. seltag[arg->i] = True; /* cannot toggle last view */
  277. arrange(NULL);
  278. }