wmfs.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include <getopt.h>
  6. #include <X11/keysym.h>
  7. #include <X11/cursorfont.h>
  8. #include "wmfs.h"
  9. #include "event.h"
  10. #include "ewmh.h"
  11. #include "screen.h"
  12. #include "infobar.h"
  13. #include "util.h"
  14. #include "config.h"
  15. #include "client.h"
  16. int
  17. wmfs_error_handler(Display *d, XErrorEvent *event)
  18. {
  19. char mess[256];
  20. /* Check if there is another WM running */
  21. if(event->error_code == BadAccess
  22. && W->root == event->resourceid)
  23. errx(EXIT_FAILURE, "Another Window Manager is already running.");
  24. /* Ignore focus change error for unmapped client
  25. * 42 = X_SetInputFocus
  26. * 28 = X_GrabButton
  27. */
  28. if(client_gb_win(event->resourceid))
  29. if(event->error_code == BadWindow
  30. || event->request_code == 42
  31. || event->request_code == 28)
  32. return 0;
  33. if(XGetErrorText(d, event->error_code, mess, 128))
  34. warnx("%s(%d) opcodes %d/%d\n resource #%lx\n",
  35. mess,
  36. event->error_code,
  37. event->request_code,
  38. event->minor_code,
  39. event->resourceid);
  40. return 1;
  41. }
  42. int
  43. wmfs_error_handler_dummy(Display *d, XErrorEvent *event)
  44. {
  45. (void)d;
  46. (void)event;
  47. return 0;
  48. }
  49. void
  50. wmfs_numlockmask(void)
  51. {
  52. int i, j;
  53. XModifierKeymap *mm = XGetModifierMapping(W->dpy);
  54. for(i = 0; i < 8; i++)
  55. for(j = 0; j < mm->max_keypermod; ++j)
  56. if(mm->modifiermap[i * mm->max_keypermod + j]
  57. == XKeysymToKeycode(W->dpy, XK_Num_Lock))
  58. W->numlockmask = (1 << i);
  59. XFreeModifiermap(mm);
  60. }
  61. void
  62. wmfs_init_font(char *font, struct theme *t)
  63. {
  64. XFontStruct **xfs = NULL;
  65. char **misschar, **names, *defstring;
  66. int d;
  67. if(!(t->font.fontset = XCreateFontSet(W->dpy, font, &misschar, &d, &defstring)))
  68. {
  69. warnx("Can't load font '%s'", font);
  70. t->font.fontset = XCreateFontSet(W->dpy, "fixed", &misschar, &d, &defstring);
  71. }
  72. XExtentsOfFontSet(t->font.fontset);
  73. XFontsOfFontSet(t->font.fontset, &xfs, &names);
  74. t->font.as = xfs[0]->max_bounds.ascent;
  75. t->font.de = xfs[0]->max_bounds.descent;
  76. t->font.width = xfs[0]->max_bounds.width;
  77. t->font.height = t->font.as + t->font.de;
  78. if(misschar)
  79. XFreeStringList(misschar);
  80. }
  81. static void
  82. wmfs_xinit(void)
  83. {
  84. XSetWindowAttributes at =
  85. {
  86. .event_mask = (KeyMask | ButtonMask | MouseMask
  87. | PropertyChangeMask | SubstructureRedirectMask
  88. | SubstructureNotifyMask | StructureNotifyMask),
  89. .cursor = XCreateFontCursor(W->dpy, XC_left_ptr)
  90. };
  91. /*
  92. * X Error handler
  93. */
  94. XSetErrorHandler(wmfs_error_handler);
  95. /*
  96. * X var
  97. */
  98. W->xscreen = DefaultScreen(W->dpy);
  99. W->xdepth = DefaultDepth(W->dpy, W->xscreen);
  100. W->gc = DefaultGC(W->dpy, W->xscreen);
  101. /*
  102. * Keys
  103. */
  104. wmfs_numlockmask();
  105. /*
  106. * Root window/cursor
  107. */
  108. W->root = RootWindow(W->dpy, W->xscreen);
  109. XChangeWindowAttributes(W->dpy, W->root, CWEventMask | CWCursor, &at);
  110. /*
  111. * Locale (font encode)
  112. */
  113. setlocale(LC_CTYPE, "");
  114. /*
  115. * Barwin linked list
  116. */
  117. SLIST_INIT(&W->h.barwin);
  118. W->running = true;
  119. }
  120. void
  121. wmfs_grab_keys(void)
  122. {
  123. KeyCode c;
  124. struct keybind *k;
  125. wmfs_numlockmask();
  126. XUngrabKey(W->dpy, AnyKey, AnyModifier, W->root);
  127. SLIST_FOREACH(k, &W->h.keybind, next)
  128. if((c = XKeysymToKeycode(W->dpy, k->keysym)))
  129. {
  130. XGrabKey(W->dpy, c, k->mod, W->root, True, GrabModeAsync, GrabModeAsync);
  131. XGrabKey(W->dpy, c, k->mod | LockMask, W->root, True, GrabModeAsync, GrabModeAsync);
  132. XGrabKey(W->dpy, c, k->mod | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
  133. XGrabKey(W->dpy, c, k->mod | LockMask | W->numlockmask, W->root, True, GrabModeAsync, GrabModeAsync);
  134. }
  135. }
  136. /** Scan if there are windows on X
  137. * for manage it
  138. */
  139. static void
  140. wmfs_scan(void)
  141. {
  142. int i, n;
  143. XWindowAttributes wa;
  144. Window usl, usl2, *w = NULL;
  145. SLIST_INIT(&W->h.client);
  146. /*
  147. Atom rt;
  148. int s, rf, tag = -1, screen = -1, flags = -1, i;
  149. ulong ir, il;
  150. uchar *ret;
  151. */
  152. if(XQueryTree(W->dpy, W->root, &usl, &usl2, &w, (unsigned int*)&n))
  153. for(i = n - 1; i != -1; --i)
  154. {
  155. XGetWindowAttributes(W->dpy, w[i], &wa);
  156. if(!wa.override_redirect && wa.map_state == IsViewable)
  157. {/*
  158. if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_TAG"), 0, 32,
  159. False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
  160. {
  161. tag = *ret;
  162. XFree(ret);
  163. }
  164. if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_SCREEN"), 0, 32,
  165. False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
  166. {
  167. screen = *ret;
  168. XFree(ret);
  169. }
  170. if(XGetWindowProperty(dpy, w[i], ATOM("_WMFS_FLAGS"), 0, 32,
  171. False, XA_CARDINAL, &rt, &rf, &ir, &il, &ret) == Success && ret)
  172. {
  173. flags = *ret;
  174. XFree(ret);
  175. }
  176. */
  177. /*c = */ client_new(w[i], &wa);
  178. /*
  179. if(tag != -1)
  180. c->tag = tag;
  181. if(screen != -1)
  182. c->screen = screen;
  183. if(flags != -1)
  184. c->flags = flags;
  185. */
  186. }
  187. }
  188. XFree(w);
  189. }
  190. static void
  191. wmfs_loop(void)
  192. {
  193. XEvent ev;
  194. while(XPending(W->dpy))
  195. while(W->running && !XNextEvent(W->dpy, &ev))
  196. EVENT_HANDLE(&ev);
  197. }
  198. static inline void
  199. wmfs_init(void)
  200. {
  201. wmfs_xinit();
  202. ewmh_init();
  203. screen_init();
  204. event_init();
  205. config_init();
  206. }
  207. void
  208. wmfs_quit(void)
  209. {
  210. struct keybind *k;
  211. struct theme *t;
  212. /* Will free:
  213. *
  214. * Screens -> tags
  215. * -> Infobars -> Elements
  216. */
  217. screen_free();
  218. XCloseDisplay(W->dpy);
  219. /* Conf stuffs */
  220. while(!SLIST_EMPTY(&W->h.keybind))
  221. {
  222. k = SLIST_FIRST(&W->h.keybind);
  223. SLIST_REMOVE_HEAD(&W->h.keybind, next);
  224. free((void*)k->cmd);
  225. free(k);
  226. }
  227. while(!SLIST_EMPTY(&W->h.theme))
  228. {
  229. t = SLIST_FIRST(&W->h.theme);
  230. SLIST_REMOVE_HEAD(&W->h.theme, next);
  231. XFreeFontSet(W->dpy, t->font.fontset);
  232. free(t);
  233. }
  234. free(W->net_atom);
  235. free(W);
  236. W->running = false;
  237. }
  238. /** Reload WMFS binary
  239. */
  240. void
  241. uicb_reload(Uicb cmd)
  242. {
  243. (void)cmd;
  244. /* TODO */
  245. }
  246. void
  247. uicb_quit(Uicb cmd)
  248. {
  249. (void)cmd;
  250. W->running = false;
  251. }
  252. int
  253. main(int argc, char **argv)
  254. {
  255. W = (struct wmfs*)xcalloc(1, sizeof(struct wmfs));
  256. /* Get X display */
  257. if(!(W->dpy = XOpenDisplay(NULL)))
  258. {
  259. fprintf(stderr, "%s: Can't open X server\n", argv[0]);
  260. exit(EXIT_FAILURE);
  261. }
  262. /* Opt */
  263. /*
  264. int i;
  265. while((i = getopt(argc, argv, "hviC:")) != -1)
  266. {
  267. switch(i)
  268. {
  269. case 'h':
  270. break;
  271. case 'v':
  272. break;
  273. case 'C':
  274. break;
  275. }
  276. }
  277. */
  278. /* Core */
  279. wmfs_init();
  280. wmfs_scan();
  281. wmfs_loop();
  282. wmfs_quit();
  283. return 1;
  284. }