- var cmd = cmd_obj.data;
- var i = cmd_obj.pos;
-
- while (i < cmd.length) {
- var command = cmd[i++];
- last_serial = base64_32(cmd, i);
- i = i + 6;
- 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, id);
- 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;
-
- /* resize a surface */
- case 'r':
- 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;
- surfaces[id].canvas.width = w;
- surfaces[id].canvas.height = h;
- 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);
+ sendInput("w", [surface.id, surface.x, surface.y, surface.width, surface.height]);
+}
+
+var windowGeometryTimeout = null;
+
+function updateBrowserWindowGeometry(win, alwaysSendConfigure) {
+ if (win.closed)
+ return;
+
+ var surface = win.surface;
+
+ var innerW = win.innerWidth;
+ var innerH = win.innerHeight;
+
+ var x = surface.x;
+ var y = surface.y;
+
+ if (win.mozInnerScreenX != undefined) {
+ x = win.mozInnerScreenX;
+ y = win.mozInnerScreenY;
+ } else if (win.screenTop != undefined) {
+ x = win.screenTop;
+ y = win.screenLeft;
+ } else {
+ alert("No implementation to get window position");
+ }
+
+ if (alwaysSendConfigure || x != surface.x || y != surface.y ||
+ innerW != surface.width || innerH != surface.height) {
+ var oldX = surface.x;
+ var oldY = surface.y;
+ surface.x = x;
+ surface.y = y;
+ if (surface.width != innerW || surface.height != innerH)
+ resizeCanvas(surface.canvas, innerW, innerH);
+ surface.width = innerW;
+ surface.height = innerH;
+ sendConfigureNotify(surface);
+ for (id in surfaces) {
+ var childSurface = surfaces[id];
+ var transientToplevel = getTransientToplevel(childSurface);
+ if (transientToplevel != null && transientToplevel == surface) {
+ childSurface.x += surface.x - oldX;
+ childSurface.y += surface.y - oldY;
+ sendConfigureNotify(childSurface);
+ }
+ }
+ }
+}
+
+function browserWindowClosed(win) {
+ var surface = win.surface;
+
+ sendInput ("W", [surface.id]);
+ for (id in surfaces) {
+ var childSurface = surfaces[id];
+ var transientToplevel = getTransientToplevel(childSurface);
+ if (transientToplevel != null && transientToplevel == surface) {
+ sendInput ("W", [childSurface.id]);
+ }
+ }
+}
+
+function registerWindow(win)
+{
+ toplevelWindows.push(win);
+ win.onresize = function(ev) { updateBrowserWindowGeometry(ev.target, false); };
+ if (!windowGeometryTimeout)
+ windowGeometryTimeout = setInterval(function () {
+ for (var i = 0; i < toplevelWindows.length; i++)
+ toplevelWindows[i].updateBrowserWindowGeometry(toplevelWindows[i], false);
+ }, 2000);
+ win.onunload = function(ev) { browserWindowClosed(ev.target.defaultView); };
+}
+
+function unregisterWindow(win)
+{
+ var i = toplevelWindows.indexOf(win);
+ if (i >= 0)
+ toplevelWindows.splice(i, 1);
+
+ if (windowGeometryTimeout && toplevelWindows.length == 0) {
+ clearInterval(windowGeometryTimeout);
+ windowGeometryTimeout = null;
+ }
+}
+
+function getTransientToplevel(surface)
+{
+ while (surface && surface.transientParent != 0) {
+ surface = surfaces[surface.transientParent];
+ if (surface && surface.window)
+ return surface;
+ }
+ return null;
+}
+
+function getStyle(el, styleProp)
+{
+ if (el.currentStyle) {
+ return el.currentStyle[styleProp];
+ } else if (window.getComputedStyle) {
+ var win = el.ownerDocument.defaultView;
+ return win.getComputedStyle(el, null).getPropertyValue(styleProp);
+ }
+ return undefined;
+}
+
+function parseOffset(value)
+{
+ var px = value.indexOf("px");
+ if (px > 0)
+ return parseInt(value.slice(0,px));
+ return 0;
+}
+
+function getFrameOffset(surface) {
+ var x = 0;
+ var y = 0;
+ var el = surface.canvas;
+ while (el != null && el != surface.frame) {
+ x += el.offsetLeft;
+ y += el.offsetTop;
+
+ /* For some reason the border is not includes in the offsets.. */
+ x += parseOffset(getStyle(el, "border-left-width"));
+ y += parseOffset(getStyle(el, "border-top-width"));
+
+ el = el.offsetParent;
+ }
+
+ /* Also include frame border as per above */
+ x += parseOffset(getStyle(el, "border-left-width"));
+ y += parseOffset(getStyle(el, "border-top-width"));
+
+ return {x: x, y: y};
+}
+
+var positionIndex = 0;
+function cmdCreateSurface(id, x, y, width, height, isTemp)
+{
+ var surface = { id: id, x: x, y:y, width: width, height: height, isTemp: isTemp };
+ surface.positioned = isTemp;
+ surface.drawQueue = [];
+ surface.transientParent = 0;
+ surface.visible = false;
+ surface.window = null;
+ surface.document = document;
+ surface.frame = null;
+
+ var canvas = document.createElement("canvas");
+ canvas.width = width;
+ canvas.height = height;
+ canvas.surface = surface;
+ surface.canvas = canvas;
+ var toplevelElement;
+
+ if (useToplevelWindows || isTemp) {
+ toplevelElement = canvas;
+ document.body.appendChild(canvas);
+ } else {
+ var frame = document.createElement("div");
+ frame.frameFor = surface;
+ frame.className = "frame-window";
+ surface.frame = frame;
+
+ var button = document.createElement("center");
+ var X = document.createTextNode("X");
+ button.appendChild(X);
+ button.className = "frame-close";
+ frame.appendChild(button);
+
+ var contents = document.createElement("div");
+ contents.className = "frame-contents";
+ frame.appendChild(contents);
+
+ canvas.style["display"] = "block";
+ contents.appendChild(canvas);
+
+ toplevelElement = frame;
+ document.body.appendChild(frame);
+
+ surface.x = 100 + positionIndex * 10;
+ surface.y = 100 + positionIndex * 10;
+ positionIndex = (positionIndex + 1) % 20;
+ }
+
+ surface.toplevelElement = toplevelElement;
+ toplevelElement.style["position"] = "absolute";
+ /* This positioning isn't strictly right for apps in another topwindow,
+ * but that will be fixed up when showing. */
+ toplevelElement.style["left"] = surface.x + "px";
+ toplevelElement.style["top"] = surface.y + "px";
+ toplevelElement.style["display"] = "inline";
+
+ /* We hide the frame with visibility rather than display none
+ * so getFrameOffset still works with hidden windows. */
+ toplevelElement.style["visibility"] = "hidden";
+
+ surfaces[id] = surface;
+ stackingOrder.push(surface);
+
+ sendConfigureNotify(surface);
+}
+
+function cmdShowSurface(id)
+{
+ var surface = surfaces[id];
+
+ if (surface.visible)
+ return;
+ surface.visible = true;
+
+ var xOffset = surface.x;
+ var yOffset = surface.y;
+
+ if (useToplevelWindows) {
+ var doc = document;
+ if (!surface.isTemp) {
+ var options =
+ 'width='+surface.width+',height='+surface.height+
+ ',location=no,menubar=no,scrollbars=no,toolbar=no';
+ if (surface.positioned)
+ options = options +
+ ',left='+surface.x+',top='+surface.y+',screenX='+surface.x+',screenY='+surface.y;
+ var win = window.open('','_blank', options);
+ win.surface = surface;
+ registerWindow(win);
+ doc = win.document;
+ doc.open();
+ doc.write("<body></body>");
+ setupDocument(doc);
+
+ surface.window = win;
+ xOffset = 0;
+ yOffset = 0;