1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#include <u.h>
#include "x11-inc.h"
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <memdraw.h>
#include "x11-memdraw.h"
void
moveto(Mousectl *m, Point pt)
{
_xmoveto(pt);
}
void
closemouse(Mousectl *mc)
{
if(mc == nil)
return;
/* postnote(PNPROC, mc->pid, "kill");
*/
do; while(nbrecv(mc->c, &mc->m) > 0);
close(mc->mfd);
close(mc->cfd);
free(mc->file);
chanfree(mc->c);
chanfree(mc->resizec);
free(mc);
}
int
readmouse(Mousectl *mc)
{
if(mc->display)
flushimage(mc->display, 1);
if(recv(mc->c, &mc->m) < 0){
fprint(2, "readmouse: %r\n");
return -1;
}
return 0;
}
static
void
_ioproc(void *arg)
{
int fd, one;
ulong mask;
Mouse m;
Mousectl *mc;
XEvent xevent;
one = 1;
mc = arg;
threadsetname("mouseproc");
memset(&m, 0, sizeof m);
mc->pid = getpid();
mask = MouseMask|ExposureMask|StructureNotifyMask;
XSelectInput(_x.mousecon, _x.drawable, mask);
fd = XConnectionNumber(_x.mousecon);
for(;;){
while(XPending(_x.mousecon) == False)
threadfdwait(fd, 'r');
XNextEvent(_x.mousecon, &xevent);
switch(xevent.type){
case Expose:
_xexpose(&xevent, _x.mousecon);
continue;
case DestroyNotify:
if(_xdestroy(&xevent, _x.mousecon)){
/* drain it before sending */
/* apps that care can notice we sent a 0 */
/* otherwise we'll have getwindow send SIGHUP */
nbrecv(mc->resizec, 0);
nbrecv(mc->resizec, 0);
send(mc->resizec, 0);
}
continue;
case ConfigureNotify:
if(_xconfigure(&xevent, _x.mousecon))
nbsend(mc->resizec, &one);
continue;
case SelectionRequest:
_xselect(&xevent, _x.mousecon);
continue;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
if(_xtoplan9mouse(_x.mousecon, &xevent, &m) < 0)
continue;
send(mc->c, &m);
/*
* mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
* This means that programs should receive into mc->Mouse (see readmouse() above) if
* they want full synchrony.
*/
mc->m = m;
break;
}
}
}
Mousectl*
initmouse(char *file, Image *i)
{
Mousectl *mc;
threadfdwaitsetup();
mc = mallocz(sizeof(Mousectl), 1);
if(i)
mc->display = i->display;
mc->c = chancreate(sizeof(Mouse), 0);
mc->resizec = chancreate(sizeof(int), 2);
threadcreate(_ioproc, mc, 16384);
return mc;
}
void
setcursor(Mousectl *mc, Cursor *c)
{
_xsetcursor(c);
}
|