xref: /plan9/sys/src/cmd/vnc/wsys.c (revision cd42b31485b3c902f838a8604fadd3402f9f1270)
19a747e4fSDavid du Colombier #include "vnc.h"
29a747e4fSDavid du Colombier #include "vncv.h"
39a747e4fSDavid du Colombier #include <cursor.h>
49a747e4fSDavid du Colombier 
59a747e4fSDavid du Colombier typedef struct Cursor Cursor;
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier typedef struct Mouse Mouse;
89a747e4fSDavid du Colombier struct Mouse {
99a747e4fSDavid du Colombier 	int buttons;
109a747e4fSDavid du Colombier 	Point xy;
119a747e4fSDavid du Colombier };
129a747e4fSDavid du Colombier 
139a747e4fSDavid du Colombier static void
resize(Vnc * v,int first)149a747e4fSDavid du Colombier resize(Vnc *v, int first)
159a747e4fSDavid du Colombier {
169a747e4fSDavid du Colombier 	int fd;
179a747e4fSDavid du Colombier 	Point d;
189a747e4fSDavid du Colombier 
199a747e4fSDavid du Colombier 	d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth));
209a747e4fSDavid du Colombier 	lockdisplay(display);
219a747e4fSDavid du Colombier 
229a747e4fSDavid du Colombier 	if(getwindow(display, Refnone) < 0)
239a747e4fSDavid du Colombier 		sysfatal("internal error: can't get the window image");
249a747e4fSDavid du Colombier 
259a747e4fSDavid du Colombier 	/*
269a747e4fSDavid du Colombier 	 * limit the window to at most the vnc server's size
279a747e4fSDavid du Colombier 	 */
289a747e4fSDavid du Colombier 	if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){
299a747e4fSDavid du Colombier 		fd = open("/dev/wctl", OWRITE);
309a747e4fSDavid du Colombier 		if(fd >= 0){
319a747e4fSDavid du Colombier 			fprint(fd, "resize -dx %d -dy %d", d.x, d.y);
329a747e4fSDavid du Colombier 			close(fd);
339a747e4fSDavid du Colombier 		}
349a747e4fSDavid du Colombier 	}
359a747e4fSDavid du Colombier 	unlockdisplay(display);
369a747e4fSDavid du Colombier }
379a747e4fSDavid du Colombier 
389a747e4fSDavid du Colombier static void
eresized(void)399a747e4fSDavid du Colombier eresized(void)
409a747e4fSDavid du Colombier {
419a747e4fSDavid du Colombier 	resize(vnc, 0);
429a747e4fSDavid du Colombier 
439a747e4fSDavid du Colombier 	requestupdate(vnc, 0);
449a747e4fSDavid du Colombier }
459a747e4fSDavid du Colombier 
469a747e4fSDavid du Colombier static Cursor dotcursor = {
479a747e4fSDavid du Colombier 	{-7, -7},
489a747e4fSDavid du Colombier 	{0x00, 0x00,
499a747e4fSDavid du Colombier 	 0x00, 0x00,
509a747e4fSDavid du Colombier 	 0x00, 0x00,
519a747e4fSDavid du Colombier 	 0x00, 0x00,
529a747e4fSDavid du Colombier 	 0x03, 0xc0,
539a747e4fSDavid du Colombier 	 0x07, 0xe0,
549a747e4fSDavid du Colombier 	 0x0f, 0xf0,
559a747e4fSDavid du Colombier 	 0x0f, 0xf0,
569a747e4fSDavid du Colombier 	 0x0f, 0xf0,
579a747e4fSDavid du Colombier 	 0x07, 0xe0,
589a747e4fSDavid du Colombier 	 0x03, 0xc0,
599a747e4fSDavid du Colombier 	 0x00, 0x00,
609a747e4fSDavid du Colombier 	 0x00, 0x00,
619a747e4fSDavid du Colombier 	 0x00, 0x00,
629a747e4fSDavid du Colombier 	 0x00, 0x00,
639a747e4fSDavid du Colombier 	 0x00, 0x00, },
649a747e4fSDavid du Colombier 	{0x00, 0x00,
659a747e4fSDavid du Colombier 	 0x00, 0x00,
669a747e4fSDavid du Colombier 	 0x00, 0x00,
679a747e4fSDavid du Colombier 	 0x00, 0x00,
689a747e4fSDavid du Colombier 	 0x00, 0x00,
699a747e4fSDavid du Colombier 	 0x03, 0xc0,
709a747e4fSDavid du Colombier 	 0x07, 0xe0,
719a747e4fSDavid du Colombier 	 0x07, 0xe0,
729a747e4fSDavid du Colombier 	 0x07, 0xe0,
739a747e4fSDavid du Colombier 	 0x03, 0xc0,
749a747e4fSDavid du Colombier 	 0x00, 0x00,
759a747e4fSDavid du Colombier 	 0x00, 0x00,
769a747e4fSDavid du Colombier 	 0x00, 0x00,
779a747e4fSDavid du Colombier 	 0x00, 0x00,
789a747e4fSDavid du Colombier 	 0x00, 0x00,
799a747e4fSDavid du Colombier 	 0x00, 0x00, }
809a747e4fSDavid du Colombier };
819a747e4fSDavid du Colombier 
829a747e4fSDavid du Colombier static void
mouseevent(Vnc * v,Mouse m)839a747e4fSDavid du Colombier mouseevent(Vnc *v, Mouse m)
849a747e4fSDavid du Colombier {
859a747e4fSDavid du Colombier 	vnclock(v);
869a747e4fSDavid du Colombier 	vncwrchar(v, MMouse);
879a747e4fSDavid du Colombier 	vncwrchar(v, m.buttons);
889a747e4fSDavid du Colombier 	vncwrpoint(v, m.xy);
899a747e4fSDavid du Colombier 	vncflush(v);
909a747e4fSDavid du Colombier 	vncunlock(v);
919a747e4fSDavid du Colombier }
929a747e4fSDavid du Colombier 
93d9306527SDavid du Colombier void
mousewarp(Point pt)94d9306527SDavid du Colombier mousewarp(Point pt)
959a747e4fSDavid du Colombier {
969a747e4fSDavid du Colombier 	pt = addpt(pt, screen->r.min);
97d9306527SDavid du Colombier 	if(fprint(mousefd, "m%d %d", pt.x, pt.y) < 0)
98d9306527SDavid du Colombier 		fprint(2, "mousefd write: %r\n");
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier 
101d9306527SDavid du Colombier void
initmouse(void)102d9306527SDavid du Colombier initmouse(void)
1039a747e4fSDavid du Colombier {
1049a747e4fSDavid du Colombier 	char buf[1024];
1059a747e4fSDavid du Colombier 
1069a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/mouse", display->devdir);
1079a747e4fSDavid du Colombier 	if((mousefd = open(buf, ORDWR)) < 0)
1089a747e4fSDavid du Colombier 		sysfatal("open %s: %r", buf);
1099a747e4fSDavid du Colombier }
1109a747e4fSDavid du Colombier 
1119a747e4fSDavid du Colombier enum {
1129a747e4fSDavid du Colombier 	EventSize = 1+4*12
1139a747e4fSDavid du Colombier };
1149a747e4fSDavid du Colombier void
readmouse(Vnc * v)1159a747e4fSDavid du Colombier readmouse(Vnc *v)
1169a747e4fSDavid du Colombier {
1179a747e4fSDavid du Colombier 	int cursorfd, len, n;
1189a747e4fSDavid du Colombier 	char buf[10*EventSize], *start, *end;
1199a747e4fSDavid du Colombier 	uchar curs[2*4+2*2*16];
1209a747e4fSDavid du Colombier 	Cursor *cs;
1219a747e4fSDavid du Colombier 	Mouse m;
1229a747e4fSDavid du Colombier 
1239a747e4fSDavid du Colombier 	cs = &dotcursor;
1249a747e4fSDavid du Colombier 
1259a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/cursor", display->devdir);
1269a747e4fSDavid du Colombier 	if((cursorfd = open(buf, OWRITE)) < 0)
1279a747e4fSDavid du Colombier 		sysfatal("open %s: %r", buf);
1289a747e4fSDavid du Colombier 
1299a747e4fSDavid du Colombier 	BPLONG(curs+0*4, cs->offset.x);
1309a747e4fSDavid du Colombier 	BPLONG(curs+1*4, cs->offset.y);
1319a747e4fSDavid du Colombier 	memmove(curs+2*4, cs->clr, 2*2*16);
1329a747e4fSDavid du Colombier 	write(cursorfd, curs, sizeof curs);
1339a747e4fSDavid du Colombier 
1349a747e4fSDavid du Colombier 	resize(v, 1);
1359a747e4fSDavid du Colombier 	requestupdate(vnc, 0);
1369a747e4fSDavid du Colombier 	start = end = buf;
1379a747e4fSDavid du Colombier 	len = 0;
1389a747e4fSDavid du Colombier 	for(;;){
1399a747e4fSDavid du Colombier 		if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
1409a747e4fSDavid du Colombier 			sysfatal("read mouse failed");
1419a747e4fSDavid du Colombier 
1429a747e4fSDavid du Colombier 		len += n;
1439a747e4fSDavid du Colombier 		end += n;
1449a747e4fSDavid du Colombier 		while(len >= EventSize){
1459a747e4fSDavid du Colombier 			if(*start == 'm'){
1469a747e4fSDavid du Colombier 				m.xy.x = atoi(start+1);
1479a747e4fSDavid du Colombier 				m.xy.y = atoi(start+1+12);
14897787252SDavid du Colombier 				m.buttons = atoi(start+1+2*12) & 0x1F;
1499a747e4fSDavid du Colombier 				m.xy = subpt(m.xy, screen->r.min);
150*cd42b314SDavid du Colombier 				if(ptinrect(m.xy, Rpt(ZP, v->dim))){
1519a747e4fSDavid du Colombier 					mouseevent(v, m);
152*cd42b314SDavid du Colombier 					/* send wheel button *release* */
153*cd42b314SDavid du Colombier 					if ((m.buttons & 0x7) != m.buttons) {
154*cd42b314SDavid du Colombier 						m.buttons &= 0x7;
155*cd42b314SDavid du Colombier 						mouseevent(v, m);
156*cd42b314SDavid du Colombier 					}
157*cd42b314SDavid du Colombier 				}
1589a747e4fSDavid du Colombier 			} else
1599a747e4fSDavid du Colombier 				eresized();
1609a747e4fSDavid du Colombier 
1619a747e4fSDavid du Colombier 			start += EventSize;
1629a747e4fSDavid du Colombier 			len -= EventSize;
1639a747e4fSDavid du Colombier 		}
1649a747e4fSDavid du Colombier 		if(start - buf > sizeof(buf) - EventSize){
1659a747e4fSDavid du Colombier 			memmove(buf, start, len);
1669a747e4fSDavid du Colombier 			start = buf;
1679a747e4fSDavid du Colombier 			end = start+len;
1689a747e4fSDavid du Colombier 		}
1699a747e4fSDavid du Colombier 	}
1709a747e4fSDavid du Colombier }
1719a747e4fSDavid du Colombier 
1729a747e4fSDavid du Colombier static int snarffd = -1;
173e6c6b7f8SDavid du Colombier static ulong snarfvers;
1749a747e4fSDavid du Colombier 
1759a747e4fSDavid du Colombier void
writesnarf(Vnc * v,long n)1769a747e4fSDavid du Colombier writesnarf(Vnc *v, long n)
1779a747e4fSDavid du Colombier {
1789a747e4fSDavid du Colombier 	uchar buf[8192];
1799a747e4fSDavid du Colombier 	long m;
180e6c6b7f8SDavid du Colombier 	Biobuf *b;
1819a747e4fSDavid du Colombier 
182e6c6b7f8SDavid du Colombier 	if((b = Bopen("/dev/snarf", OWRITE)) == nil){
1839a747e4fSDavid du Colombier 		vncgobble(v, n);
1849a747e4fSDavid du Colombier 		return;
1859a747e4fSDavid du Colombier 	}
1869a747e4fSDavid du Colombier 
1879a747e4fSDavid du Colombier 	while(n > 0){
1889a747e4fSDavid du Colombier 		m = n;
1899a747e4fSDavid du Colombier 		if(m > sizeof(buf))
1909a747e4fSDavid du Colombier 			m = sizeof(buf);
1919a747e4fSDavid du Colombier 		vncrdbytes(v, buf, m);
1929a747e4fSDavid du Colombier 		n -= m;
1939a747e4fSDavid du Colombier 
194e6c6b7f8SDavid du Colombier 		Bwrite(b, buf, m);
1959a747e4fSDavid du Colombier 	}
196e6c6b7f8SDavid du Colombier 	Bterm(b);
197e6c6b7f8SDavid du Colombier 	snarfvers++;
1989a747e4fSDavid du Colombier }
1999a747e4fSDavid du Colombier 
2009a747e4fSDavid du Colombier char *
getsnarf(int * sz)2019a747e4fSDavid du Colombier getsnarf(int *sz)
2029a747e4fSDavid du Colombier {
2039a747e4fSDavid du Colombier 	char *snarf, *p;
2049a747e4fSDavid du Colombier 	int n, c;
2059a747e4fSDavid du Colombier 
2069a747e4fSDavid du Colombier 	*sz =0;
2079a747e4fSDavid du Colombier 	n = 8192;
2089a747e4fSDavid du Colombier 	p = snarf = malloc(n);
2099a747e4fSDavid du Colombier 
2109a747e4fSDavid du Colombier 	seek(snarffd, 0, 0);
2119a747e4fSDavid du Colombier 	while ((c = read(snarffd, p, n)) > 0){
2129a747e4fSDavid du Colombier 		p += c;
2139a747e4fSDavid du Colombier 		n -= c;
2149a747e4fSDavid du Colombier 		*sz += c;
2159a747e4fSDavid du Colombier 		if (n == 0){
2169a747e4fSDavid du Colombier 			snarf = realloc(snarf, *sz + 8192);
2179a747e4fSDavid du Colombier 			n = 8192;
2189a747e4fSDavid du Colombier 		}
2199a747e4fSDavid du Colombier 	}
2209a747e4fSDavid du Colombier 	return snarf;
2219a747e4fSDavid du Colombier }
2229a747e4fSDavid du Colombier 
2239a747e4fSDavid du Colombier void
checksnarf(Vnc * v)2249a747e4fSDavid du Colombier checksnarf(Vnc *v)
2259a747e4fSDavid du Colombier {
2269a747e4fSDavid du Colombier 	Dir *dir;
2279a747e4fSDavid du Colombier 	char *snarf;
2289a747e4fSDavid du Colombier 	int len;
2299a747e4fSDavid du Colombier 
2309a747e4fSDavid du Colombier 	if(snarffd < 0){
2319a747e4fSDavid du Colombier 		snarffd = open("/dev/snarf", OREAD);
2329a747e4fSDavid du Colombier 		if(snarffd < 0)
2339a747e4fSDavid du Colombier 			sysfatal("can't open /dev/snarf: %r");
2349a747e4fSDavid du Colombier 	}
2359a747e4fSDavid du Colombier 
236f8e525acSDavid du Colombier 	for(;;){
2379a747e4fSDavid du Colombier 		sleep(1000);
2389a747e4fSDavid du Colombier 
2399a747e4fSDavid du Colombier 		dir = dirstat("/dev/snarf");
2409a747e4fSDavid du Colombier 		if(dir == nil)	/* this happens under old drawterm */
2419a747e4fSDavid du Colombier 			continue;
242e6c6b7f8SDavid du Colombier 		if(dir->qid.vers > snarfvers){
2439a747e4fSDavid du Colombier 			snarf = getsnarf(&len);
2449a747e4fSDavid du Colombier 
2459a747e4fSDavid du Colombier 			vnclock(v);
2469a747e4fSDavid du Colombier 			vncwrchar(v, MCCut);
2479a747e4fSDavid du Colombier 			vncwrbytes(v, "pad", 3);
2489a747e4fSDavid du Colombier 			vncwrlong(v, len);
2499a747e4fSDavid du Colombier 			vncwrbytes(v, snarf, len);
2509a747e4fSDavid du Colombier 			vncflush(v);
2519a747e4fSDavid du Colombier 			vncunlock(v);
2529a747e4fSDavid du Colombier 
2539a747e4fSDavid du Colombier 			free(snarf);
2549a747e4fSDavid du Colombier 
255e6c6b7f8SDavid du Colombier 			snarfvers = dir->qid.vers;
2569a747e4fSDavid du Colombier 		}
2579a747e4fSDavid du Colombier 		free(dir);
2589a747e4fSDavid du Colombier 	}
2599a747e4fSDavid du Colombier }
260