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.

258 lines
4.9 KiB

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 <stdlib.h>
  6. #include <string.h>
  7. #include <X11/Xatom.h>
  8. #include "util.h"
  9. #include "wm.h"
  10. static void
  11. resize_title(Client *c)
  12. {
  13. c->tw = textw(&brush.font, c->name) + bh;
  14. if(c->tw > c->w)
  15. c->tw = c->w + 2;
  16. c->tx = c->x + c->w - c->tw + 2;
  17. c->ty = c->y;
  18. XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
  19. }
  20. void
  21. update_name(Client *c)
  22. {
  23. XTextProperty name;
  24. int n;
  25. char **list = NULL;
  26. name.nitems = 0;
  27. c->name[0] = 0;
  28. XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
  29. if(!name.nitems)
  30. XGetWMName(dpy, c->win, &name);
  31. if(!name.nitems)
  32. return;
  33. if(name.encoding == XA_STRING)
  34. strncpy(c->name, (char *)name.value, sizeof(c->name));
  35. else {
  36. if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
  37. && n > 0 && *list)
  38. {
  39. strncpy(c->name, *list, sizeof(c->name));
  40. XFreeStringList(list);
  41. }
  42. }
  43. XFree(name.value);
  44. resize_title(c);
  45. }
  46. void
  47. update_size(Client *c)
  48. {
  49. XSizeHints size;
  50. long msize;
  51. if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
  52. size.flags = PSize;
  53. c->flags = size.flags;
  54. if(c->flags & PBaseSize) {
  55. c->basew = size.base_width;
  56. c->baseh = size.base_height;
  57. }
  58. else
  59. c->basew = c->baseh = 0;
  60. if(c->flags & PResizeInc) {
  61. c->incw = size.width_inc;
  62. c->inch = size.height_inc;
  63. }
  64. else
  65. c->incw = c->inch = 0;
  66. if(c->flags & PMaxSize) {
  67. c->maxw = size.max_width;
  68. c->maxh = size.max_height;
  69. }
  70. else
  71. c->maxw = c->maxh = 0;
  72. if(c->flags & PMinSize) {
  73. c->minw = size.min_width;
  74. c->minh = size.min_height;
  75. }
  76. else
  77. c->minw = c->minh = 0;
  78. }
  79. void
  80. raise(Client *c)
  81. {
  82. XRaiseWindow(dpy, c->win);
  83. XRaiseWindow(dpy, c->title);
  84. }
  85. void
  86. lower(Client *c)
  87. {
  88. XLowerWindow(dpy, c->title);
  89. XLowerWindow(dpy, c->win);
  90. }
  91. void
  92. focus(Client *c)
  93. {
  94. Client **l, *old;
  95. old = stack;
  96. for(l = &stack; *l && *l != c; l = &(*l)->snext);
  97. eassert(*l == c);
  98. *l = c->snext;
  99. c->snext = stack;
  100. stack = c;
  101. if(old && old != c) {
  102. XMapWindow(dpy, old->title);
  103. draw_client(old);
  104. }
  105. XUnmapWindow(dpy, c->title);
  106. draw_client(old);
  107. XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
  108. XFlush(dpy);
  109. }
  110. void
  111. manage(Window w, XWindowAttributes *wa)
  112. {
  113. Client *c, **l;
  114. XSetWindowAttributes twa;
  115. c = emallocz(sizeof(Client));
  116. c->win = w;
  117. c->tx = c->x = wa->x;
  118. c->ty = c->y = wa->y;
  119. if(c->y < bh)
  120. c->ty = c->y += bh;
  121. c->tw = c->w = wa->width;
  122. c->h = wa->height;
  123. c->th = bh;
  124. update_size(c);
  125. XSetWindowBorderWidth(dpy, c->win, 1);
  126. XSetWindowBorder(dpy, c->win, brush.border);
  127. XSelectInput(dpy, c->win,
  128. StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
  129. XGetTransientForHint(dpy, c->win, &c->trans);
  130. twa.override_redirect = 1;
  131. twa.background_pixmap = ParentRelative;
  132. twa.event_mask = ExposureMask;
  133. c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
  134. 0, DefaultDepth(dpy, screen), CopyFromParent,
  135. DefaultVisual(dpy, screen),
  136. CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
  137. update_name(c);
  138. for(l=&clients; *l; l=&(*l)->next);
  139. c->next = *l; /* *l == nil */
  140. *l = c;
  141. c->snext = stack;
  142. stack = c;
  143. XMapRaised(dpy, c->win);
  144. XMapRaised(dpy, c->title);
  145. XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
  146. GrabModeAsync, GrabModeSync, None, None);
  147. XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
  148. GrabModeAsync, GrabModeSync, None, None);
  149. XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
  150. GrabModeAsync, GrabModeSync, None, None);
  151. resize(c);
  152. focus(c);
  153. }
  154. void
  155. resize(Client *c)
  156. {
  157. XConfigureEvent e;
  158. resize_title(c);
  159. XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
  160. e.type = ConfigureNotify;
  161. e.event = c->win;
  162. e.window = c->win;
  163. e.x = c->x;
  164. e.y = c->y;
  165. e.width = c->w;
  166. e.height = c->h;
  167. e.border_width = 0;
  168. e.above = None;
  169. e.override_redirect = False;
  170. XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
  171. XFlush(dpy);
  172. }
  173. static int
  174. dummy_error_handler(Display *dpy, XErrorEvent *error)
  175. {
  176. return 0;
  177. }
  178. void
  179. unmanage(Client *c)
  180. {
  181. Client **l;
  182. XGrabServer(dpy);
  183. XSetErrorHandler(dummy_error_handler);
  184. XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
  185. XDestroyWindow(dpy, c->title);
  186. for(l=&clients; *l && *l != c; l=&(*l)->next);
  187. eassert(*l == c);
  188. *l = c->next;
  189. for(l=&stack; *l && *l != c; l=&(*l)->snext);
  190. eassert(*l == c);
  191. *l = c->snext;
  192. free(c);
  193. XFlush(dpy);
  194. XSetErrorHandler(error_handler);
  195. XUngrabServer(dpy);
  196. if(stack)
  197. focus(stack);
  198. }
  199. Client *
  200. gettitle(Window w)
  201. {
  202. Client *c;
  203. for(c = clients; c; c = c->next)
  204. if(c->title == w)
  205. return c;
  206. return NULL;
  207. }
  208. Client *
  209. getclient(Window w)
  210. {
  211. Client *c;
  212. for(c = clients; c; c = c->next)
  213. if(c->win == w)
  214. return c;
  215. return NULL;
  216. }
  217. void
  218. draw_client(Client *c)
  219. {
  220. if(c == stack) {
  221. draw_bar();
  222. return;
  223. }
  224. brush.x = brush.y = 0;
  225. brush.w = c->tw;
  226. brush.h = c->th;
  227. draw(dpy, &brush, True, c->name);
  228. XCopyArea(dpy, brush.drawable, c->title, brush.gc,
  229. 0, 0, c->tw, c->th, 0, 0);
  230. XFlush(dpy);
  231. }