]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/mouse.c
devvmx: add support for SG_STICKY segments
[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         close(mc->mfd);
21         close(mc->cfd);
22         mc->mfd = mc->cfd = -1;
23         threadint(mc->pid);
24 }
25
26 int
27 readmouse(Mousectl *mc)
28 {
29         if(mc->image){
30                 Display *d = mc->image->display;
31                 if(d->bufp > d->buf)
32                         flushimage(d, 1);
33         }
34         if(recv(mc->c, &mc->Mouse) < 0){
35                 fprint(2, "readmouse: %r\n");
36                 return -1;
37         }
38         return 0;
39 }
40
41 static
42 void
43 _ioproc(void *arg)
44 {
45         int n, nerr, one;
46         char buf[1+5*12];
47         Mouse m;
48         Mousectl *mc;
49
50         mc = arg;
51         threadsetname("mouseproc");
52         memset(&m, 0, sizeof m);
53         nerr = 0;
54         while(mc->mfd >= 0){
55                 n = read(mc->mfd, buf, sizeof buf);
56                 if(n != 1+4*12){
57                         yield();        /* if error is due to exiting, we'll exit here */
58                         if(mc->mfd < 0)
59                                 break;
60                         fprint(2, "mouse: bad count %d not 49: %r\n", n);
61                         if(n<0 || ++nerr>10)
62                                 threadexits("read error");
63                         continue;
64                 }
65                 nerr = 0;
66                 switch(buf[0]){
67                 case 'r':
68                         one = 1;
69                         if(send(mc->resizec, &one) < 0)
70                                 continue;
71                         /* fall through */
72                 case 'm':
73                         m.xy.x = atoi(buf+1+0*12);
74                         m.xy.y = atoi(buf+1+1*12);
75                         m.buttons = atoi(buf+1+2*12);
76                         m.msec = atoi(buf+1+3*12);
77                         if(send(mc->c, &m) < 0)
78                                 continue;
79                         /*
80                          * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
81                          * This means that programs should receive into mc->Mouse (see readmouse() above) if
82                          * they want full synchrony.
83                          */
84                         mc->Mouse = m;
85                         break;
86                 }
87         }
88         free(mc->file);
89         chanfree(mc->c);
90         chanfree(mc->resizec);
91         free(mc);
92 }
93
94 Mousectl*
95 initmouse(char *file, Image *i)
96 {
97         Mousectl *mc;
98         char *t, *sl;
99
100         mc = mallocz(sizeof(Mousectl), 1);
101         if(file == nil)
102                 file = "/dev/mouse";
103         mc->file = strdup(file);
104         mc->mfd = open(file, ORDWR|OCEXEC);
105         if(mc->mfd < 0){
106                 free(mc);
107                 return nil;
108         }
109         t = malloc(strlen(file)+16);
110         if (t == nil) {
111                 close(mc->mfd);
112                 free(mc);
113                 return nil;
114         }
115         strcpy(t, file);
116         sl = utfrrune(t, '/');
117         if(sl)
118                 strcpy(sl, "/cursor");
119         else
120                 strcpy(t, "/dev/cursor");
121         mc->cfd = open(t, ORDWR|OCEXEC);
122         free(t);
123         mc->image = i;
124         mc->c = chancreate(sizeof(Mouse), 0);
125         mc->resizec = chancreate(sizeof(int), 2);
126         mc->pid = proccreate(_ioproc, mc, 4096);
127         return mc;
128 }
129
130 void
131 setcursor(Mousectl *mc, Cursor *c)
132 {
133         char curs[2*4+2*2*16];
134
135         if(c == nil)
136                 write(mc->cfd, curs, 0);
137         else{
138                 BPLONG(curs+0*4, c->offset.x);
139                 BPLONG(curs+1*4, c->offset.y);
140                 memmove(curs+2*4, c->clr, 2*2*16);
141                 write(mc->cfd, curs, sizeof curs);
142         }
143 }