event.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include "event.h"
  6. #include "ewmh.h"
  7. #include "util.h"
  8. #include "wmfs.h"
  9. #include "client.h"
  10. #include "barwin.h"
  11. #include "screen.h"
  12. #include "systray.h"
  13. #define EVDPY(e) (e)->xany.display
  14. #define MOUSE_CHECK_BIND(m) \
  15. if(m->button == ev->button) \
  16. if(!m->use_area || (m->use_area && INAREA(ev->x, ev->y, m->area))) \
  17. if(m->func) \
  18. m->func(m->cmd);
  19. static void
  20. event_buttonpress(XEvent *e)
  21. {
  22. XButtonEvent *ev = &e->xbutton;
  23. struct mousebind *m;
  24. struct barwin *b;
  25. screen_update_sel();
  26. SLIST_FOREACH(b, &W->h.barwin, next)
  27. if(b->win == ev->window)
  28. {
  29. W->last_clicked_barwin = b;
  30. SLIST_FOREACH(m, &b->mousebinds, next)
  31. MOUSE_CHECK_BIND(m);
  32. SLIST_FOREACH(m, &b->statusmousebinds, next)
  33. MOUSE_CHECK_BIND(m);
  34. break;
  35. }
  36. }
  37. static void
  38. event_enternotify(XEvent *e)
  39. {
  40. XCrossingEvent *ev = &e->xcrossing;
  41. struct client *c;
  42. if((ev->mode != NotifyNormal
  43. || ev->detail == NotifyInferior)
  44. && ev->window != W->root)
  45. return;
  46. if(ev->window == W->systray.win || systray_find(ev->window))
  47. return;
  48. if((c = client_gb_win(ev->window))
  49. || (c = client_gb_frame(ev->window)))
  50. {
  51. if(c->flags & CLIENT_IGNORE_ENTER)
  52. c->flags ^= CLIENT_IGNORE_ENTER;
  53. else if(c != W->client && !(c->flags & CLIENT_TABBED))
  54. client_focus(c);
  55. }
  56. }
  57. static void
  58. event_clientmessageevent(XEvent *e)
  59. {
  60. XClientMessageEvent *ev = &e->xclient;
  61. struct client *c;
  62. struct _systray *sy;
  63. int type = 0;
  64. while(type < net_last && W->net_atom[type] != ev->message_type)
  65. ++type;
  66. /*
  67. * Systray message
  68. * _NET_WM_SYSTRAY_TRAY_OPCODE
  69. */
  70. if(ev->window == W->systray.win && type == net_system_tray_opcode)
  71. {
  72. if(ev->data.l[1] == XEMBED_EMBEDDED_NOTIFY)
  73. {
  74. systray_add(ev->data.l[2]);
  75. systray_update();
  76. }
  77. else if(ev->data.l[1] == XEMBED_REQUEST_FOCUS)
  78. {
  79. if((sy = systray_find(ev->data.l[2])))
  80. ewmh_send_message(sy->win, sy->win, "_XEMBED", XEMBED_FOCUS_IN,
  81. XEMBED_FOCUS_CURRENT, 0, 0, 0);
  82. }
  83. }
  84. else if(ev->window == W->root)
  85. {
  86. if(type == net_active_window)
  87. if((sy = systray_find(ev->data.l[0])))
  88. XSetInputFocus(W->dpy, sy->win, RevertToNone, CurrentTime);
  89. }
  90. switch(type)
  91. {
  92. /* _NET_WM_STATE */
  93. case net_wm_state:
  94. if((c = client_gb_win(ev->window)))
  95. ewmh_manage_state(ev->data.l, c);
  96. break;
  97. /* _NET_CLOSE_WINDOW */
  98. case net_close_window:
  99. if((c = client_gb_win(ev->window)))
  100. client_close(c);
  101. break;
  102. /* _NET_WM_DESKTOP */
  103. case net_wm_desktop:
  104. break;
  105. }
  106. }
  107. static void
  108. event_configureevent(XEvent *e)
  109. {
  110. XConfigureRequestEvent *ev = &e->xconfigurerequest;
  111. XWindowChanges wc;
  112. struct client *c;
  113. if((c = client_gb_win(ev->window)))
  114. {
  115. if(ev->value_mask & CWWidth)
  116. _fac_resize(c, Right, ev->width - c->wgeo.w);
  117. if(ev->value_mask & CWHeight)
  118. _fac_resize(c, Bottom, ev->height - c->wgeo.h);
  119. client_apply_tgeo(c->tag);
  120. }
  121. else
  122. {
  123. wc.x = ev->x;
  124. wc.y = ev->y;
  125. wc.width = ev->width;
  126. wc.height = ev->height;
  127. wc.border_width = ev->border_width;
  128. wc.sibling = ev->above;
  129. wc.stack_mode = ev->detail;
  130. XConfigureWindow(EVDPY(e), ev->window, ev->value_mask, &wc);
  131. }
  132. }
  133. static void
  134. event_destroynotify(XEvent *e)
  135. {
  136. XDestroyWindowEvent *ev = &e->xdestroywindow;
  137. struct client *c;
  138. struct _systray *s;
  139. if((c = client_gb_win(ev->window)))
  140. client_remove(c);
  141. else if((s = systray_find(ev->window)))
  142. {
  143. ewmh_set_wm_state(s->win, WithdrawnState);
  144. systray_del(s);
  145. systray_update();
  146. }
  147. }
  148. static void
  149. event_focusin(XEvent *e)
  150. {
  151. if(W->client
  152. && e->xfocus.window != W->client->win
  153. && e->xfocus.window != W->client->frame)
  154. client_focus(W->client);
  155. }
  156. static void
  157. event_maprequest(XEvent *e)
  158. {
  159. XMapRequestEvent *ev = &e->xmaprequest;
  160. XWindowAttributes at;
  161. struct _systray *s;
  162. /* Which windows to manage */
  163. if(!XGetWindowAttributes(EVDPY(e), ev->window, &at)
  164. || at.override_redirect)
  165. return;
  166. if(!client_gb_win(ev->window))
  167. client_new(ev->window, &at, false);
  168. else if((s = systray_find(ev->window)))
  169. {
  170. ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
  171. XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
  172. systray_update();
  173. }
  174. }
  175. static void
  176. event_mappingnotify(XEvent *e)
  177. {
  178. XMappingEvent *ev = &e->xmapping;
  179. XRefreshKeyboardMapping(ev);
  180. if(ev->request == MappingKeyboard)
  181. wmfs_grab_keys();
  182. }
  183. static void
  184. event_propertynotify(XEvent *e)
  185. {
  186. XPropertyEvent *ev = &e->xproperty;
  187. struct client *c;
  188. struct _systray *s;
  189. if(ev->state == PropertyDelete)
  190. return;
  191. if((c = client_gb_win(ev->window)))
  192. {
  193. switch(ev->atom)
  194. {
  195. case XA_WM_TRANSIENT_FOR:
  196. break;
  197. case XA_WM_NORMAL_HINTS:
  198. /* client_get_size_hints(c); */
  199. break;
  200. case XA_WM_HINTS:
  201. /*
  202. XWMHints *h;
  203. if((h = XGetWMHints(EVDPY, c->win)) && (h->flags & XUrgencyHint) && c != sel)
  204. {
  205. client_urgent(c, True);
  206. XFree(h);
  207. }
  208. */
  209. break;
  210. default:
  211. if(ev->atom == XA_WM_NAME || ev->atom == W->net_atom[net_wm_name])
  212. client_get_name(c);
  213. break;
  214. }
  215. }
  216. else if((s = systray_find(ev->window)))
  217. {
  218. systray_state(s);
  219. systray_update();
  220. }
  221. }
  222. static void
  223. event_unmapnotify(XEvent *e)
  224. {
  225. XUnmapEvent *ev = &e->xunmap;
  226. struct client *c;
  227. struct _systray *s;
  228. if((c = client_gb_win(ev->window)) && ev->send_event)
  229. client_remove(c);
  230. else if((s = systray_find(ev->window)))
  231. {
  232. systray_del(s);
  233. systray_update();
  234. }
  235. }
  236. static void
  237. event_keypress(XEvent *e)
  238. {
  239. XKeyPressedEvent *ev = &e->xkey;
  240. KeySym keysym = XKeycodeToKeysym(EVDPY(e), (KeyCode)ev->keycode, 0);
  241. struct keybind *k;
  242. screen_update_sel();
  243. SLIST_FOREACH(k, &W->h.keybind, next)
  244. if(k->keysym == keysym && KEYPRESS_MASK(k->mod) == KEYPRESS_MASK(ev->state))
  245. if(k->func)
  246. k->func(k->cmd);
  247. }
  248. static void
  249. event_expose(XEvent *e)
  250. {
  251. XExposeEvent *ev = &e->xexpose;
  252. struct barwin *b;
  253. SLIST_FOREACH(b, &W->h.barwin, next)
  254. if(b->win == ev->window)
  255. {
  256. barwin_refresh(b);
  257. return;
  258. }
  259. }
  260. static void
  261. event_mapnotify(XEvent *e)
  262. {
  263. XMapEvent *ev = &e->xmap;
  264. struct client *c;
  265. struct _systray *s;
  266. if(ev->window != ev->event && !ev->send_event)
  267. return;
  268. if((c = client_gb_win(ev->window)))
  269. ewmh_set_wm_state(c->win, NormalState);
  270. else if((s = systray_find(ev->window)))
  271. {
  272. ewmh_set_wm_state(s->win, NormalState);
  273. ewmh_send_message(s->win, s->win, "_XEMBED", CurrentTime,
  274. XEMBED_WINDOW_ACTIVATE, 0, 0, 0);
  275. }
  276. }
  277. static void
  278. event_selectionclearevent(XEvent *ev)
  279. {
  280. /* Getting selection if lost it */
  281. if(ev->xselectionclear.window == W->systray.win)
  282. systray_acquire();
  283. systray_update();
  284. }
  285. static void
  286. event_dummy(XEvent *e)
  287. {
  288. /* printf("%d\n", e->type);*/
  289. (void)e;
  290. }
  291. void
  292. event_init(void)
  293. {
  294. int i = MAX_EV;
  295. while(i--)
  296. event_handle[i] = event_dummy;
  297. event_handle[ButtonPress] = event_buttonpress;
  298. event_handle[ClientMessage] = event_clientmessageevent;
  299. event_handle[ConfigureRequest] = event_configureevent;
  300. event_handle[DestroyNotify] = event_destroynotify;
  301. event_handle[EnterNotify] = event_enternotify;
  302. event_handle[Expose] = event_expose;
  303. event_handle[FocusIn] = event_focusin;
  304. event_handle[KeyPress] = event_keypress;
  305. event_handle[MapNotify] = event_mapnotify;
  306. event_handle[MapRequest] = event_maprequest;
  307. event_handle[MappingNotify] = event_mappingnotify;
  308. event_handle[PropertyNotify] = event_propertynotify;
  309. /*event_handle[ReparentNotify] = event_reparentnotify;*/
  310. event_handle[SelectionClear] = event_selectionclearevent;
  311. event_handle[UnmapNotify] = event_unmapnotify;
  312. }