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.

347 lines
8.3 KiB

17 years ago
18 years ago
17 years ago
17 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. /* (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 <stdlib.h>
  6. #include <string.h>
  7. #include <X11/Xatom.h>
  8. #include <X11/Xutil.h>
  9. /* static */
  10. static void
  11. closestpt(float *rx, float *ry, float x, float y, float grad) {
  12. float u = (x * grad + y) / (grad * grad + 1);
  13. *rx = u * grad;
  14. *ry = u;
  15. }
  16. static void
  17. detachstack(Client *c) {
  18. Client **tc;
  19. for(tc=&stack; *tc && *tc != c; tc=&(*tc)->snext);
  20. *tc = c->snext;
  21. }
  22. static void
  23. grabbuttons(Client *c, Bool focused) {
  24. XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
  25. if(focused) {
  26. XGrabButton(dpy, Button1, MODKEY, c->win, False, BUTTONMASK,
  27. GrabModeAsync, GrabModeSync, None, None);
  28. XGrabButton(dpy, Button1, MODKEY | LockMask, c->win, False, BUTTONMASK,
  29. GrabModeAsync, GrabModeSync, None, None);
  30. XGrabButton(dpy, Button1, MODKEY | numlockmask, c->win, False, BUTTONMASK,
  31. GrabModeAsync, GrabModeSync, None, None);
  32. XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
  33. GrabModeAsync, GrabModeSync, None, None);
  34. XGrabButton(dpy, Button2, MODKEY, c->win, False, BUTTONMASK,
  35. GrabModeAsync, GrabModeSync, None, None);
  36. XGrabButton(dpy, Button2, MODKEY | LockMask, c->win, False, BUTTONMASK,
  37. GrabModeAsync, GrabModeSync, None, None);
  38. XGrabButton(dpy, Button2, MODKEY | numlockmask, c->win, False, BUTTONMASK,
  39. GrabModeAsync, GrabModeSync, None, None);
  40. XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
  41. GrabModeAsync, GrabModeSync, None, None);
  42. XGrabButton(dpy, Button3, MODKEY, c->win, False, BUTTONMASK,
  43. GrabModeAsync, GrabModeSync, None, None);
  44. XGrabButton(dpy, Button3, MODKEY | LockMask, c->win, False, BUTTONMASK,
  45. GrabModeAsync, GrabModeSync, None, None);
  46. XGrabButton(dpy, Button3, MODKEY | numlockmask, c->win, False, BUTTONMASK,
  47. GrabModeAsync, GrabModeSync, None, None);
  48. XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c->win, False, BUTTONMASK,
  49. GrabModeAsync, GrabModeSync, None, None);
  50. }
  51. else
  52. XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, BUTTONMASK,
  53. GrabModeAsync, GrabModeSync, None, None);
  54. }
  55. static void
  56. setclientstate(Client *c, long state) {
  57. long data[] = {state, None};
  58. XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
  59. PropModeReplace, (unsigned char *)data, 2);
  60. }
  61. static int
  62. xerrordummy(Display *dsply, XErrorEvent *ee) {
  63. return 0;
  64. }
  65. /* extern */
  66. void
  67. configure(Client *c) {
  68. XEvent synev;
  69. synev.type = ConfigureNotify;
  70. synev.xconfigure.display = dpy;
  71. synev.xconfigure.event = c->win;
  72. synev.xconfigure.window = c->win;
  73. synev.xconfigure.x = c->x;
  74. synev.xconfigure.y = c->y;
  75. synev.xconfigure.width = c->w;
  76. synev.xconfigure.height = c->h;
  77. synev.xconfigure.border_width = c->border;
  78. synev.xconfigure.above = None;
  79. XSendEvent(dpy, c->win, True, NoEventMask, &synev);
  80. }
  81. void
  82. focus(Client *c) {
  83. if(c && !isvisible(c))
  84. return;
  85. if(sel && sel != c) {
  86. grabbuttons(sel, False);
  87. XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
  88. }
  89. if(c) {
  90. detachstack(c);
  91. c->snext = stack;
  92. stack = c;
  93. grabbuttons(c, True);
  94. }
  95. sel = c;
  96. drawstatus();
  97. if(!selscreen)
  98. return;
  99. if(c) {
  100. XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
  101. XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
  102. }
  103. else
  104. XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
  105. }
  106. Client *
  107. getclient(Window w) {
  108. Client *c;
  109. for(c = clients; c; c = c->next)
  110. if(c->win == w)
  111. return c;
  112. return NULL;
  113. }
  114. void
  115. killclient(Arg *arg) {
  116. if(!sel)
  117. return;
  118. if(sel->proto & PROTODELWIN)
  119. sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
  120. else
  121. XKillClient(dpy, sel->win);
  122. }
  123. void
  124. manage(Window w, XWindowAttributes *wa) {
  125. Client *c;
  126. Window trans;
  127. c = emallocz(sizeof(Client));
  128. c->tags = emallocz(ntags * sizeof(Bool));
  129. c->win = w;
  130. c->x = wa->x;
  131. c->y = wa->y;
  132. c->w = wa->width;
  133. c->h = wa->height;
  134. if(c->w == sw && c->h == sh) {
  135. c->border = 0;
  136. c->x = sx;
  137. c->y = sy;
  138. }
  139. else {
  140. c->border = BORDERPX;
  141. if(c->x + c->w + 2 * c->border > wax + waw)
  142. c->x = wax + waw - c->w - 2 * c->border;
  143. if(c->y + c->h + 2 * c->border > way + wah)
  144. c->y = way + wah - c->h - 2 * c->border;
  145. if(c->x < wax)
  146. c->x = wax;
  147. if(c->y < way)
  148. c->y = way;
  149. }
  150. updatesizehints(c);
  151. c->proto = getproto(c->win);
  152. XSelectInput(dpy, c->win,
  153. StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
  154. XGetTransientForHint(dpy, c->win, &trans);
  155. grabbuttons(c, False);
  156. XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
  157. updatetitle(c);
  158. settags(c, getclient(trans));
  159. if(!c->isfloat)
  160. c->isfloat = trans || c->isfixed;
  161. if(clients)
  162. clients->prev = c;
  163. c->next = clients;
  164. c->snext = stack;
  165. stack = clients = c;
  166. XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
  167. XMapWindow(dpy, c->win);
  168. setclientstate(c, NormalState);
  169. if(isvisible(c))
  170. focus(c);
  171. arrange();
  172. }
  173. void
  174. resize(Client *c, Bool sizehints) {
  175. float dx, dy, min, max, actual;
  176. XWindowChanges wc;
  177. if(c->w <= 0 || c->h <= 0)
  178. return;
  179. if(sizehints) {
  180. if(c->minw && c->w < c->minw)
  181. c->w = c->minw;
  182. if(c->minh && c->h < c->minh)
  183. c->h = c->minh;
  184. if(c->maxw && c->w > c->maxw)
  185. c->w = c->maxw;
  186. if(c->maxh && c->h > c->maxh)
  187. c->h = c->maxh;
  188. /* inspired by algorithm from fluxbox */
  189. if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) {
  190. dx = (float)(c->w - c->basew);
  191. dy = (float)(c->h - c->baseh);
  192. min = (float)(c->minax) / (float)(c->minay);
  193. max = (float)(c->maxax) / (float)(c->maxay);
  194. actual = dx / dy;
  195. if(max > 0 && min > 0 && actual > 0) {
  196. if(actual < min) {
  197. closestpt(&dx, &dy, dx, dy, min);
  198. c->w = (int)dx + c->basew;
  199. c->h = (int)dy + c->baseh;
  200. }
  201. else if(actual > max) {
  202. closestpt(&dx, &dy, dx, dy, max);
  203. c->w = (int)dx + c->basew;
  204. c->h = (int)dy + c->baseh;
  205. }
  206. }
  207. }
  208. if(c->incw)
  209. c->w -= (c->w - c->basew) % c->incw;
  210. if(c->inch)
  211. c->h -= (c->h - c->baseh) % c->inch;
  212. }
  213. if(c->w == sw && c->h == sh)
  214. c->border = 0;
  215. else
  216. c->border = BORDERPX;
  217. /* offscreen appearance fixes */
  218. if(c->x > sw)
  219. c->x = sw - c->w - 2 * c->border;
  220. if(c->y > sh)
  221. c->y = sh - c->h - 2 * c->border;
  222. if(c->x + c->w + 2 * c->border < sx)
  223. c->x = sx;
  224. if(c->y + c->h + 2 * c->border < sy)
  225. c->y = sy;
  226. wc.x = c->x;
  227. wc.y = c->y;
  228. wc.width = c->w;
  229. wc.height = c->h;
  230. wc.border_width = c->border;
  231. XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
  232. configure(c);
  233. XSync(dpy, False);
  234. }
  235. void
  236. updatesizehints(Client *c) {
  237. long msize;
  238. XSizeHints size;
  239. if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
  240. size.flags = PSize;
  241. c->flags = size.flags;
  242. if(c->flags & PBaseSize) {
  243. c->basew = size.base_width;
  244. c->baseh = size.base_height;
  245. }
  246. else
  247. c->basew = c->baseh = 0;
  248. if(c->flags & PResizeInc) {
  249. c->incw = size.width_inc;
  250. c->inch = size.height_inc;
  251. }
  252. else
  253. c->incw = c->inch = 0;
  254. if(c->flags & PMaxSize) {
  255. c->maxw = size.max_width;
  256. c->maxh = size.max_height;
  257. }
  258. else
  259. c->maxw = c->maxh = 0;
  260. if(c->flags & PMinSize) {
  261. c->minw = size.min_width;
  262. c->minh = size.min_height;
  263. }
  264. else
  265. c->minw = c->minh = 0;
  266. if(c->flags & PAspect) {
  267. c->minax = size.min_aspect.x;
  268. c->minay = size.min_aspect.y;
  269. c->maxax = size.max_aspect.x;
  270. c->maxay = size.max_aspect.y;
  271. }
  272. else
  273. c->minax = c->minay = c->maxax = c->maxay = 0;
  274. c->isfixed = (c->maxw && c->minw && c->maxh && c->minh &&
  275. c->maxw == c->minw && c->maxh == c->minh);
  276. }
  277. void
  278. updatetitle(Client *c) {
  279. char **list = NULL;
  280. int n;
  281. XTextProperty name;
  282. name.nitems = 0;
  283. c->name[0] = 0;
  284. XGetTextProperty(dpy, c->win, &name, netatom[NetWMName]);
  285. if(!name.nitems)
  286. XGetWMName(dpy, c->win, &name);
  287. if(!name.nitems)
  288. return;
  289. if(name.encoding == XA_STRING)
  290. strncpy(c->name, (char *)name.value, sizeof c->name);
  291. else {
  292. if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
  293. && n > 0 && *list)
  294. {
  295. strncpy(c->name, *list, sizeof c->name);
  296. XFreeStringList(list);
  297. }
  298. }
  299. XFree(name.value);
  300. }
  301. void
  302. unmanage(Client *c) {
  303. Client *nc;
  304. /* The server grab construct avoids race conditions. */
  305. XGrabServer(dpy);
  306. XSetErrorHandler(xerrordummy);
  307. detach(c);
  308. detachstack(c);
  309. if(sel == c) {
  310. for(nc = stack; nc && !isvisible(nc); nc = nc->snext);
  311. focus(nc);
  312. }
  313. XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
  314. setclientstate(c, WithdrawnState);
  315. free(c->tags);
  316. free(c);
  317. XSync(dpy, False);
  318. XSetErrorHandler(xerror);
  319. XUngrabServer(dpy);
  320. arrange();
  321. }