]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/mouse.c
merge
[plan9front.git] / sys / src / libdraw / mouse.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <cursor.h>
6 #include <mouse.h>
7
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 }
14
15 void
16 closemouse(Mousectl *mc)
17 {
18         if(mc == nil)
19                 return;
20
21         postnote(PNPROC, mc->pid, "kill");
22
23         do; while(nbrecv(mc->c, &mc->Mouse) > 0);
24
25         close(mc->mfd);
26         close(mc->cfd);
27         free(mc->file);
28         free(mc->c);
29         free(mc->resizec);
30         free(mc);
31 }
32
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 }
44
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;
53
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 }
90
91 Mousectl*
92 initmouse(char *file, Image *i)
93 {
94         Mousectl *mc;
95         char *t, *sl;
96
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);
105         }
106         if(mc->mfd < 0){
107                 free(mc);
108                 return nil;
109         }
110         t = malloc(strlen(file)+16);
111         if (t == nil) {
112                 close(mc->mfd);
113                 free(mc);
114                 return nil;
115         }
116         strcpy(t, file);
117         sl = utfrrune(t, '/');
118         if(sl)
119                 strcpy(sl, "/cursor");
120         else
121                 strcpy(t, "/dev/cursor");
122         mc->cfd = open(t, ORDWR|OCEXEC);
123         free(t);
124         mc->image = i;
125         mc->c = chancreate(sizeof(Mouse), 0);
126         mc->resizec = chancreate(sizeof(int), 2);
127         proccreate(_ioproc, mc, 4096);
128         return mc;
129 }
130
131 void
132 setcursor(Mousectl *mc, Cursor *c)
133 {
134         char curs[2*4+2*2*16];
135
136         if(c == nil)
137                 write(mc->cfd, curs, 0);
138         else{
139                 BPLONG(curs+0*4, c->offset.x);
140                 BPLONG(curs+1*4, c->offset.y);
141                 memmove(curs+2*4, c->clr, 2*2*16);
142                 write(mc->cfd, curs, sizeof curs);
143         }
144 }