aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/mouse.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdraw/mouse.c')
-rw-r--r--src/libdraw/mouse.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/libdraw/mouse.c b/src/libdraw/mouse.c
new file mode 100644
index 00000000..e7b8f890
--- /dev/null
+++ b/src/libdraw/mouse.c
@@ -0,0 +1,139 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <cursor.h>
+#include <mouse.h>
+
+void
+moveto(Mousectl *m, Point pt)
+{
+ fprint(m->mfd, "m%d %d", pt.x, pt.y);
+ m->xy = pt;
+}
+
+void
+closemouse(Mousectl *mc)
+{
+ if(mc == nil)
+ return;
+
+ postnote(PNPROC, mc->pid, "kill");
+
+ do; while(nbrecv(mc->c, &mc->Mouse) > 0);
+
+ close(mc->mfd);
+ close(mc->cfd);
+ free(mc->file);
+ free(mc->c);
+ free(mc->resizec);
+ free(mc);
+}
+
+int
+readmouse(Mousectl *mc)
+{
+ if(mc->image)
+ flushimage(mc->image->display, 1);
+ if(recv(mc->c, &mc->Mouse) < 0){
+ fprint(2, "readmouse: %r\n");
+ return -1;
+ }
+ return 0;
+}
+
+static
+void
+_ioproc(void *arg)
+{
+ int n, nerr, one;
+ char buf[1+5*12];
+ Mouse m;
+ Mousectl *mc;
+
+ mc = arg;
+ threadsetname("mouseproc");
+ one = 1;
+ memset(&m, 0, sizeof m);
+ mc->pid = getpid();
+ nerr = 0;
+ for(;;){
+ n = read(mc->mfd, buf, sizeof buf);
+ if(n != 1+4*12){
+ yield(); /* if error is due to exiting, we'll exit here */
+ fprint(2, "mouse: bad count %d not 49: %r\n", n);
+ if(n<0 || ++nerr>10)
+ threadexits("read error");
+ continue;
+ }
+ nerr = 0;
+ switch(buf[0]){
+ case 'r':
+ send(mc->resizec, &one);
+ /* fall through */
+ case 'm':
+ m.xy.x = atoi(buf+1+0*12);
+ m.xy.y = atoi(buf+1+1*12);
+ m.buttons = atoi(buf+1+2*12);
+ m.msec = atoi(buf+1+3*12);
+ 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->Mouse = m;
+ break;
+ }
+ }
+}
+
+Mousectl*
+initmouse(char *file, Image *i)
+{
+ Mousectl *mc;
+ char *t, *sl;
+
+ mc = mallocz(sizeof(Mousectl), 1);
+ if(file == nil)
+ file = "/dev/mouse";
+ mc->file = strdup(file);
+ mc->mfd = open(file, ORDWR|OCEXEC);
+ if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){
+ bind("#m", "/dev", MAFTER);
+ mc->mfd = open(file, ORDWR|OCEXEC);
+ }
+ if(mc->mfd < 0){
+ free(mc);
+ return nil;
+ }
+ t = malloc(strlen(file)+16);
+ strcpy(t, file);
+ sl = utfrrune(t, '/');
+ if(sl)
+ strcpy(sl, "/cursor");
+ else
+ strcpy(t, "/dev/cursor");
+ mc->cfd = open(t, ORDWR|OCEXEC);
+ free(t);
+ mc->image = i;
+ mc->c = chancreate(sizeof(Mouse), 0);
+ mc->resizec = chancreate(sizeof(int), 2);
+ proccreate(_ioproc, mc, 4096);
+ return mc;
+}
+
+void
+setcursor(Mousectl *mc, Cursor *c)
+{
+ char curs[2*4+2*2*16];
+
+ if(c == nil)
+ write(mc->cfd, curs, 0);
+ else{
+ BPLONG(curs+0*4, c->offset.x);
+ BPLONG(curs+1*4, c->offset.y);
+ memmove(curs+2*4, c->clr, 2*2*16);
+ write(mc->cfd, curs, sizeof curs);
+ }
+}