Configuration of dwm for Mac Computers
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.

344 lines
6.4 KiB

  1. /* (C)opyright MMVI-MMVII Anselm R. Garbe <garbeam at gmail dot com>
  2. * See LICENSE file for license details.
  3. */
  4. #include "dwm.h"
  5. #include <regex.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <X11/Xutil.h>
  11. void (*arrange)(void) = DEFMODE;
  12. unsigned int master = MASTER;
  13. unsigned int nmaster = NMASTER;
  14. /* static */
  15. typedef struct {
  16. const char *prop;
  17. const char *tags;
  18. Bool isfloat;
  19. } Rule;
  20. typedef struct {
  21. regex_t *propregex;
  22. regex_t *tagregex;
  23. } Regexps;
  24. TAGS
  25. RULES
  26. static Regexps *regexps = NULL;
  27. static unsigned int len = 0;
  28. static Client *
  29. nextmanaged(Client *c) {
  30. for(; c && (c->isfloat || !isvisible(c)); c = c->next);
  31. return c;
  32. }
  33. static void
  34. togglemax(Client *c) {
  35. XEvent ev;
  36. if(c->isfixed)
  37. return;
  38. if((c->ismax = !c->ismax)) {
  39. c->rx = c->x;
  40. c->ry = c->y;
  41. c->rw = c->w;
  42. c->rh = c->h;
  43. resize(c, wax, way, waw - 2 * BORDERPX, wah - 2 * BORDERPX, True);
  44. }
  45. else
  46. resize(c, c->rx, c->ry, c->rw, c->rh, True);
  47. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  48. }
  49. /* extern */
  50. void
  51. compileregexps(void) {
  52. unsigned int i;
  53. regex_t *reg;
  54. if(regexps)
  55. return;
  56. len = sizeof rule / sizeof rule[0];
  57. regexps = emallocz(len * sizeof(Regexps));
  58. for(i = 0; i < len; i++) {
  59. if(rule[i].prop) {
  60. reg = emallocz(sizeof(regex_t));
  61. if(regcomp(reg, rule[i].prop, REG_EXTENDED))
  62. free(reg);
  63. else
  64. regexps[i].propregex = reg;
  65. }
  66. if(rule[i].tags) {
  67. reg = emallocz(sizeof(regex_t));
  68. if(regcomp(reg, rule[i].tags, REG_EXTENDED))
  69. free(reg);
  70. else
  71. regexps[i].tagregex = reg;
  72. }
  73. }
  74. }
  75. void
  76. dofloat(void) {
  77. Client *c;
  78. for(c = clients; c; c = c->next) {
  79. if(isvisible(c)) {
  80. if(c->isbanned)
  81. XMoveWindow(dpy, c->win, c->x, c->y);
  82. c->isbanned = False;
  83. resize(c, c->x, c->y, c->w, c->h, True);
  84. }
  85. else {
  86. c->isbanned = True;
  87. XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  88. }
  89. }
  90. if(!sel || !isvisible(sel)) {
  91. for(c = stack; c && !isvisible(c); c = c->snext);
  92. focus(c);
  93. }
  94. restack();
  95. }
  96. void
  97. dotile(void) {
  98. unsigned int i, n, nx, ny, nw, nh, mw, mh, tw, th;
  99. Client *c;
  100. for(n = 0, c = nextmanaged(clients); c; c = nextmanaged(c->next))
  101. n++;
  102. /* window geoms */
  103. mh = (n > nmaster) ? wah / nmaster : wah / (n > 0 ? n : 1);
  104. mw = (n > nmaster) ? (waw * master) / 1000 : waw;
  105. th = (n > nmaster) ? wah / (n - nmaster) : 0;
  106. tw = waw - mw;
  107. for(i = 0, c = clients; c; c = c->next)
  108. if(isvisible(c)) {
  109. if(c->isbanned)
  110. XMoveWindow(dpy, c->win, c->x, c->y);
  111. c->isbanned = False;
  112. if(c->isfloat)
  113. continue;
  114. c->ismax = False;
  115. nx = wax;
  116. ny = way;
  117. if(i < nmaster) {
  118. ny += i * mh;
  119. nw = mw - 2 * BORDERPX;
  120. nh = mh - 2 * BORDERPX;
  121. }
  122. else { /* tile window */
  123. nx += mw;
  124. nw = tw - 2 * BORDERPX;
  125. if(th > 2 * BORDERPX) {
  126. ny += (i - nmaster) * th;
  127. nh = th - 2 * BORDERPX;
  128. }
  129. else /* fallback if th <= 2 * BORDERPX */
  130. nh = wah - 2 * BORDERPX;
  131. }
  132. resize(c, nx, ny, nw, nh, False);
  133. i++;
  134. }
  135. else {
  136. c->isbanned = True;
  137. XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  138. }
  139. if(!sel || !isvisible(sel)) {
  140. for(c = stack; c && !isvisible(c); c = c->snext);
  141. focus(c);
  142. }
  143. restack();
  144. }
  145. void
  146. incnmaster(Arg *arg) {
  147. if((arrange == dofloat) || (nmaster + arg->i < 1)
  148. || (wah / (nmaster + arg->i) <= 2 * BORDERPX))
  149. return;
  150. nmaster += arg->i;
  151. if(sel)
  152. arrange();
  153. else
  154. drawstatus();
  155. }
  156. Bool
  157. isvisible(Client *c) {
  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. resizemaster(Arg *arg) {
  166. if(arrange != dotile)
  167. return;
  168. if(arg->i == 0)
  169. master = MASTER;
  170. else {
  171. if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
  172. || waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
  173. return;
  174. master += arg->i;
  175. }
  176. arrange();
  177. }
  178. void
  179. restack(void) {
  180. Client *c;
  181. XEvent ev;
  182. drawstatus();
  183. if(!sel)
  184. return;
  185. if(sel->isfloat || arrange == dofloat)
  186. XRaiseWindow(dpy, sel->win);
  187. if(arrange != dofloat) {
  188. if(!sel->isfloat)
  189. XLowerWindow(dpy, sel->win);
  190. for(c = nextmanaged(clients); c; c = nextmanaged(c->next)) {
  191. if(c == sel)
  192. continue;
  193. XLowerWindow(dpy, c->win);
  194. }
  195. }
  196. XSync(dpy, False);
  197. while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
  198. }
  199. void
  200. settags(Client *c, Client *trans) {
  201. char prop[512];
  202. unsigned int i, j;
  203. regmatch_t tmp;
  204. Bool matched = trans != NULL;
  205. XClassHint ch = { 0 };
  206. if(matched)
  207. for(i = 0; i < ntags; i++)
  208. c->tags[i] = trans->tags[i];
  209. else {
  210. XGetClassHint(dpy, c->win, &ch);
  211. snprintf(prop, sizeof prop, "%s:%s:%s",
  212. ch.res_class ? ch.res_class : "",
  213. ch.res_name ? ch.res_name : "", c->name);
  214. for(i = 0; i < len; i++)
  215. if(regexps[i].propregex && !regexec(regexps[i].propregex, prop, 1, &tmp, 0)) {
  216. c->isfloat = rule[i].isfloat;
  217. for(j = 0; regexps[i].tagregex && j < ntags; j++) {
  218. if(!regexec(regexps[i].tagregex, tags[j], 1, &tmp, 0)) {
  219. matched = True;
  220. c->tags[j] = True;
  221. }
  222. }
  223. }
  224. if(ch.res_class)
  225. XFree(ch.res_class);
  226. if(ch.res_name)
  227. XFree(ch.res_name);
  228. }
  229. if(!matched)
  230. for(i = 0; i < ntags; i++)
  231. c->tags[i] = seltag[i];
  232. }
  233. void
  234. tag(Arg *arg) {
  235. unsigned int i;
  236. if(!sel)
  237. return;
  238. for(i = 0; i < ntags; i++)
  239. sel->tags[i] = (arg->i == -1) ? True : False;
  240. if(arg->i >= 0 && arg->i < ntags)
  241. sel->tags[arg->i] = True;
  242. arrange();
  243. }
  244. void
  245. togglefloat(Arg *arg) {
  246. if(!sel || arrange == dofloat)
  247. return;
  248. sel->isfloat = !sel->isfloat;
  249. arrange();
  250. }
  251. void
  252. toggletag(Arg *arg) {
  253. unsigned int i;
  254. if(!sel)
  255. return;
  256. sel->tags[arg->i] = !sel->tags[arg->i];
  257. for(i = 0; i < ntags && !sel->tags[i]; i++);
  258. if(i == ntags)
  259. sel->tags[arg->i] = True;
  260. arrange();
  261. }
  262. void
  263. togglemode(Arg *arg) {
  264. arrange = (arrange == dofloat) ? dotile : dofloat;
  265. if(sel)
  266. arrange();
  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. arrange();
  278. }
  279. void
  280. view(Arg *arg) {
  281. unsigned int i;
  282. for(i = 0; i < ntags; i++)
  283. seltag[i] = (arg->i == -1) ? True : False;
  284. if(arg->i >= 0 && arg->i < ntags)
  285. seltag[arg->i] = True;
  286. arrange();
  287. }
  288. void
  289. zoom(Arg *arg) {
  290. unsigned int n;
  291. Client *c;
  292. if(!sel)
  293. return;
  294. if(sel->isfloat || (arrange == dofloat)) {
  295. togglemax(sel);
  296. return;
  297. }
  298. for(n = 0, c = nextmanaged(clients); c; c = nextmanaged(c->next))
  299. n++;
  300. if((c = sel) == nextmanaged(clients))
  301. if(!(c = nextmanaged(c->next)))
  302. return;
  303. detach(c);
  304. attach(c);
  305. focus(c);
  306. arrange();
  307. }