Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <cursor.h>
6 #include <mouse.h>
8 void
9 moveto(Mousectl *m, Point pt)
10 {
11 fprint(m->mfd, "m%d %d", pt.x, pt.y);
12 m->xy = pt;
13 }
15 void
16 closemouse(Mousectl *mc)
17 {
18 if(mc == nil)
19 return;
21 postnote(PNPROC, mc->pid, "kill");
23 do; while(nbrecv(mc->c, &mc->Mouse) > 0);
25 close(mc->mfd);
26 close(mc->cfd);
27 free(mc->file);
28 free(mc->c);
29 free(mc->resizec);
30 free(mc);
31 }
33 int
34 readmouse(Mousectl *mc)
35 {
36 if(mc->image)
37 flushimage(mc->image->display, 1);
38 if(recv(mc->c, &mc->Mouse) < 0){
39 fprint(2, "readmouse: %r\n");
40 return -1;
41 }
42 return 0;
43 }
45 static
46 void
47 _ioproc(void *arg)
48 {
49 int n, nerr, one;
50 char buf[1+5*12];
51 Mouse m;
52 Mousectl *mc;
54 mc = arg;
55 threadsetname("mouseproc");
56 one = 1;
57 memset(&m, 0, sizeof m);
58 mc->pid = getpid();
59 nerr = 0;
60 for(;;){
61 n = read(mc->mfd, buf, sizeof buf);
62 if(n != 1+4*12){
63 yield(); /* if error is due to exiting, we'll exit here */
64 fprint(2, "mouse: bad count %d not 49: %r\n", n);
65 if(n<0 || ++nerr>10)
66 threadexits("read error");
67 continue;
68 }
69 nerr = 0;
70 switch(buf[0]){
71 case 'r':
72 send(mc->resizec, &one);
73 /* fall through */
74 case 'm':
75 m.xy.x = atoi(buf+1+0*12);
76 m.xy.y = atoi(buf+1+1*12);
77 m.buttons = atoi(buf+1+2*12);
78 m.msec = atoi(buf+1+3*12);
79 send(mc->c, &m);
80 /*
81 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
82 * This means that programs should receive into mc->Mouse (see readmouse() above) if
83 * they want full synchrony.
84 */
85 mc->Mouse = m;
86 break;
87 }
88 }
89 }
91 Mousectl*
92 initmouse(char *file, Image *i)
93 {
94 Mousectl *mc;
95 char *t, *sl;
97 mc = mallocz(sizeof(Mousectl), 1);
98 if(file == nil)
99 file = "/dev/mouse";
100 mc->file = strdup(file);
101 mc->mfd = open(file, ORDWR|OCEXEC);
102 if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){
103 bind("#m", "/dev", MAFTER);
104 mc->mfd = open(file, ORDWR|OCEXEC);
106 if(mc->mfd < 0){
107 free(mc);
108 return nil;
110 t = malloc(strlen(file)+16);
111 strcpy(t, file);
112 sl = utfrrune(t, '/');
113 if(sl)
114 strcpy(sl, "/cursor");
115 else
116 strcpy(t, "/dev/cursor");
117 mc->cfd = open(t, ORDWR|OCEXEC);
118 free(t);
119 mc->image = i;
120 mc->c = chancreate(sizeof(Mouse), 0);
121 chansetname(mc->c, "mousec");
122 mc->resizec = chancreate(sizeof(int), 2);
123 chansetname(mc->resizec, "resizec");
124 proccreate(_ioproc, mc, 4096);
125 return mc;
128 void
129 setcursor(Mousectl *mc, Cursor *c)
131 char curs[2*4+2*2*16];
133 if(c == nil)
134 write(mc->cfd, curs, 0);
135 else{
136 BPLONG(curs+0*4, c->offset.x);
137 BPLONG(curs+1*4, c->offset.y);
138 memmove(curs+2*4, c->clr, 2*2*16);
139 write(mc->cfd, curs, sizeof curs);