mouse.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * wmfs2 by Martin Duquesnoy <xorg62@gmail.com> { for(i = 2011; i < 2111; ++i) ©(i); }
  3. * For license, see COPYING.
  4. */
  5. #include "wmfs.h"
  6. #include "mouse.h"
  7. #include "barwin.h"
  8. #include "client.h"
  9. #include "draw.h"
  10. #define _REV_SBORDER(c) draw_reversed_rect(W->root, c, false);
  11. #define _REV_BORDER() \
  12. do { \
  13. FOREACH_NFCLIENT(gc, &c->tag->clients, tnext) \
  14. draw_reversed_rect(W->root, gc, true); \
  15. } while(/* CONSTCOND */ 0);
  16. static void
  17. mouse_resize(struct client *c)
  18. {
  19. struct client *gc;
  20. XEvent ev;
  21. Window w;
  22. int d, u, ox, oy, ix, iy;
  23. int mx, my;
  24. XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (unsigned int *)&u);
  25. XGrabServer(W->dpy);
  26. if(c->flags & CLIENT_FREE)
  27. {
  28. _REV_SBORDER(c);
  29. }
  30. else
  31. _REV_BORDER();
  32. if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
  33. c = c->tabmaster;
  34. ix = ox;
  35. iy = oy;
  36. c->flags |= CLIENT_MOUSE;
  37. do
  38. {
  39. XMaskEvent(W->dpy, MouseMask | SubstructureRedirectMask, &ev);
  40. if(ev.type != MotionNotify)
  41. continue;
  42. mx = ev.xmotion.x_root;
  43. my = ev.xmotion.y_root;
  44. if(c->flags & CLIENT_FREE)
  45. {
  46. _REV_SBORDER(c);
  47. mx -= c->screen->ugeo.x;
  48. my -= c->screen->ugeo.y;
  49. c->geo.w = ((mx - c->geo.x <= c->sizeh[MINW] + c->border + c->border)
  50. ? c->sizeh[MINW] + c->border + c->border
  51. : mx - c->geo.x);
  52. c->geo.h = ((my - c->geo.y <= (c->sizeh[MINH] + c->tbarw + c->border))
  53. ? c->sizeh[MINH] + c->tbarw + c->border
  54. : my - c->geo.y);
  55. client_geo_hints(&c->geo, (int*)c->sizeh);
  56. /* For border preview cohesion */
  57. c->geo.h += c->tbarw + c->border;
  58. c->geo.w += c->border + c->border;
  59. _REV_SBORDER(c);
  60. }
  61. else
  62. {
  63. _REV_BORDER();
  64. if(ix >= c->rgeo.x + (c->geo.w >> 1))
  65. _fac_resize(c, Right, mx - ox);
  66. else
  67. _fac_resize(c, Left, ox - mx);
  68. if(iy >= c->rgeo.y + (c->geo.h >> 1))
  69. _fac_resize(c, Bottom, my - oy);
  70. else
  71. _fac_resize(c, Top, oy - my);
  72. ox = mx;
  73. oy = my;
  74. _REV_BORDER();
  75. }
  76. XSync(W->dpy, false);
  77. } while(ev.type != ButtonRelease);
  78. if(c->flags & CLIENT_FREE)
  79. {
  80. _REV_SBORDER(c);
  81. client_moveresize(c, &c->geo);
  82. }
  83. else
  84. {
  85. _REV_BORDER();
  86. client_apply_tgeo(c->tag);
  87. layout_save_set(c->tag);
  88. }
  89. c->flags &= ~CLIENT_MOUSE;
  90. XUngrabServer(W->dpy);
  91. }
  92. static struct tag*
  93. mouse_drag_tag(struct client *c, Window w)
  94. {
  95. struct barwin *b;
  96. struct tag *t = NULL;
  97. Window rw;
  98. int d, u;
  99. XQueryPointer(W->dpy, w, &rw, &rw, &d, &d, &d, &d, (uint *)&u);
  100. SLIST_FOREACH(b, &W->h.barwin, next)
  101. if(b->win == rw
  102. && (t = (struct tag*)b->ptr)
  103. && t != c->tag)
  104. return t;
  105. return NULL;
  106. }
  107. void
  108. mouse_move(struct client *c, void (*func)(struct client*, struct client*))
  109. {
  110. struct client *c2 = NULL, *last = c;
  111. struct tag *t = NULL;
  112. XEvent ev;
  113. Window w;
  114. int d, u, ox, oy;
  115. int ocx, ocy;
  116. ocx = c->geo.x;
  117. ocy = c->geo.y;
  118. if(c->flags & CLIENT_TABBED && !(c->flags & CLIENT_TABMASTER))
  119. c = c->tabmaster;
  120. XQueryPointer(W->dpy, W->root, &w, &w, &ox, &oy, &d, &d, (uint *)&u);
  121. _REV_SBORDER(c);
  122. c->flags |= CLIENT_MOUSE;
  123. do
  124. {
  125. XMaskEvent(W->dpy, MouseMask | SubstructureRedirectMask, &ev);
  126. if(ev.type != MotionNotify)
  127. continue;
  128. if(!func && c->flags & CLIENT_FREE)
  129. {
  130. _REV_SBORDER(c);
  131. c->geo.x = (ocx + (ev.xmotion.x_root - ox));
  132. c->geo.y = (ocy + (ev.xmotion.y_root - oy));
  133. _REV_SBORDER(c);
  134. }
  135. else
  136. {
  137. c2 = NULL;
  138. XQueryPointer(W->dpy, W->root, &w, &w, &d, &d, &d, &d, (uint *)&u);
  139. if((c2 = client_gb_win(w)) || (c2 = client_gb_frame(w)) || (c2 = client_gb_titlebar(w)))
  140. {
  141. if(c2 != last)
  142. {
  143. _REV_SBORDER(last);
  144. _REV_SBORDER(c2);
  145. last = c2;
  146. }
  147. }
  148. else
  149. t = mouse_drag_tag(c, w);
  150. }
  151. XSync(W->dpy, false);
  152. } while(ev.type != ButtonRelease);
  153. if(c2)
  154. func(c, c2);
  155. else if(t && t != (struct tag*)c)
  156. tag_client(t, c);
  157. else
  158. {
  159. _REV_SBORDER(c);
  160. /* No func mean free client resize */
  161. if(!func)
  162. client_moveresize(c, &c->geo);
  163. }
  164. c->flags &= ~CLIENT_MOUSE;
  165. }
  166. void
  167. uicb_mouse_resize(Uicb cmd)
  168. {
  169. (void)cmd;
  170. if(W->client && mouse_check_client(W->client))
  171. mouse_resize(W->client);
  172. }
  173. void
  174. uicb_mouse_move(Uicb cmd)
  175. {
  176. (void)cmd;
  177. if(W->client && mouse_check_client(W->client))
  178. mouse_move(W->client, (W->client->flags & CLIENT_FREE ? NULL : client_swap2));
  179. }
  180. void
  181. uicb_mouse_tab(Uicb cmd)
  182. {
  183. (void)cmd;
  184. if(W->client && mouse_check_client(W->client))
  185. mouse_move(W->client, _client_tab);
  186. }