!752 p { serveHttp(7799); } static int lastImageSize; static RGBImage lastImage; static S lastImageID; static BufferedImage diff; // TODO: better auth check static synchronized NanoHTTPD.Response serve(S uri, NanoHTTPD.Method method, Map header, Map parms, Map files) ctex { if (eq(uri, "/favicon.ico")) ret serveHTML(""); // who cares S pw = trim(loadSecretTextFile("vnc-pw")); if (nempty(pw)) assertEq(pw, parms.get("pw")); if (eq(uri, "/mouse")) { int x = toInt(parms.get("x")); int y = toInt(parms.get("y")); S type = parms.get("type"); print("Mouse event! " + type + " " + x + " " + y); new Robot robot; robot.mouseMove(x, y); if (eq(type, "down")) robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); else if (eq(type, "up")) { sleepSeconds(0.1); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } ret serveHTML(""); } if (eq(uri, "/diff.png")) { byte[] data = convertToPNG(diff); ret NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Status.OK, "image/png", new ByteArrayInputStream(data), l(data)); } if (eq(uri, "/image.png")) { BufferedImage img = shootScreen2(); lastImage = new RGBImage(img); lastImageID = randomID(10); byte[] data = convertToPNG(img); lastImageSize = l(data); ret NanoHTTPD.newFixedLengthResponse(NanoHTTPD.Status.OK, "image/png", new ByteArrayInputStream(data), l(data)); } if (eq(uri, "/diff")) { S lastID = parms.get("lastid"); if (eq(lastID, lastImageID)) { // todo: serve diff BufferedImage img = shootScreen2(); RGBImage image = new RGBImage(img); Rectangle r = findDiffArea(lastImage, image); if (r.width <= 0 && r.height <= 0) ret serveHTML("no change"); diff = image.clip(r).getBufferedImage(); lastImage = image; lastImageID = randomID(10); ret serveHTML(r.x + " " + r.y + " " + r.width + " " + r.height + lastImageID); } ret serveHTML("full"); } print("Serving HTML."); S html = htitle("Mini-VNC") + hjavascript([[ function httpGetAsync(theUrl, callback) { var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) if (callback != null) callback(xmlHttp.responseText); } xmlHttp.open("GET", theUrl, true); // true for asynchronous xmlHttp.send(null); } function FindPosition(oElement) { if (typeof(oElement.offsetParent) != "undefined") { for(var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent) { posX += oElement.offsetLeft; posY += oElement.offsetTop; } return [ posX, posY ]; } else { return [ oElement.x, oElement.y ]; } } function sendMouse(e, type) { var PosX = 0; var PosY = 0; var ImgPos; ImgPos = FindPosition(myImg); if (!e) var e = window.event; if (e.pageX || e.pageY) { PosX = e.pageX; PosY = e.pageY; } else if (e.clientX || e.clientY) { PosX = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; PosY = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } PosX = PosX - ImgPos[0]; PosY = PosY - ImgPos[1]; httpGetAsync("/mouse?pw=$PW$&type=" + type + "&x=" + PosX + "&y=" + PosY, null); if (type == "up") setTimeout(function() { thescreen.src = "image.png?pw=$PW$&_=" + new Date().getTime(); }, 1000); //document.getElementById("y").innerHTML = PosY; } ]].replace("$PW$", urlencode(pw))) + himg("image.png?pw=" + urlencode(pw), "id", "thescreen") + hjavascript([[ var myImg = document.getElementById("thescreen"); myImg.ondragstart = function() { return false; }; //myImg.onmouseover = GetCoordinates; myImg.onmousemove = function(e) {}; myImg.onmousedown = function(e) { sendMouse(e, "down"); }; myImg.onmouseup = function(e) { sendMouse(e, "up"); }; ]]) + (lastImageSize == 0 ? "" : "

Last image size: " + toK(lastImageSize) + "K"); ret serveHTML(html); } static Rectangle findDiffArea(RGBImage a, RGBImage b) { int w = a.getWidth(), h = a.getHeight(); int x1 = 0, y1 = 0, x2 = w, y2 = h; // left side out0: while (x1 < x2) { for (int y=y1; y < y2; y++) if (different(a, b, x1, y)) break out0; ++x1; } // top side out1: while (y1 < y2) { for (int x=x1; x < x2; x++) if (different(a, b, x, y1)) break out1; ++y1; } // right side out2: while (x2 > x1) { for (int y=y1; y < y2; y++) if (different(a, b, x2-1, y)) break out2; --x2; } // bottom side out3: while (y2 > y1) { for (int x=x1; x < x2; x++) if (different(a, b, x, y2-1)) break out3; --y2; } ret new Rectangle(x1, y1, x2-x1, y2-y1); } static bool different(RGBImage a, RGBImage b, int x, int y) { ret a.getInt(x, y) != b.getInt(x, y); }