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