xref: /plan9/sys/src/libdraw/mouse.c (revision 223a035810d484657ee1a815f68faa8211009d6d)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier void
moveto(Mousectl * m,Point pt)97dd7cddfSDavid du Colombier moveto(Mousectl *m, Point pt)
107dd7cddfSDavid du Colombier {
119a747e4fSDavid du Colombier 	fprint(m->mfd, "m%d %d", pt.x, pt.y);
127dd7cddfSDavid du Colombier 	m->xy = pt;
137dd7cddfSDavid du Colombier }
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier void
closemouse(Mousectl * mc)167dd7cddfSDavid du Colombier closemouse(Mousectl *mc)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier 	if(mc == nil)
197dd7cddfSDavid du Colombier 		return;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	postnote(PNPROC, mc->pid, "kill");
227dd7cddfSDavid du Colombier 
239a747e4fSDavid du Colombier 	do; while(nbrecv(mc->c, &mc->Mouse) > 0);
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier 	close(mc->mfd);
267dd7cddfSDavid du Colombier 	close(mc->cfd);
277dd7cddfSDavid du Colombier 	free(mc->file);
287dd7cddfSDavid du Colombier 	free(mc->c);
297dd7cddfSDavid du Colombier 	free(mc->resizec);
307dd7cddfSDavid du Colombier 	free(mc);
317dd7cddfSDavid du Colombier }
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier int
readmouse(Mousectl * mc)347dd7cddfSDavid du Colombier readmouse(Mousectl *mc)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier 	if(mc->image)
377dd7cddfSDavid du Colombier 		flushimage(mc->image->display, 1);
387dd7cddfSDavid du Colombier 	if(recv(mc->c, &mc->Mouse) < 0){
399a747e4fSDavid du Colombier 		fprint(2, "readmouse: %r\n");
407dd7cddfSDavid du Colombier 		return -1;
417dd7cddfSDavid du Colombier 	}
427dd7cddfSDavid du Colombier 	return 0;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier static
467dd7cddfSDavid du Colombier void
_ioproc(void * arg)473ff48bf5SDavid du Colombier _ioproc(void *arg)
487dd7cddfSDavid du Colombier {
497dd7cddfSDavid du Colombier 	int n, nerr, one;
507dd7cddfSDavid du Colombier 	char buf[1+5*12];
517dd7cddfSDavid du Colombier 	Mouse m;
527dd7cddfSDavid du Colombier 	Mousectl *mc;
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier 	mc = arg;
557dd7cddfSDavid du Colombier 	threadsetname("mouseproc");
567dd7cddfSDavid du Colombier 	one = 1;
577dd7cddfSDavid du Colombier 	memset(&m, 0, sizeof m);
587dd7cddfSDavid du Colombier 	mc->pid = getpid();
597dd7cddfSDavid du Colombier 	nerr = 0;
607dd7cddfSDavid du Colombier 	for(;;){
617dd7cddfSDavid du Colombier 		n = read(mc->mfd, buf, sizeof buf);
627dd7cddfSDavid du Colombier 		if(n != 1+4*12){
639a747e4fSDavid du Colombier 			yield();	/* if error is due to exiting, we'll exit here */
649a747e4fSDavid du Colombier 			fprint(2, "mouse: bad count %d not 49: %r\n", n);
657dd7cddfSDavid du Colombier 			if(n<0 || ++nerr>10)
667dd7cddfSDavid du Colombier 				threadexits("read error");
677dd7cddfSDavid du Colombier 			continue;
687dd7cddfSDavid du Colombier 		}
697dd7cddfSDavid du Colombier 		nerr = 0;
707dd7cddfSDavid du Colombier 		switch(buf[0]){
717dd7cddfSDavid du Colombier 		case 'r':
727dd7cddfSDavid du Colombier 			send(mc->resizec, &one);
737dd7cddfSDavid du Colombier 			/* fall through */
747dd7cddfSDavid du Colombier 		case 'm':
757dd7cddfSDavid du Colombier 			m.xy.x = atoi(buf+1+0*12);
767dd7cddfSDavid du Colombier 			m.xy.y = atoi(buf+1+1*12);
777dd7cddfSDavid du Colombier 			m.buttons = atoi(buf+1+2*12);
787dd7cddfSDavid du Colombier 			m.msec = atoi(buf+1+3*12);
797dd7cddfSDavid du Colombier 			send(mc->c, &m);
807dd7cddfSDavid du Colombier 			/*
817dd7cddfSDavid du Colombier 			 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send.
827dd7cddfSDavid du Colombier 			 * This means that programs should receive into mc->Mouse (see readmouse() above) if
837dd7cddfSDavid du Colombier 			 * they want full synchrony.
847dd7cddfSDavid du Colombier 			 */
857dd7cddfSDavid du Colombier 			mc->Mouse = m;
867dd7cddfSDavid du Colombier 			break;
877dd7cddfSDavid du Colombier 		}
887dd7cddfSDavid du Colombier 	}
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier Mousectl*
initmouse(char * file,Image * i)927dd7cddfSDavid du Colombier initmouse(char *file, Image *i)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier 	Mousectl *mc;
957dd7cddfSDavid du Colombier 	char *t, *sl;
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	mc = mallocz(sizeof(Mousectl), 1);
987dd7cddfSDavid du Colombier 	if(file == nil)
997dd7cddfSDavid du Colombier 		file = "/dev/mouse";
1007dd7cddfSDavid du Colombier 	mc->file = strdup(file);
1017dd7cddfSDavid du Colombier 	mc->mfd = open(file, ORDWR|OCEXEC);
1027dd7cddfSDavid du Colombier 	if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){
1037dd7cddfSDavid du Colombier 		bind("#m", "/dev", MAFTER);
1047dd7cddfSDavid du Colombier 		mc->mfd = open(file, ORDWR|OCEXEC);
1057dd7cddfSDavid du Colombier 	}
1067dd7cddfSDavid du Colombier 	if(mc->mfd < 0){
1077dd7cddfSDavid du Colombier 		free(mc);
1087dd7cddfSDavid du Colombier 		return nil;
1097dd7cddfSDavid du Colombier 	}
1107dd7cddfSDavid du Colombier 	t = malloc(strlen(file)+16);
111*223a0358SDavid du Colombier 	if (t == nil) {
112*223a0358SDavid du Colombier 		close(mc->mfd);
113*223a0358SDavid du Colombier 		free(mc);
114*223a0358SDavid du Colombier 		return nil;
115*223a0358SDavid du Colombier 	}
1167dd7cddfSDavid du Colombier 	strcpy(t, file);
1177dd7cddfSDavid du Colombier 	sl = utfrrune(t, '/');
1187dd7cddfSDavid du Colombier 	if(sl)
1197dd7cddfSDavid du Colombier 		strcpy(sl, "/cursor");
1207dd7cddfSDavid du Colombier 	else
1217dd7cddfSDavid du Colombier 		strcpy(t, "/dev/cursor");
1227dd7cddfSDavid du Colombier 	mc->cfd = open(t, ORDWR|OCEXEC);
1237dd7cddfSDavid du Colombier 	free(t);
1247dd7cddfSDavid du Colombier 	mc->image = i;
1257dd7cddfSDavid du Colombier 	mc->c = chancreate(sizeof(Mouse), 0);
1267dd7cddfSDavid du Colombier 	mc->resizec = chancreate(sizeof(int), 2);
1273ff48bf5SDavid du Colombier 	proccreate(_ioproc, mc, 4096);
1287dd7cddfSDavid du Colombier 	return mc;
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier 
1317dd7cddfSDavid du Colombier void
setcursor(Mousectl * mc,Cursor * c)1327dd7cddfSDavid du Colombier setcursor(Mousectl *mc, Cursor *c)
1337dd7cddfSDavid du Colombier {
1347dd7cddfSDavid du Colombier 	char curs[2*4+2*2*16];
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier 	if(c == nil)
1377dd7cddfSDavid du Colombier 		write(mc->cfd, curs, 0);
1387dd7cddfSDavid du Colombier 	else{
1397dd7cddfSDavid du Colombier 		BPLONG(curs+0*4, c->offset.x);
1407dd7cddfSDavid du Colombier 		BPLONG(curs+1*4, c->offset.y);
1417dd7cddfSDavid du Colombier 		memmove(curs+2*4, c->clr, 2*2*16);
1427dd7cddfSDavid du Colombier 		write(mc->cfd, curs, sizeof curs);
1437dd7cddfSDavid du Colombier 	}
1447dd7cddfSDavid du Colombier }
145