Various cross-browser fixes.

Now working under Arora 0.5.

But not Konqueror 4.2.2 (WebSockets never connects).

IE support with excanvas still pending.
This commit is contained in:
Joel Martin
2010-06-23 16:08:36 -05:00
parent 11bb7a4ae4
commit d93d3e09ab
9 changed files with 243 additions and 103 deletions
+4 -4
View File
@@ -49,7 +49,7 @@ base64Pad : '=',
encode: function (data) {
var result = '';
var chrTable = Base64.toBase64Table;
var chrTable = Base64.toBase64Table.split('');
var pad = Base64.base64Pad;
var length = data.length;
var i;
@@ -107,11 +107,11 @@ decode: function (data, offset) {
// Convert one by one.
var idx = 0;
for (var i = offset; i < data.length; i++) {
var c = binTable[data[i].charCodeAt(0) & 0x7f];
var padding = (data[i] == pad);
var c = binTable[data.charCodeAt(i) & 0x7f];
var padding = (data.charAt(i) == pad);
// Skip illegal characters and whitespace
if (c == -1) {
console.log("Illegal character '" + data[i].charCodeAt(0) + "'");
console.log("Illegal character '" + data.charCodeAt(i) + "'");
continue;
}
+160 -44
View File
@@ -10,10 +10,22 @@
/*jslint white: false, bitwise: false */
/*global window, console, $, Util */
// Everything namespaced inside Canvas
var Canvas = {
var Canvas, Canvas_native;
prefer_js : false,
(function () {
var pre, extra = "", start, end;
if (document.createElement('canvas').getContext) {
Canvas_native = true;
} else {
Canvas_native = false;
document.write("<script src='excanvas'><\/script>");
}
}());
// Everything namespaced inside Canvas
Canvas = {
prefer_js : false,
true_color : false,
colourMap : [],
@@ -93,7 +105,7 @@ onKeyDown: function (e) {
},
onKeyUp : function (e) {
//console.log("keyup: " + e.key + "(" + e.code + ")");
//console.log("keyup: " + Canvas.getKeysym(e));
if (! Canvas.focused) {
return true;
}
@@ -122,17 +134,86 @@ onMouseDisable: function (e) {
},
init: function (id, width, height, true_color, keyPress,
mouseButton, mouseMove) {
init: function (id) {
var c, imgTest, arora;
console.log(">> Canvas.init");
Canvas.id = id;
c = $(Canvas.id);
if (Canvas_native) {
console.log("Using native canvas");
// Use default Canvas functions
} else {
console.warn("Using excanvas canvas emulation");
G_vmlCanvasManager.initElement(c);
}
if (! c.getContext) { throw("No getContext method"); }
Canvas.ctx = c.getContext('2d');
Canvas.clear();
/*
* Determine browser feature support and most optimal rendering
* methods
*/
tval = 0;
try {
imgTest = Canvas.ctx.getImageData(0, 0, 1,1);
imgTest.data[0] = 123;
imgTest.data[3] = 255;
Canvas.ctx.putImageData(imgTest, 0, 0);
tval = Canvas.ctx.getImageData(0, 0, 1, 1).data[0];
} catch (exc) {
}
if (tval === 123) {
Canvas._rgbxImage = Canvas._rgbxImageData;
Canvas._cmapImage = Canvas._cmapImageData;
if (Canvas.ctx.createImageData) {
// If it's there, it's faster
console.log("Using Canvas createImageData");
Canvas._imageData = Canvas._imageDataCreate;
} else if (Canvas.ctx.getImageData) {
console.log("Using Canvas getImageData");
Canvas._imageData = Canvas._imageDataGet;
} else {
console.log("No imageData support");
return false;
}
if (Util.Engine.webkit) {
console.log("Prefering javascript operations");
Canvas.prefer_js = true;
} else {
console.log("Prefering Canvas operations");
Canvas.prefer_js = false;
}
} else {
console.log("No imageData, using fillRect (slow)");
Canvas._rgbxImage = Canvas._rgbxImageFill;
Canvas._cmapImage = Canvas._cmapImageFill;
Canvas.prefer_js = false;
}
Canvas.colourMap = [];
Canvas.prevStyle = "";
Canvas.focused = true;
//console.log("<< Canvas.init");
return true;
},
start: function (keyPress, mouseButton, mouseMove) {
var c;
console.log(">> Canvas.start");
c = $(Canvas.id);
Canvas.keyPress = keyPress || null;
Canvas.mouseButton = mouseButton || null;
Canvas.mouseMove = mouseMove || null;
var c = $(Canvas.id);
Util.addEvent(document, 'keydown', Canvas.onKeyDown);
Util.addEvent(document, 'keyup', Canvas.onKeyUp);
Util.addEvent(c, 'mousedown', Canvas.onMouseDown);
@@ -145,34 +226,26 @@ init: function (id, width, height, true_color, keyPress,
Util.addEvent(document, 'click', Canvas.onMouseDisable);
Util.addEvent(document.body, 'contextmenu', Canvas.onMouseDisable);
Canvas.resize(width, height);
Canvas.c_wx = c.offsetWidth;
Canvas.c_wy = c.offsetHeight;
Canvas.true_color = true_color;
Canvas.colourMap = [];
if (! c.getContext) { return; }
Canvas.ctx = c.getContext('2d');
Canvas.prevStyle = "";
Canvas.focused = true;
if (Util.Engine.webkit) {
Canvas.prefer_js = true;
}
//console.log("<< Canvas.init");
//console.log("<< Canvas.start");
},
clear: function () {
Canvas.ctx.clearRect(0, 0, Canvas.c_wx, Canvas.c_wy);
Canvas.resize(640, 20);
Canvas.ctx.clearRect(0, 0, Canvas.c_wx, Canvas.c_wy);
},
resize: function (width, height) {
resize: function (width, height, true_color) {
var c = $(Canvas.id);
if (typeof true_color !== "undefined") {
Canvas.true_color = true_color;
}
c.width = width;
c.height = height;
Canvas.c_wx = c.offsetWidth;
Canvas.c_wy = c.offsetHeight;
},
stop: function () {
@@ -226,7 +299,7 @@ getTile: function(x, y, width, height, color) {
return img;
},
setTile: function(img, x, y, w, h, color) {
setSubTile: function(img, x, y, w, h, color) {
var data, p, rgb, red, green, blue, width, j, i;
if (Canvas.prefer_js) {
data = img.data;
@@ -255,19 +328,25 @@ setTile: function(img, x, y, w, h, color) {
putTile: function(img) {
if (Canvas.prefer_js) {
Canvas.rgbxImage(img.x, img.y, img.width, img.height, img.data, 0);
//Canvas.ctx.putImageData(img, img.x, img.y);
Canvas._rgbxImage(img.x, img.y, img.width, img.height, img.data, 0);
} else {
// No-op, under gecko already done by setTile
// No-op, under gecko already done by setSubTile
}
},
_imageDataGet: function(width, height) {
return Canvas.ctx.getImageData(0, 0, width, height);
},
_imageDataCreate: function(width, height) {
return Canvas.ctx.createImageData(width, height);
},
_imageDataRaw: function(width, height) {
return {'data': [], 'width': width, 'height': height};
},
rgbxImage: function(x, y, width, height, arr, offset) {
_rgbxImageData: function(x, y, width, height, arr, offset) {
var img, i, j, data;
//console.log("rfbxImage: img: " + img + " x: " + x + " y: " + y + " width: " + width + " height: " + height);
/* Old firefox and Opera don't support createImageData */
img = Canvas.ctx.getImageData(0, 0, width, height);
img = Canvas._imageData(width, height);
data = img.data;
for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) {
data[i + 0] = arr[j + 0];
@@ -278,13 +357,25 @@ rgbxImage: function(x, y, width, height, arr, offset) {
Canvas.ctx.putImageData(img, x, y);
},
cmapImage: function(x, y, width, height, arr, offset) {
// really slow fallback if we don't have imageData
_rgbxImageFill: function(x, y, width, height, arr, offset) {
var sx = 0, sy = 0;
for (i=0, j=offset; i < (width * height); i+=1, j+=4) {
Canvas.fillRect(x+sx, y+sy, 1, 1, [arr[j+0], arr[j+1], arr[j+2]]);
sx += 1;
if ((sx % width) === 0) {
sx = 0;
sy += 1;
}
}
},
_cmapImageData: function(x, y, width, height, arr, offset) {
var img, i, j, data, rgb, cmap;
img = Canvas.ctx.getImageData(0, 0, width, height);
img = Canvas._imageData(width, height);
data = img.data;
cmap = Canvas.colourMap;
//console.log("cmapImage x: " + x + ", y: " + y + "arr.slice(0,20): " + arr.slice(0,20));
for (i=0, j=offset; i < (width * height * 4); i=i+4, j += 1) {
for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) {
rgb = cmap[arr[j]];
data[i + 0] = rgb[0];
data[i + 1] = rgb[1];
@@ -294,15 +385,36 @@ cmapImage: function(x, y, width, height, arr, offset) {
Canvas.ctx.putImageData(img, x, y);
},
blitImage: function(x, y, width, height, arr, offset) {
if (Canvas.true_color) {
Canvas.rgbxImage(x, y, width, height, arr, offset);
} else {
Canvas.cmapImage(x, y, width, height, arr, offset);
_cmapImageFill: function(x, y, width, height, arr, offset) {
var sx = 0, sy = 0;
cmap = Canvas.colourMap;
console.log("here1: arr[2]: " + arr[2] + ", cmap[arr[2]]: " + cmap[arr[2]]);
for (i=0, j=offset; i < (width * height); i+=1, j+=1) {
Canvas.fillRect(x+sx, y+sy, 1, 1, [arr[j]]);
sx += 1;
if ((sx % width) === 0) {
sx = 0;
sy += 1;
}
}
},
fillRect: function(x, y, width, height, color) {
blitImage: function(x, y, width, height, arr, offset) {
if (Canvas.true_color) {
Canvas._rgbxImage(x, y, width, height, arr, offset);
} else {
Canvas._cmapImage(x, y, width, height, arr, offset);
}
},
blitStringImage: function(str, x, y) {
var img = new Image();
img.onload = function () { Canvas.ctx.drawImage(img, x, y); };
img.src = str;
},
setFillColor: function(color) {
var rgb, newStyle;
if (Canvas.true_color) {
rgb = color;
@@ -314,6 +426,10 @@ fillRect: function(x, y, width, height, color) {
Canvas.ctx.fillStyle = newStyle;
Canvas.prevStyle = newStyle;
}
},
fillRect: function(x, y, width, height, color) {
Canvas.setFillColor(color);
Canvas.ctx.fillRect(x, y, width, height);
},
+8 -8
View File
@@ -171,24 +171,24 @@ Util.getEventPosition = function (e, obj) {
// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
Util.addEvent = function (obj, evType, fn){
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
} else if (obj.attachEvent){
if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
} else {
throw("Handler could not be attached");
}
};
Util.removeEvent = function(obj, evType, fn){
if (obj.removeEventListener){
obj.removeEventListener(evType, fn, false);
return true;
} else if (obj.detachEvent){
if (obj.detachEvent){
var r = obj.detachEvent("on"+evType, fn);
return r;
} else if (obj.removeEventListener){
obj.removeEventListener(evType, fn, false);
return true;
} else {
throw("Handler could not be removed");
}
+8 -5
View File
@@ -64,7 +64,7 @@ true_color : false,
b64encode : true, // false means UTF-8 on the wire
//b64encode : false, // false means UTF-8 on the wire
connectTimeout : 1000, // time to wait for connection
connectTimeout : 3000, // time to wait for connection
// In preference order
@@ -140,6 +140,9 @@ load: function () {
}
}
// Initialize canvas/fxcanvas
Canvas.init(RFB.canvasID);
// Populate encoding lookup tables
RFB.encHandlers = {};
RFB.encNames = {};
@@ -466,8 +469,8 @@ init_msg: function () {
name_length = RQ.shift32();
RFB.fb_name = RQ.shiftStr(name_length);
Canvas.init(RFB.canvasID, RFB.fb_width, RFB.fb_height, RFB.true_color,
RFB.keyPress, RFB.mouseButton, RFB.mouseMove);
Canvas.resize(RFB.fb_width, RFB.fb_height, RFB.true_color);
Canvas.start(RFB.keyPress, RFB.mouseButton, RFB.mouseMove);
if (RFB.true_color) {
RFB.fb_Bpp = 4;
@@ -873,7 +876,7 @@ display_hextile: function() {
sw = (wh >> 4) + 1;
sh = (wh & 0x0f) + 1;
Canvas.setTile(tile, sx, sy, sw, sh, color);
Canvas.setSubTile(tile, sx, sy, sw, sh, color);
}
}
Canvas.putTile(tile);
@@ -1191,7 +1194,7 @@ recv_message_reorder: function(e) {
} else {
console.warn("sequence number mismatch: expected " +
RFB.RQ_seq_num + ", got " + seq_num);
if (RFB.RQ_reorder.length > 20) {
if (RFB.RQ_reorder.length > 40) {
RFB.updateState('failed', "Re-order queue too long");
} else {
RFB.RQ_reorder = RFB.RQ_reorder.concat(e.data.substr(0));