xref: /plan9/sys/src/cmd/vnc/wsys.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include "vnc.h"
2*9a747e4fSDavid du Colombier #include "vncv.h"
3*9a747e4fSDavid du Colombier #include <cursor.h>
4*9a747e4fSDavid du Colombier 
5*9a747e4fSDavid du Colombier typedef struct Cursor Cursor;
6*9a747e4fSDavid du Colombier 
7*9a747e4fSDavid du Colombier typedef struct Mouse Mouse;
8*9a747e4fSDavid du Colombier struct Mouse {
9*9a747e4fSDavid du Colombier 	int buttons;
10*9a747e4fSDavid du Colombier 	Point xy;
11*9a747e4fSDavid du Colombier };
12*9a747e4fSDavid du Colombier 
13*9a747e4fSDavid du Colombier static void
14*9a747e4fSDavid du Colombier resize(Vnc *v, int first)
15*9a747e4fSDavid du Colombier {
16*9a747e4fSDavid du Colombier 	int fd;
17*9a747e4fSDavid du Colombier 	Point d;
18*9a747e4fSDavid du Colombier 
19*9a747e4fSDavid du Colombier 	d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth));
20*9a747e4fSDavid du Colombier 	lockdisplay(display);
21*9a747e4fSDavid du Colombier 
22*9a747e4fSDavid du Colombier 	if(getwindow(display, Refnone) < 0)
23*9a747e4fSDavid du Colombier 		sysfatal("internal error: can't get the window image");
24*9a747e4fSDavid du Colombier 
25*9a747e4fSDavid du Colombier 	/*
26*9a747e4fSDavid du Colombier 	 * limit the window to at most the vnc server's size
27*9a747e4fSDavid du Colombier 	 */
28*9a747e4fSDavid du Colombier 	if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){
29*9a747e4fSDavid du Colombier 		fd = open("/dev/wctl", OWRITE);
30*9a747e4fSDavid du Colombier 		if(fd >= 0){
31*9a747e4fSDavid du Colombier 			fprint(fd, "resize -dx %d -dy %d", d.x, d.y);
32*9a747e4fSDavid du Colombier 			close(fd);
33*9a747e4fSDavid du Colombier 		}
34*9a747e4fSDavid du Colombier 	}
35*9a747e4fSDavid du Colombier 	unlockdisplay(display);
36*9a747e4fSDavid du Colombier }
37*9a747e4fSDavid du Colombier 
38*9a747e4fSDavid du Colombier static void
39*9a747e4fSDavid du Colombier eresized(void)
40*9a747e4fSDavid du Colombier {
41*9a747e4fSDavid du Colombier 	resize(vnc, 0);
42*9a747e4fSDavid du Colombier 
43*9a747e4fSDavid du Colombier 	requestupdate(vnc, 0);
44*9a747e4fSDavid du Colombier }
45*9a747e4fSDavid du Colombier 
46*9a747e4fSDavid du Colombier static Cursor dotcursor = {
47*9a747e4fSDavid du Colombier 	{-7, -7},
48*9a747e4fSDavid du Colombier 	{0x00, 0x00,
49*9a747e4fSDavid du Colombier 	 0x00, 0x00,
50*9a747e4fSDavid du Colombier 	 0x00, 0x00,
51*9a747e4fSDavid du Colombier 	 0x00, 0x00,
52*9a747e4fSDavid du Colombier 	 0x03, 0xc0,
53*9a747e4fSDavid du Colombier 	 0x07, 0xe0,
54*9a747e4fSDavid du Colombier 	 0x0f, 0xf0,
55*9a747e4fSDavid du Colombier 	 0x0f, 0xf0,
56*9a747e4fSDavid du Colombier 	 0x0f, 0xf0,
57*9a747e4fSDavid du Colombier 	 0x07, 0xe0,
58*9a747e4fSDavid du Colombier 	 0x03, 0xc0,
59*9a747e4fSDavid du Colombier 	 0x00, 0x00,
60*9a747e4fSDavid du Colombier 	 0x00, 0x00,
61*9a747e4fSDavid du Colombier 	 0x00, 0x00,
62*9a747e4fSDavid du Colombier 	 0x00, 0x00,
63*9a747e4fSDavid du Colombier 	 0x00, 0x00, },
64*9a747e4fSDavid du Colombier 	{0x00, 0x00,
65*9a747e4fSDavid du Colombier 	 0x00, 0x00,
66*9a747e4fSDavid du Colombier 	 0x00, 0x00,
67*9a747e4fSDavid du Colombier 	 0x00, 0x00,
68*9a747e4fSDavid du Colombier 	 0x00, 0x00,
69*9a747e4fSDavid du Colombier 	 0x03, 0xc0,
70*9a747e4fSDavid du Colombier 	 0x07, 0xe0,
71*9a747e4fSDavid du Colombier 	 0x07, 0xe0,
72*9a747e4fSDavid du Colombier 	 0x07, 0xe0,
73*9a747e4fSDavid du Colombier 	 0x03, 0xc0,
74*9a747e4fSDavid du Colombier 	 0x00, 0x00,
75*9a747e4fSDavid du Colombier 	 0x00, 0x00,
76*9a747e4fSDavid du Colombier 	 0x00, 0x00,
77*9a747e4fSDavid du Colombier 	 0x00, 0x00,
78*9a747e4fSDavid du Colombier 	 0x00, 0x00,
79*9a747e4fSDavid du Colombier 	 0x00, 0x00, }
80*9a747e4fSDavid du Colombier };
81*9a747e4fSDavid du Colombier 
82*9a747e4fSDavid du Colombier static void
83*9a747e4fSDavid du Colombier mouseevent(Vnc *v, Mouse m)
84*9a747e4fSDavid du Colombier {
85*9a747e4fSDavid du Colombier 	vnclock(v);
86*9a747e4fSDavid du Colombier 	vncwrchar(v, MMouse);
87*9a747e4fSDavid du Colombier 	vncwrchar(v, m.buttons);
88*9a747e4fSDavid du Colombier 	vncwrpoint(v, m.xy);
89*9a747e4fSDavid du Colombier 	vncflush(v);
90*9a747e4fSDavid du Colombier 	vncunlock(v);
91*9a747e4fSDavid du Colombier }
92*9a747e4fSDavid du Colombier 
93*9a747e4fSDavid du Colombier void mousewarp(Point pt)
94*9a747e4fSDavid du Colombier {
95*9a747e4fSDavid du Colombier 	char buf[49];
96*9a747e4fSDavid du Colombier 
97*9a747e4fSDavid du Colombier 	pt = addpt(pt, screen->r.min);
98*9a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "m%11d %11d ", pt.x, pt.y);
99*9a747e4fSDavid du Colombier 	write(mousefd, buf, 25);
100*9a747e4fSDavid du Colombier }
101*9a747e4fSDavid du Colombier 
102*9a747e4fSDavid du Colombier void initmouse(void)
103*9a747e4fSDavid du Colombier {
104*9a747e4fSDavid du Colombier 	char buf[1024];
105*9a747e4fSDavid du Colombier 
106*9a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/mouse", display->devdir);
107*9a747e4fSDavid du Colombier 	if((mousefd = open(buf, ORDWR)) < 0)
108*9a747e4fSDavid du Colombier 		sysfatal("open %s: %r", buf);
109*9a747e4fSDavid du Colombier }
110*9a747e4fSDavid du Colombier 
111*9a747e4fSDavid du Colombier enum {
112*9a747e4fSDavid du Colombier 	EventSize = 1+4*12
113*9a747e4fSDavid du Colombier };
114*9a747e4fSDavid du Colombier void
115*9a747e4fSDavid du Colombier readmouse(Vnc *v)
116*9a747e4fSDavid du Colombier {
117*9a747e4fSDavid du Colombier 	int cursorfd, len, n;
118*9a747e4fSDavid du Colombier 	char buf[10*EventSize], *start, *end;
119*9a747e4fSDavid du Colombier 	uchar curs[2*4+2*2*16];
120*9a747e4fSDavid du Colombier 	Cursor *cs;
121*9a747e4fSDavid du Colombier 	Mouse m;
122*9a747e4fSDavid du Colombier 
123*9a747e4fSDavid du Colombier 	cs = &dotcursor;
124*9a747e4fSDavid du Colombier 
125*9a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "%s/cursor", display->devdir);
126*9a747e4fSDavid du Colombier 	if((cursorfd = open(buf, OWRITE)) < 0)
127*9a747e4fSDavid du Colombier 		sysfatal("open %s: %r", buf);
128*9a747e4fSDavid du Colombier 
129*9a747e4fSDavid du Colombier 	BPLONG(curs+0*4, cs->offset.x);
130*9a747e4fSDavid du Colombier 	BPLONG(curs+1*4, cs->offset.y);
131*9a747e4fSDavid du Colombier 	memmove(curs+2*4, cs->clr, 2*2*16);
132*9a747e4fSDavid du Colombier 	write(cursorfd, curs, sizeof curs);
133*9a747e4fSDavid du Colombier 
134*9a747e4fSDavid du Colombier 	resize(v, 1);
135*9a747e4fSDavid du Colombier 	requestupdate(vnc, 0);
136*9a747e4fSDavid du Colombier 	start = end = buf;
137*9a747e4fSDavid du Colombier 	len = 0;
138*9a747e4fSDavid du Colombier 	for(;;) {
139*9a747e4fSDavid du Colombier 		if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
140*9a747e4fSDavid du Colombier 			sysfatal("read mouse failed");
141*9a747e4fSDavid du Colombier 
142*9a747e4fSDavid du Colombier 		len += n;
143*9a747e4fSDavid du Colombier 		end += n;
144*9a747e4fSDavid du Colombier 		while(len >= EventSize) {
145*9a747e4fSDavid du Colombier 			if(*start == 'm') {
146*9a747e4fSDavid du Colombier 				m.xy.x = atoi(start+1);
147*9a747e4fSDavid du Colombier 				m.xy.y = atoi(start+1+12);
148*9a747e4fSDavid du Colombier 				m.buttons = atoi(start+1+2*12) & 7;
149*9a747e4fSDavid du Colombier 				m.xy = subpt(m.xy, screen->r.min);
150*9a747e4fSDavid du Colombier 				if(ptinrect(m.xy, Rpt(ZP, v->dim)))
151*9a747e4fSDavid du Colombier 					mouseevent(v, m);
152*9a747e4fSDavid du Colombier 			} else
153*9a747e4fSDavid du Colombier 				eresized();
154*9a747e4fSDavid du Colombier 
155*9a747e4fSDavid du Colombier 			start += EventSize;
156*9a747e4fSDavid du Colombier 			len -= EventSize;
157*9a747e4fSDavid du Colombier 		}
158*9a747e4fSDavid du Colombier 		if(start - buf > sizeof(buf) - EventSize) {
159*9a747e4fSDavid du Colombier 			memmove(buf, start, len);
160*9a747e4fSDavid du Colombier 			start = buf;
161*9a747e4fSDavid du Colombier 			end = start+len;
162*9a747e4fSDavid du Colombier 		}
163*9a747e4fSDavid du Colombier 	}
164*9a747e4fSDavid du Colombier }
165*9a747e4fSDavid du Colombier 
166*9a747e4fSDavid du Colombier static int snarffd = -1;
167*9a747e4fSDavid du Colombier static ulong snarf_vers;
168*9a747e4fSDavid du Colombier 
169*9a747e4fSDavid du Colombier void
170*9a747e4fSDavid du Colombier writesnarf(Vnc *v, long n)
171*9a747e4fSDavid du Colombier {
172*9a747e4fSDavid du Colombier 	uchar buf[8192];
173*9a747e4fSDavid du Colombier 	long m;
174*9a747e4fSDavid du Colombier 	Biobuf * fd;
175*9a747e4fSDavid du Colombier 
176*9a747e4fSDavid du Colombier 	if( (fd = Bopen("/dev/snarf", OWRITE)) == nil ) {
177*9a747e4fSDavid du Colombier 		vncgobble(v, n);
178*9a747e4fSDavid du Colombier 		return;
179*9a747e4fSDavid du Colombier 	}
180*9a747e4fSDavid du Colombier 
181*9a747e4fSDavid du Colombier 	while(n > 0) {
182*9a747e4fSDavid du Colombier 		m = n;
183*9a747e4fSDavid du Colombier 		if(m > sizeof(buf))
184*9a747e4fSDavid du Colombier 			m = sizeof(buf);
185*9a747e4fSDavid du Colombier 		vncrdbytes(v, buf, m);
186*9a747e4fSDavid du Colombier 		n -= m;
187*9a747e4fSDavid du Colombier 
188*9a747e4fSDavid du Colombier 		Bwrite(fd, buf, m);
189*9a747e4fSDavid du Colombier 	}
190*9a747e4fSDavid du Colombier 	Bterm(fd);
191*9a747e4fSDavid du Colombier 	snarf_vers++;
192*9a747e4fSDavid du Colombier }
193*9a747e4fSDavid du Colombier 
194*9a747e4fSDavid du Colombier char *
195*9a747e4fSDavid du Colombier getsnarf(int * sz)
196*9a747e4fSDavid du Colombier {
197*9a747e4fSDavid du Colombier 	char * snarf, * p;
198*9a747e4fSDavid du Colombier 	int n, c;
199*9a747e4fSDavid du Colombier 
200*9a747e4fSDavid du Colombier 	*sz =0;
201*9a747e4fSDavid du Colombier 	n = 8192;
202*9a747e4fSDavid du Colombier 	p = snarf = malloc(n);
203*9a747e4fSDavid du Colombier 
204*9a747e4fSDavid du Colombier 	seek(snarffd, 0, 0);
205*9a747e4fSDavid du Colombier 	while ((c = read(snarffd, p, n)) > 0) {
206*9a747e4fSDavid du Colombier 		p += c;
207*9a747e4fSDavid du Colombier 		n -= c;
208*9a747e4fSDavid du Colombier 		*sz += c;
209*9a747e4fSDavid du Colombier 		if ( n == 0 ) {
210*9a747e4fSDavid du Colombier 			snarf = realloc(snarf, *sz + 8192);
211*9a747e4fSDavid du Colombier 			n = 8192;
212*9a747e4fSDavid du Colombier 		}
213*9a747e4fSDavid du Colombier 	}
214*9a747e4fSDavid du Colombier 	return snarf;
215*9a747e4fSDavid du Colombier }
216*9a747e4fSDavid du Colombier 
217*9a747e4fSDavid du Colombier void
218*9a747e4fSDavid du Colombier checksnarf(Vnc *v)
219*9a747e4fSDavid du Colombier {
220*9a747e4fSDavid du Colombier 	Dir *dir;
221*9a747e4fSDavid du Colombier 	char *snarf;
222*9a747e4fSDavid du Colombier 	int len;
223*9a747e4fSDavid du Colombier 
224*9a747e4fSDavid du Colombier 	if(snarffd < 0){
225*9a747e4fSDavid du Colombier 		snarffd = open("/dev/snarf", OREAD);
226*9a747e4fSDavid du Colombier 		if(snarffd < 0)
227*9a747e4fSDavid du Colombier 			sysfatal("can't open /dev/snarf: %r");
228*9a747e4fSDavid du Colombier 	}
229*9a747e4fSDavid du Colombier 
230*9a747e4fSDavid du Colombier 	while(1) {
231*9a747e4fSDavid du Colombier 		sleep(1000);
232*9a747e4fSDavid du Colombier 
233*9a747e4fSDavid du Colombier 		dir = dirstat("/dev/snarf");
234*9a747e4fSDavid du Colombier 		if(dir == nil)	/* this happens under old drawterm */
235*9a747e4fSDavid du Colombier 			continue;
236*9a747e4fSDavid du Colombier 		if(dir->qid.vers > snarf_vers) {
237*9a747e4fSDavid du Colombier 			snarf = getsnarf(&len);
238*9a747e4fSDavid du Colombier 
239*9a747e4fSDavid du Colombier 			vnclock(v);
240*9a747e4fSDavid du Colombier 			vncwrchar(v, MCCut);
241*9a747e4fSDavid du Colombier 			vncwrbytes(v, "pad", 3);
242*9a747e4fSDavid du Colombier 			vncwrlong(v, len);
243*9a747e4fSDavid du Colombier 			vncwrbytes(v, snarf, len);
244*9a747e4fSDavid du Colombier 			vncflush(v);
245*9a747e4fSDavid du Colombier 			vncunlock(v);
246*9a747e4fSDavid du Colombier 
247*9a747e4fSDavid du Colombier 			free(snarf);
248*9a747e4fSDavid du Colombier 
249*9a747e4fSDavid du Colombier 			snarf_vers = dir->qid.vers;
250*9a747e4fSDavid du Colombier 		}
251*9a747e4fSDavid du Colombier 		free(dir);
252*9a747e4fSDavid du Colombier 	}
253*9a747e4fSDavid du Colombier }
254