+/* Helper functions for debugging */
+var logDiv = null;
+function log(str) {
+ if (!logDiv) {
+ logDiv = document.createElement('div');
+ document.body.appendChild(logDiv);
+ logDiv.style["position"] = "absolute";
+ logDiv.style["right"] = "0px";
+ }
+ logDiv.appendChild(document.createTextNode(str));
+ logDiv.appendChild(document.createElement('br'));
+}
-var base64_val = [
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
- 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
- 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
+var base64Values = [
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255,
+ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255
]
function base64_8(str, index) {
- var v =
- (base64_val[str.charCodeAt(index)]) +
- (base64_val[str.charCodeAt(index+1)] << 6);
- return v;
+ var v =
+ (base64Values[str.charCodeAt(index)]) +
+ (base64Values[str.charCodeAt(index+1)] << 6);
+ return v;
}
function base64_16(str, index) {
- var v =
- (base64_val[str.charCodeAt(index)]) +
- (base64_val[str.charCodeAt(index+1)] << 6) +
- (base64_val[str.charCodeAt(index+2)] << 12);
- return v;
+ var v =
+ (base64Values[str.charCodeAt(index)]) +
+ (base64Values[str.charCodeAt(index+1)] << 6) +
+ (base64Values[str.charCodeAt(index+2)] << 12);
+ return v;
}
function base64_16s(str, index) {
- var v = base64_16(str, index);
- if (v > 32767)
- return v - 65536;
- else
- return v;
+ var v = base64_16(str, index);
+ if (v > 32767)
+ return v - 65536;
+ else
+ return v;
}
function base64_24(str, index) {
- var v =
- (base64_val[str.charCodeAt(index)]) +
- (base64_val[str.charCodeAt(index+1)] << 6) +
- (base64_val[str.charCodeAt(index+2)] << 12) +
- (base64_val[str.charCodeAt(index+3)] << 18);
- return v;
+ var v =
+ (base64Values[str.charCodeAt(index)]) +
+ (base64Values[str.charCodeAt(index+1)] << 6) +
+ (base64Values[str.charCodeAt(index+2)] << 12) +
+ (base64Values[str.charCodeAt(index+3)] << 18);
+ return v;
}
function base64_32(str, index) {
- var v =
- (base64_val[str.charCodeAt(index)]) +
- (base64_val[str.charCodeAt(index+1)] << 6) +
- (base64_val[str.charCodeAt(index+2)] << 12) +
- (base64_val[str.charCodeAt(index+3)] << 18) +
- (base64_val[str.charCodeAt(index+4)] << 24) +
- (base64_val[str.charCodeAt(index+5)] << 30);
- return v;
+ var v =
+ (base64Values[str.charCodeAt(index)]) +
+ (base64Values[str.charCodeAt(index+1)] << 6) +
+ (base64Values[str.charCodeAt(index+2)] << 12) +
+ (base64Values[str.charCodeAt(index+3)] << 18) +
+ (base64Values[str.charCodeAt(index+4)] << 24) +
+ (base64Values[str.charCodeAt(index+5)] << 30);
+ return v;
}
function createXHR()
{
- try { return new XMLHttpRequest(); } catch(e) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
- try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
- try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
+ try { return new XMLHttpRequest(); } catch(e) {}
+ try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
+ try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
+ try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
+ try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
- return null;
+ return null;
}
+var grab = new Object();
+grab.window = null;
+grab.ownerEvents = false;
+grab.implicit = false;
+var lastSerial = 0;
+var lastX = 0;
+var lastY = 0;
+var lastState;
+var lastTimeStamp = 0;
+var realWindowWithMouse = 0;
+var windowWithMouse = 0;
var surfaces = {};
-var outstanding_commands = new Array();
+var outstandingCommands = new Array();
+var inputSocket = null;
+
+var GDK_CROSSING_NORMAL = 0;
+var GDK_CROSSING_GRAB = 1;
+var GDK_CROSSING_UNGRAB = 2;
+
+// GdkModifierType
+var GDK_SHIFT_MASK = 1 << 0;
+var GDK_LOCK_MASK = 1 << 1;
+var GDK_CONTROL_MASK = 1 << 2;
+var GDK_MOD1_MASK = 1 << 3;
+var GDK_MOD2_MASK = 1 << 4;
+var GDK_MOD3_MASK = 1 << 5;
+var GDK_MOD4_MASK = 1 << 6;
+var GDK_MOD5_MASK = 1 << 7;
+var GDK_BUTTON1_MASK = 1 << 8;
+var GDK_BUTTON2_MASK = 1 << 9;
+var GDK_BUTTON3_MASK = 1 << 10;
+var GDK_BUTTON4_MASK = 1 << 11;
+var GDK_BUTTON5_MASK = 1 << 12;
+var GDK_SUPER_MASK = 1 << 26;
+var GDK_HYPER_MASK = 1 << 27;
+var GDK_META_MASK = 1 << 28;
+var GDK_RELEASE_MASK = 1 << 30;
+
+function getButtonMask (button) {
+ if (button == 1)
+ return GDK_BUTTON1_MASK;
+ if (button == 2)
+ return GDK_BUTTON2_MASK;
+ if (button == 3)
+ return GDK_BUTTON3_MASK;
+ if (button == 4)
+ return GDK_BUTTON4_MASK;
+ if (button == 5)
+ return GDK_BUTTON5_MASK;
+ return 0;
+}
-function apply_delta(id, img, x, y)
+function flushSurface(surface)
{
- var tmp_surface = document.createElement("canvas");
- var w = img.width;
- var h = img.height;
- tmp_surface.width = w;
- tmp_surface.height = h;
-
- tmp_context = tmp_surface.getContext("2d");
- tmp_context.drawImage(img, 0, 0);
-
- var data = surfaces[id].getImageData(x, y, w, h);
- var d = data.data
- var delta = tmp_context.getImageData(0, 0, w, h).data;
- var imax = w * h * 4;
- for (var i = 0; i < imax; i += 4) {
- d[i ] = (d[i ] + delta[i ]) & 0xff;
- d[i+1] = (d[i+1] + delta[i+1]) & 0xff;
- d[i+2] = (d[i+2] + delta[i+2]) & 0xff;
- d[i+3] = 255;
- }
- surfaces[id].putImageData(data, x, y);
- delete tmp_surface
-}
-
-function initContext(canvas, x, y)
+ var commands = surface.drawQueue;
+ surface.queue = [];
+ var context = surface.context;
+ var i = 0;
+ for (i = 0; i < commands.length; i++) {
+ var cmd = commands[i];
+ switch (cmd.op) {
+ case 'i': // put image data surface
+ context.globalCompositeOperation = "source-over";
+ context.drawImage(cmd.img, cmd.x, cmd.y);
+ break;
+
+ case 'b': // copy rects
+ context.save();
+ context.beginPath();
+
+ var minx;
+ var miny;
+ var maxx;
+ var maxy;
+ for (var j = 0; j < cmd.rects.length; j++) {
+ var rect = cmd.rects[j];
+ context.rect(rect.x, rect.y, rect.w, rect.h);
+ if (j == 0) {
+ minx = rect.x;
+ miny = rect.y;
+ maxx = rect.x + rect.w;
+ maxy = rect.y + rect.h;
+ } else {
+ if (rect.x < minx)
+ minx = rect.x;
+ if (rect.y < miny)
+ miny = rect.y;
+ if (rect.x + rect.w > maxx)
+ maxx = rect.x + rect.w;
+ if (rect.y + rect.h > maxy)
+ maxy = rect.y + rect.h;
+ }
+ }
+ context.clip();
+ context.globalCompositeOperation = "copy";
+ context.drawImage(context.canvas,
+ minx - cmd.dx, miny - cmd.dy, maxx - minx, maxy - miny,
+ minx, miny, maxx - minx, maxy - miny);
+ context.restore();
+ break;
+
+ default:
+ alert("Unknown drawing op " + cmd.op);
+ }
+ }
+}
+
+function cmdCreateSurface(id, x, y, width, height, isTemp)
{
- canvas.style["position"] = "absolute"
- canvas.style["top"] = x + "px"
- canvas.style["left"] = y + "px"
- canvas.style["display"] = "none"
- context = canvas.getContext("2d")
- context.globalCompositeOperation = "copy"
- context.fillRect(0, 0, canvas.width, canvas.height);
- document.body.appendChild(canvas)
- return context
-}
-
-function handleCommands(cmd_obj)
+ var surface = { id: id, x: x, y:y, width: width, height: height, isTemp: isTemp };
+ surface.drawQueue = [];
+ surface.transientParent = 0;
+
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ canvas.surface = surface;
+ canvas.style["position"] = "absolute";
+ canvas.style["left"] = x + "px";
+ canvas.style["top"] = y + "px";
+ canvas.style["display"] = "none";
+ document.body.appendChild(canvas);
+ surface.canvas = canvas;
+
+ var context = canvas.getContext("2d");
+ context.globalCompositeOperation = "source-over";
+ surface.context = context;
+
+ surfaces[id] = surface;
+}
+
+function cmdShowSurface(id)
{
- var cmd = cmd_obj.data;
- var i = cmd_obj.pos;
-
- while (i < cmd.length) {
- var command = cmd[i++];
- switch (command) {
- /* create new surface */
- case 's':
- var id = base64_16(cmd, i);
- i = i + 3;
- var x = base64_16(cmd, i);
- i = i + 3;
- var y = base64_16(cmd, i);
- i = i + 3;
- var w = base64_16(cmd, i);
- i = i + 3;
- var h = base64_16(cmd, i);
- i = i + 3;
- var surface = document.createElement("canvas");
- surface.width = w;
- surface.height = h;
- surfaces[id] = initContext(surface, x, y);
- break;
-
- /* show a surface */
- case 'S':
- var id = base64_16(cmd, i);
- i = i + 3;
- surfaces[id].canvas.style["display"] = "inline";
- break;
-
- /* hide a surface */
- case 'H':
- var id = base64_16(cmd, i);
- i = i + 3;
- surfaces[id].canvas.style["display"] = "inline";
- break;
-
- /* delete surface */
- case 'd':
- var id = base64_16(cmd, i);
- i = i + 3;
- var canvas = surfaces[id].canvas
- delete surfaces[id]
- canvas.parentNode.removeChild(canvas);
-
- break;
-
- /* move a surface */
- case 'm':
- var id = base64_16(cmd, i);
- i = i + 3;
- var x = base64_16(cmd, i);
- i = i + 3;
- var y = base64_16(cmd, i);
- i = i + 3;
- surfaces[id].canvas.style["left"] = x + "px";
- surfaces[id].canvas.style["top"] = y + "px";
- break;
-
- /* put image data surface */
- case 'i':
- var id = base64_16(cmd, i);
- i = i + 3;
- var x = base64_16(cmd, i);
- i = i + 3;
- var y = base64_16(cmd, i);
- i = i + 3;
- var size = base64_32(cmd, i);
- i = i + 6;
- var url = cmd.slice(i, i + size);
- i = i + size;
- var img = new Image();
- img.src = url
- if (img.complete) {
- surfaces[id].drawImage(img, x, y);
- } else {
- cmd_obj.pos = i;
- img.onload = function() { surfaces[id].drawImage(img, x, y); handleOutstanding(); }
- return false
- }
+ surfaces[id].canvas.style["display"] = "inline";
+}
- break;
-
- /* put delta image data surface */
- case 'D':
- var id = base64_16(cmd, i);
- i = i + 3;
- var x = base64_16(cmd, i);
- i = i + 3;
- var y = base64_16(cmd, i);
- i = i + 3;
- var size = base64_32(cmd, i);
- i = i + 6;
- var url = cmd.slice(i, i + size);
- i = i + size;
- var img = new Image();
- img.src = url
- if (img.complete) {
- apply_delta(id, img, x, y);
- } else {
- cmd_obj.pos = i;
- img.onload = function() { apply_delta(id, img, x, y); handleOutstanding(); }
- return false
- }
+function cmdHideSurface(id)
+{
+ surfaces[id].canvas.style["display"] = "none";
+}
- break;
-
- /* copy rects */
- case 'b':
- var id = base64_16(cmd, i);
- i = i + 3;
-
- var nrects = base64_16(cmd, i);
- i = i + 3;
-
- var context = surfaces[id];
- context.save();
-
- for (var r = 0; r < nrects; r++) {
- var x = base64_16(cmd, i);
- i = i + 3;
- var y = base64_16(cmd, i);
- i = i + 3;
- var w = base64_16(cmd, i);
- i = i + 3;
- var h = base64_16(cmd, i);
- i = i + 3;
- context.rect(x, y, w, h);
- }
+function cmdSetTransientFor(id, parentId)
+{
+ surfaces[id].transientParent = parentId;
+}
+
+function cmdDeleteSurface(id)
+{
+ var canvas = surfaces[id].canvas;
+ delete surfaces[id];
+ canvas.parentNode.removeChild(canvas);
+}
+
+function cmdMoveSurface(id, x, y)
+{
+ surfaces[id].canvas.style["left"] = x + "px";
+ surfaces[id].canvas.style["top"] = y + "px";
+}
+
+function cmdResizeSurface(id, w, h)
+{
+ var surface = surfaces[id];
+
+ /* Flush any outstanding draw ops before changing size */
+ flushSurface(surface);
- context.clip()
+ /* Canvas resize clears the data, so we need to save it first */
+ var tmpCanvas = document.createElement("canvas");
+ tmpCanvas.width = surface.canvas.width;
+ tmpCanvas.height = surface.canvas.height;
+ var tmpContext = tmpCanvas.getContext("2d");
+ tmpContext.globalCompositeOperation = "copy";
+ tmpContext.drawImage(surface.canvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
+
+ surface.canvas.width = w;
+ surface.canvas.height = h;
+
+ surface.context.globalCompositeOperation = "copy";
+ surface.context.drawImage(tmpCanvas, 0, 0, tmpCanvas.width, tmpCanvas.height);
+}
- var dx = base64_16s(cmd, i);
- i = i + 3;
- var dy = base64_16s(cmd, i);
- i = i + 3;
+function cmdFlushSurface(id)
+{
+ flushSurface(surfaces[id]);
+}
- context.drawImage(context.canvas, dx, dy, context.canvas.width, context.canvas.height);
+function cmdGrabPointer(id, ownerEvents)
+{
+ doGrab(id, ownerEvents, false);
+ sendInput ("g", []);
+}
- context.restore();
- break;
+function cmdUngrabPointer()
+{
+ sendInput ("u", []);
- default:
- alert("Unknown op " + command);
+ if (grab.window != null) {
+ if (grab.time == 0 || time == 0 ||
+ grab.time < time)
+ grab.window = null;
}
- }
- return true;
+}
+
+function handleCommands(cmdObj)
+{
+ var cmd = cmdObj.data;
+ var i = cmdObj.pos;
+
+ while (i < cmd.length) {
+ var command = cmd[i++];
+ lastSerial = base64_32(cmd, i);
+ i = i + 6;
+ switch (command) {
+ case 's': // create new surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var x = base64_16(cmd, i);
+ i = i + 3;
+ var y = base64_16(cmd, i);
+ i = i + 3;
+ var w = base64_16(cmd, i);
+ i = i + 3;
+ var h = base64_16(cmd, i);
+ i = i + 3;
+ var isTemp = cmd[i] == '1';
+ i = i + 1;
+ cmdCreateSurface(id, x, y, w, h, isTemp);
+ break;
+
+ case 'S': // Show a surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ cmdShowSurface(id);
+ break;
+
+ case 'H': // Hide a surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ cmdHideSurface(id);
+ break;
+
+ case 'p': // Set transient parent
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var parentId = base64_16(cmd, i);
+ i = i + 3;
+ cmdSetTransientFor(id, parentId);
+ break;
+
+ case 'd': // Delete surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ cmdDeleteSurface(id);
+ break;
+
+ case 'm': // Move a surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var x = base64_16(cmd, i);
+ i = i + 3;
+ var y = base64_16(cmd, i);
+ i = i + 3;
+ cmdMoveSurface(id, x, y);
+ break;
+
+ case 'r': // Resize a surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var w = base64_16(cmd, i);
+ i = i + 3;
+ var h = base64_16(cmd, i);
+ i = i + 3;
+ cmdResizeSurface(id, w, h);
+ break;
+
+ case 'i': // Put image data surface
+ var q = new Object();
+ q.op = 'i';
+ q.id = base64_16(cmd, i);
+ i = i + 3;
+ q.x = base64_16(cmd, i);
+ i = i + 3;
+ q.y = base64_16(cmd, i);
+ i = i + 3;
+ var size = base64_32(cmd, i);
+ i = i + 6;
+ var url = cmd.slice(i, i + size);
+ i = i + size;
+ q.img = new Image();
+ q.img.src = url;
+ surfaces[q.id].drawQueue.push(q);
+ if (!q.img.complete) {
+ cmdObj.pos = i;
+ q.img.onload = function() { handleOutstanding(); };
+ return false;
+ }
+ break;
+
+ case 'b': // Copy rects
+ var q = new Object();
+ q.op = 'b';
+ q.id = base64_16(cmd, i);
+ i = i + 3;
+
+ var nrects = base64_16(cmd, i);
+ i = i + 3;
+
+ q.rects = [];
+ for (var r = 0; r < nrects; r++) {
+ var rect = new Object();
+ rect.x = base64_16(cmd, i);
+ i = i + 3;
+ rect.y = base64_16(cmd, i);
+ i = i + 3;
+ rect.w = base64_16(cmd, i);
+ i = i + 3;
+ rect.h = base64_16(cmd, i);
+ i = i + 3;
+ q.rects.push (rect);
+ }
+
+ q.dx = base64_16s(cmd, i);
+ i = i + 3;
+ q.dy = base64_16s(cmd, i);
+ i = i + 3;
+ surfaces[q.id].drawQueue.push(q);
+ break;
+
+ case 'f': // Flush surface
+ var id = base64_16(cmd, i);
+ i = i + 3;
+
+ cmdFlushSurface(id);
+ break;
+
+ case 'g': // Grab
+ var id = base64_16(cmd, i);
+ i = i + 3;
+ var ownerEvents = cmd[i++] == '1';
+
+ cmdGrabPointer(id, ownerEvents);
+ break;
+
+ case 'u': // Ungrab
+ cmdUngrabPointer();
+ break;
+ default:
+ alert("Unknown op " + command);
+ }
+ }
+ return true;
}
function handleOutstanding()
{
- while (outstanding_commands.length > 0) {
- var cmd = outstanding_commands.shift();
- if (!handleCommands(cmd)) {
- outstanding_commands.unshift(cmd);
- return;
+ while (outstandingCommands.length > 0) {
+ var cmd = outstandingCommands.shift();
+ if (!handleCommands(cmd)) {
+ outstandingCommands.unshift(cmd);
+ return;
+ }
}
- }
}
function handleLoad(event)
{
- var cmd_obj = {};
- cmd_obj.data = event.target.responseText;
- cmd_obj.pos = 0;
+ var cmdObj = {};
+ cmdObj.data = event.target.responseText;
+ cmdObj.pos = 0;
+
+ outstandingCommands.push(cmdObj);
+ if (outstandingCommands.length == 1) {
+ handleOutstanding();
+ }
+}
- outstanding_commands.push(cmd_obj);
- if (outstanding_commands.length == 1) {
- handleOutstanding()
- }
+function getSurfaceId(ev) {
+ var surface = ev.target.surface;
+ if (surface != undefined)
+ return surface.id;
+ return 0;
}
-function connect(app)
+function sendInput(cmd, args)
{
- var xhr = createXHR();
- if (xhr) {
- if (typeof xhr.multipart == 'undefined') {
- alert("Sorry, this example only works in browsers that support multipart.");
- return;
+ if (inputSocket != null) {
+ inputSocket.send(cmd + ([lastSerial, lastTimeStamp].concat(args)).join(","));
+ }
+}
+
+function getDocumentCoordinates(element)
+{
+ var res = new Object();
+ res.x = element.offsetLeft;
+ res.y = element.offsetTop;
+
+ var offsetParent = element.offsetParent;
+ while (offsetParent != null) {
+ res.x += offsetParent.offsetLeft;
+ res.y += offsetParent.offsetTop;
+ offsetParent = offsetParent.offsetParent;
+ }
+ return res;
+}
+
+function getPositionsFromAbsCoord(absX, absY, relativeId) {
+ var res = Object();
+
+ res.rootX = absX;
+ res.rootY = absY;
+ res.winX = absX;
+ res.winY = absY;
+ if (relativeId != 0) {
+ var pos = getDocumentCoordinates(surfaces[relativeId].canvas);
+ res.winX = res.winX - pos.x;
+ res.winY = res.winY - pos.y;
+ }
+
+ return res;
+}
+
+function getPositionsFromEvent(ev, relativeId) {
+ var res = getPositionsFromAbsCoord(ev.pageX, ev.pageY, relativeId);
+
+ lastX = res.rootX;
+ lastY = res.rootY;
+
+ return res;
+}
+
+function getEffectiveEventTarget (id) {
+ if (grab.window != null) {
+ if (!grab.ownerEvents)
+ return grab.window;
+ if (id == 0)
+ return grab.window;
+ }
+ return id;
+}
+
+function updateForEvent(ev) {
+ lastTimeStamp = ev.timeStamp;
+}
+
+function onMouseMove (ev) {
+ updateForEvent(ev);
+ var id = getSurfaceId(ev);
+ id = getEffectiveEventTarget (id);
+ var pos = getPositionsFromEvent(ev, id);
+ sendInput ("m", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState]);
+}
+
+function onMouseOver (ev) {
+ updateForEvent(ev);
+ var id = getSurfaceId(ev);
+ realWindowWithMouse = id;
+ id = getEffectiveEventTarget (id);
+ var pos = getPositionsFromEvent(ev, id);
+ windowWithMouse = id;
+ if (windowWithMouse != 0) {
+ sendInput ("e", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_NORMAL]);
+ }
+}
+
+function onMouseOut (ev) {
+ updateForEvent(ev);
+ var id = getSurfaceId(ev);
+ var origId = id;
+ id = getEffectiveEventTarget (id);
+ var pos = getPositionsFromEvent(ev, id);
+
+ if (id != 0) {
+ sendInput ("l", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_NORMAL]);
+ }
+ realWindowWithMouse = 0;
+ windowWithMouse = 0;
+}
+
+function doGrab(id, ownerEvents, implicit) {
+ var pos;
+
+ if (windowWithMouse != id) {
+ if (windowWithMouse != 0) {
+ pos = getPositionsFromAbsCoord(lastX, lastY, windowWithMouse);
+ sendInput ("l", [realWindowWithMouse, windowWithMouse, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_GRAB]);
+ }
+ pos = getPositionsFromAbsCoord(lastX, lastY, id);
+ sendInput ("e", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_GRAB]);
+ windowWithMouse = id;
+ }
+
+ grab.window = id;
+ grab.ownerEvents = ownerEvents;
+ grab.implicit = implicit;
+}
+
+function doUngrab() {
+ var pos;
+ if (realWindowWithMouse != windowWithMouse) {
+ if (windowWithMouse != 0) {
+ pos = getPositionsFromAbsCoord(lastX, lastY, windowWithMouse);
+ sendInput ("l", [realWindowWithMouse, windowWithMouse, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_UNGRAB]);
+ }
+ if (realWindowWithMouse != 0) {
+ pos = getPositionsFromAbsCoord(lastX, lastY, realWindowWithMouse);
+ sendInput ("e", [realWindowWithMouse, realWindowWithMouse, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, GDK_CROSSING_UNGRAB]);
+ }
+ windowWithMouse = realWindowWithMouse;
+ }
+ grab.window = null;
+}
+
+function onMouseDown (ev) {
+ updateForEvent(ev);
+ var id = getSurfaceId(ev);
+ id = getEffectiveEventTarget (id);
+ var pos = getPositionsFromEvent(ev, id);
+ if (grab.window != null)
+ doGrab (id, false, true);
+ var button = ev.button + 1;
+ lastState = lastState | getButtonMask (button);
+ sendInput ("b", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, button]);
+}
+
+function onMouseUp (ev) {
+ updateForEvent(ev);
+ var id = getSurfaceId(ev);
+ id = getEffectiveEventTarget (id);
+ var pos = getPositionsFromEvent(ev, id);
+ var button = ev.button + 1;
+ lastState = lastState & ~getButtonMask (button);
+ sendInput ("B", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, button]);
+
+ if (grab.window != null && grab.implicit)
+ doUngrab(ev.timeStamp);
+}
+
+var lastKeyDown = 0;
+function onKeyDown (ev) {
+ updateForEvent(ev);
+ var keyCode = ev.keyCode;
+ if (keyCode != lastKeyDown) {
+ sendInput ("k", [keyCode]);
+ lastKeyDown = keyCode;
}
+}
- xhr.multipart = true;
- xhr.open("GET", "/cgi-bin/" + app, true);
- xhr.onload = handleLoad;
- xhr.send(null);
- }
+function onKeyUp (ev) {
+ updateForEvent(ev);
+ var keyCode = ev.keyCode;
+ sendInput ("K", [keyCode]);
+ lastKeyDown = 0;
}
-function startClient(app)
+function cancelEvent(ev)
{
- connect(app);
+ ev = ev ? ev : window.event;
+ if (ev.stopPropagation)
+ ev.stopPropagation();
+ if (ev.preventDefault)
+ ev.preventDefault();
+ ev.cancelBubble = true;
+ ev.cancel = true;
+ ev.returnValue = false;
+ return false;
+}
+
+function onMouseWheel(ev)
+{
+ updateForEvent(ev);
+ ev = ev ? ev : window.event;
+
+ var id = getSurfaceId(ev);
+ var pos = getPositionsFromEvent(ev, id);
+
+ var offset = ev.detail ? ev.detail : ev.wheelDelta;
+ var dir = 0;
+ if (offset > 0)
+ dir = 1;
+ sendInput ("s", [realWindowWithMouse, id, pos.rootX, pos.rootY, pos.winX, pos.winY, lastState, dir]);
+
+ return cancelEvent(ev);
+}
+
+function connect()
+{
+ var xhr = createXHR();
+ if (xhr) {
+ if (typeof xhr.multipart == 'undefined') {
+ alert("Sorry, this example only works in browsers that support multipart.");
+ return;
+ }
+
+ xhr.multipart = true;
+ xhr.open("GET", "/output", true);
+ xhr.onload = handleLoad;
+ xhr.send(null);
+ }
+
+ if ("WebSocket" in window) {
+ var loc = window.location.toString().replace("http:", "ws:");
+ loc = loc.substr(0, loc.lastIndexOf('/')) + "/input";
+ var ws = new WebSocket(loc, "broadway");
+ ws.onopen = function() {
+ inputSocket = ws;
+ };
+ ws.onclose = function() {
+ inputSocket = null;
+ };
+ } else {
+ alert("WebSocket not supported, input will not work!");
+ }
+ document.oncontextmenu = function () { return false; };
+ document.onmousemove = onMouseMove;
+ document.onmouseover = onMouseOver;
+ document.onmouseout = onMouseOut;
+ document.onmousedown = onMouseDown;
+ document.onmouseup = onMouseUp;
+ document.onkeydown = onKeyDown;
+ document.onkeyup = onKeyUp;
+
+ if (document.addEventListener) {
+ document.addEventListener('DOMMouseScroll', onMouseWheel, false);
+ document.addEventListener('mousewheel', onMouseWheel, false);
+ } else if (document.attachEvent) {
+ element.attachEvent("onmousewheel", onMouseWheel);
+ }
}