Blob


1 #include <u.h>
2 #include "x11-inc.h"
3 #include <libc.h>
4 #include <draw.h>
5 #include <thread.h>
6 #include <cursor.h>
7 #include <mouse.h>
8 #include <memdraw.h>
9 #include "x11-memdraw.h"
11 int _windowhasfocus = 1;
12 int _wantfocuschanges;
14 void
15 moveto(Mousectl *m, Point pt)
16 {
17 _xmoveto(pt);
18 }
20 void
21 closemouse(Mousectl *mc)
22 {
23 if(mc == nil)
24 return;
26 /* postnote(PNPROC, mc->pid, "kill");
27 */
28 do; while(nbrecv(mc->c, &mc->m) > 0);
29 close(mc->mfd);
30 close(mc->cfd);
31 free(mc->file);
32 chanfree(mc->c);
33 chanfree(mc->resizec);
34 free(mc);
35 }
37 int
38 readmouse(Mousectl *mc)
39 {
40 if(mc->display)
41 flushimage(mc->display, 1);
42 if(recv(mc->c, &mc->m) < 0){
43 fprint(2, "readmouse: %r\n");
44 return -1;
45 }
46 return 0;
47 }
49 static
50 void
51 _ioproc(void *arg)
52 {
53 int fd, one, buttons;
54 Atom a;
55 ulong mask;
56 Mouse m;
57 Mousectl *mc;
58 XEvent xevent;
60 one = 1;
61 mc = arg;
62 threadsetname("mouseproc");
63 memset(&m, 0, sizeof m);
64 mc->pid = getpid();
65 mask = MouseMask|ExposureMask|StructureNotifyMask;
66 XSelectInput(_x.mousecon, _x.drawable, mask);
67 fd = XConnectionNumber(_x.mousecon);
68 buttons = 0;
69 for(;;){
70 XNextEvent(_x.mousecon, &xevent);
71 switch(xevent.type){
72 case Expose:
73 _xexpose(&xevent, _x.mousecon);
74 continue;
75 case DestroyNotify:
76 if(_xdestroy(&xevent, _x.mousecon)){
77 /* drain it before sending */
78 /* apps that care can notice we sent a 0 */
79 /* otherwise we'll have getwindow send SIGHUP */
80 nbrecv(mc->resizec, 0);
81 nbrecv(mc->resizec, 0);
82 send(mc->resizec, 0);
83 }
84 continue;
85 case ConfigureNotify:
86 if(_xconfigure(&xevent, _x.mousecon))
87 nbsend(mc->resizec, &one);
88 continue;
89 case SelectionRequest:
90 _xselect(&xevent, _x.mousecon);
91 continue;
92 case ButtonPress:
93 case ButtonRelease:
94 case MotionNotify:
95 /* If the motion notifications are backing up, skip over some. */
96 if(0 && xevent.type == MotionNotify){
97 while(XCheckWindowEvent(_x.mousecon, _x.drawable, MouseMask, &xevent)){
98 if(xevent.type != MotionNotify)
99 break;
102 m.buttons = buttons;
103 if(_xtoplan9mouse(_x.mousecon, &xevent, &m) < 0)
104 continue;
105 buttons = m.buttons;
106 send(mc->c, &m);
107 /*
108 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
109 * This means that programs should receive into mc->Mouse (see readmouse() above) if
110 * they want full synchrony.
111 */
112 mc->m = m;
113 break;
114 case ClientMessage:
115 if(xevent.xclient.message_type == _x.wmprotos){
116 a = xevent.xclient.data.l[0];
117 if(_wantfocuschanges && a == _x.takefocus){
118 _windowhasfocus = 1;
119 _x.newscreenr = _x.screenr;
120 nbsend(mc->resizec, &one);
121 }else if(_wantfocuschanges && a == _x.losefocus){
122 _windowhasfocus = 0;
123 _x.newscreenr = _x.screenr;
124 nbsend(mc->resizec, &one);
127 break;
132 Mousectl*
133 initmouse(char *file, Image *i)
135 Mousectl *mc;
137 mc = mallocz(sizeof(Mousectl), 1);
138 if(i)
139 mc->display = i->display;
140 mc->c = chancreate(sizeof(Mouse), 0);
141 chansetname(mc->c, "mousec");
142 mc->resizec = chancreate(sizeof(int), 2);
143 chansetname(mc->resizec, "resizec");
144 proccreate(_ioproc, mc, 32768);
145 return mc;
148 void
149 setcursor(Mousectl *mc, Cursor *c)
151 _xsetcursor(c);
154 /*
155 * Send the mouse event back to the window manager.
156 * So that 9term can tell rio to pop up its button3 menu.
157 * Note that we're using _x.mousecon in a few places,
158 * so we have to be sure that the mouse proc isn't using it
159 * when we call! This is all a bit wonky and should be
160 * avoided unless you know what you're doing.
161 */
162 void
163 bouncemouse(Mouse *m)
165 XButtonEvent e;
166 XWindow dw;
168 e.type = ButtonPress;
169 e.state = 0;
170 e.button = 0;
171 if(m->buttons&1)
172 e.button = 1;
173 else if(m->buttons&2)
174 e.button = 2;
175 else if(m->buttons&4)
176 e.button = 3;
177 e.same_screen = 1;
178 XTranslateCoordinates(_x.display, _x.drawable,
179 DefaultRootWindow(_x.display),
180 m->xy.x, m->xy.y, &e.x_root, &e.y_root, &dw);
181 e.root = DefaultRootWindow(_x.mousecon);
182 e.window = e.root;
183 e.subwindow = None;
184 e.x = e.x_root;
185 e.y = e.y_root;
186 #undef time
187 e.time = CurrentTime;
188 XUngrabPointer(_x.mousecon, m->msec);
189 XSendEvent(_x.mousecon, e.root, True, ButtonPressMask, (XEvent*)&e);
190 XFlush(_x.mousecon);