Indexed receive queue. Up to 2X speedup in Chrome.
Generally, most servers send hextile updates as single updates containing many rects. Some servers send hextile updates as many small framebuffer updates with a few rects each (such as QEMU). This latter cases revealed that shifting off the beginning of the receive queue (which happens after each hextile FBU) performs poorly. This change switches to using an indexed receive queue (instead of actually shifting off the array). When the receive queue has grown to a certain size, then it is compacted all at once. The code is not as clean, but this change results in more than 2X speedup under Chrome for the pessimal case and 10-20% in firefox.
This commit is contained in:
parent
fb007628d6
commit
67b4e9879a
|
@ -654,6 +654,18 @@ that.changeCursor = function(pixels, mask, hotx, hoty, w, h) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push multi-byte little-endian values
|
||||||
|
cur.push16le = function (num) {
|
||||||
|
this.push((num ) & 0xFF,
|
||||||
|
(num >> 8) & 0xFF );
|
||||||
|
};
|
||||||
|
cur.push32le = function (num) {
|
||||||
|
this.push((num ) & 0xFF,
|
||||||
|
(num >> 8) & 0xFF,
|
||||||
|
(num >> 16) & 0xFF,
|
||||||
|
(num >> 24) & 0xFF );
|
||||||
|
};
|
||||||
|
|
||||||
cmap = conf.colourMap;
|
cmap = conf.colourMap;
|
||||||
IHDRsz = 40;
|
IHDRsz = 40;
|
||||||
ANDsz = w * h * 4;
|
ANDsz = w * h * 4;
|
||||||
|
|
310
include/rfb.js
310
include/rfb.js
|
@ -69,6 +69,7 @@ var that = {}, // Public API interface
|
||||||
|
|
||||||
// Receive and send queues
|
// Receive and send queues
|
||||||
RQ = [], // Receive Queue
|
RQ = [], // Receive Queue
|
||||||
|
RQi = 0, // Receive Queue Index
|
||||||
SQ = "", // Send Queue
|
SQ = "", // Send Queue
|
||||||
|
|
||||||
// Frame buffer update state
|
// Frame buffer update state
|
||||||
|
@ -100,6 +101,7 @@ var that = {}, // Public API interface
|
||||||
scan_imgs_rate = 100,
|
scan_imgs_rate = 100,
|
||||||
last_req_time = 0,
|
last_req_time = 0,
|
||||||
rre_chunk_sz = 100,
|
rre_chunk_sz = 100,
|
||||||
|
maxRQlen = 100000,
|
||||||
|
|
||||||
timing = {
|
timing = {
|
||||||
last_fbu : 0,
|
last_fbu : 0,
|
||||||
|
@ -182,6 +184,35 @@ that.get_canvas = function() {
|
||||||
// Private functions
|
// Private functions
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Receive Queue functions
|
||||||
|
//
|
||||||
|
RQlen = function() {
|
||||||
|
return RQ.length - RQi;
|
||||||
|
}
|
||||||
|
|
||||||
|
RQshift16 = function() {
|
||||||
|
return (RQ[RQi++] << 8) +
|
||||||
|
(RQ[RQi++] );
|
||||||
|
}
|
||||||
|
RQshift32 = function() {
|
||||||
|
return (RQ[RQi++] << 24) +
|
||||||
|
(RQ[RQi++] << 16) +
|
||||||
|
(RQ[RQi++] << 8) +
|
||||||
|
(RQ[RQi++] );
|
||||||
|
}
|
||||||
|
RQshiftStr = function(len) {
|
||||||
|
var arr = RQ.slice(RQi, RQi + len);
|
||||||
|
RQi += len;
|
||||||
|
return arr.map(function (num) {
|
||||||
|
return String.fromCharCode(num); } ).join('');
|
||||||
|
|
||||||
|
}
|
||||||
|
RQshiftBytes = function(len) {
|
||||||
|
RQi += len;
|
||||||
|
return RQ.slice(RQi-len, RQi);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup routines
|
// Setup routines
|
||||||
//
|
//
|
||||||
|
@ -189,7 +220,7 @@ that.get_canvas = function() {
|
||||||
// Create the public API interface
|
// Create the public API interface
|
||||||
function constructor() {
|
function constructor() {
|
||||||
var i;
|
var i;
|
||||||
//Util.Debug(">> init");
|
Util.Debug(">> RFB.constructor");
|
||||||
|
|
||||||
// Create lookup tables based encoding number
|
// Create lookup tables based encoding number
|
||||||
for (i=0; i < encodings.length; i+=1) {
|
for (i=0; i < encodings.length; i+=1) {
|
||||||
|
@ -205,12 +236,12 @@ function constructor() {
|
||||||
updateState('fatal', "No working Canvas");
|
updateState('fatal', "No working Canvas");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Util.Debug("<< init");
|
Util.Debug("<< RFB.constructor");
|
||||||
return that; // Return the public API interface
|
return that; // Return the public API interface
|
||||||
}
|
}
|
||||||
|
|
||||||
function init_ws() {
|
function init_ws() {
|
||||||
//Util.Debug(">> init_ws");
|
Util.Debug(">> RFB.init_ws");
|
||||||
|
|
||||||
var uri = "", vars = [];
|
var uri = "", vars = [];
|
||||||
if (conf.encrypt) {
|
if (conf.encrypt) {
|
||||||
|
@ -261,7 +292,7 @@ function init_ws() {
|
||||||
}
|
}
|
||||||
}, conf.connectTimeout);
|
}, conf.connectTimeout);
|
||||||
|
|
||||||
//Util.Debug("<< init_ws");
|
Util.Debug("<< RFB.init_ws");
|
||||||
}
|
}
|
||||||
|
|
||||||
init_vars = function() {
|
init_vars = function() {
|
||||||
|
@ -269,6 +300,7 @@ init_vars = function() {
|
||||||
cuttext = 'none';
|
cuttext = 'none';
|
||||||
cuttext_length = 0;
|
cuttext_length = 0;
|
||||||
RQ = [];
|
RQ = [];
|
||||||
|
RQi = 0;
|
||||||
SQ = "";
|
SQ = "";
|
||||||
FBU.rects = 0;
|
FBU.rects = 0;
|
||||||
FBU.subrects = 0; // RRE and HEXTILE
|
FBU.subrects = 0; // RRE and HEXTILE
|
||||||
|
@ -456,8 +488,8 @@ function decode_message(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_message() {
|
function handle_message() {
|
||||||
//Util.Debug("RQ.slice(0,20): " + RQ.slice(0,20) + " (" + RQ.length + ")");
|
//Util.Debug("RQ.slice(RQi,RQi+20): " + RQ.slice(RQi,RQi+20) + " (" + RQlen() + ")");
|
||||||
if (RQ.length === 0) {
|
if (RQlen() === 0) {
|
||||||
Util.Warn("handle_message called on empty receive queue");
|
Util.Warn("handle_message called on empty receive queue");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +502,7 @@ function handle_message() {
|
||||||
that.disconnect();
|
that.disconnect();
|
||||||
break;
|
break;
|
||||||
case 'normal':
|
case 'normal':
|
||||||
if (normal_msg() && RQ.length > 0) {
|
if (normal_msg() && RQlen() > 0) {
|
||||||
// true means we can continue processing
|
// true means we can continue processing
|
||||||
// Give other events a chance to run
|
// Give other events a chance to run
|
||||||
if (msgTimer === null) {
|
if (msgTimer === null) {
|
||||||
|
@ -483,6 +515,12 @@ function handle_message() {
|
||||||
Util.Debug("More data to process, existing timer");
|
Util.Debug("More data to process, existing timer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Compact the queue
|
||||||
|
if (RQ.length > maxRQlen) {
|
||||||
|
//Util.Debug("Compacting receive queue");
|
||||||
|
RQ = RQ.slice(RQi);
|
||||||
|
RQi = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
init_msg();
|
init_msg();
|
||||||
|
@ -495,7 +533,7 @@ recv_message = function(e) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
decode_message(e.data);
|
decode_message(e.data);
|
||||||
if (RQ.length > 0) {
|
if (RQlen() > 0) {
|
||||||
handle_message();
|
handle_message();
|
||||||
} else {
|
} else {
|
||||||
Util.Debug("Ignoring empty message");
|
Util.Debug("Ignoring empty message");
|
||||||
|
@ -669,16 +707,16 @@ init_msg = function() {
|
||||||
i, types, num_types, challenge, response, bpp, depth,
|
i, types, num_types, challenge, response, bpp, depth,
|
||||||
big_endian, true_color, name_length;
|
big_endian, true_color, name_length;
|
||||||
|
|
||||||
//Util.Debug("RQ (" + RQ.length + ") " + RQ);
|
//Util.Debug("RQ (" + RQlen() + ") " + RQ);
|
||||||
switch (rfb_state) {
|
switch (rfb_state) {
|
||||||
|
|
||||||
case 'ProtocolVersion' :
|
case 'ProtocolVersion' :
|
||||||
if (RQ.length < 12) {
|
if (RQlen() < 12) {
|
||||||
updateState('failed',
|
updateState('failed',
|
||||||
"Disconnected: incomplete protocol version");
|
"Disconnected: incomplete protocol version");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sversion = RQ.shiftStr(12).substr(4,7);
|
sversion = RQshiftStr(12).substr(4,7);
|
||||||
Util.Info("Server ProtocolVersion: " + sversion);
|
Util.Info("Server ProtocolVersion: " + sversion);
|
||||||
switch (sversion) {
|
switch (sversion) {
|
||||||
case "003.003": rfb_version = 3.3; break;
|
case "003.003": rfb_version = 3.3; break;
|
||||||
|
@ -718,16 +756,16 @@ init_msg = function() {
|
||||||
|
|
||||||
case 'Security' :
|
case 'Security' :
|
||||||
if (rfb_version >= 3.7) {
|
if (rfb_version >= 3.7) {
|
||||||
num_types = RQ.shift8();
|
num_types = RQ[RQi++];
|
||||||
if (num_types === 0) {
|
if (num_types === 0) {
|
||||||
strlen = RQ.shift32();
|
strlen = RQshift32();
|
||||||
reason = RQ.shiftStr(strlen);
|
reason = RQshiftStr(strlen);
|
||||||
updateState('failed',
|
updateState('failed',
|
||||||
"Disconnected: security failure: " + reason);
|
"Disconnected: security failure: " + reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rfb_auth_scheme = 0;
|
rfb_auth_scheme = 0;
|
||||||
types = RQ.shiftBytes(num_types);
|
types = RQshiftBytes(num_types);
|
||||||
Util.Debug("Server security types: " + types);
|
Util.Debug("Server security types: " + types);
|
||||||
for (i=0; i < types.length; i+=1) {
|
for (i=0; i < types.length; i+=1) {
|
||||||
if ((types[i] > rfb_auth_scheme) && (types[i] < 3)) {
|
if ((types[i] > rfb_auth_scheme) && (types[i] < 3)) {
|
||||||
|
@ -742,11 +780,11 @@ init_msg = function() {
|
||||||
|
|
||||||
send_array([rfb_auth_scheme]);
|
send_array([rfb_auth_scheme]);
|
||||||
} else {
|
} else {
|
||||||
if (RQ.length < 4) {
|
if (RQlen() < 4) {
|
||||||
updateState('failed', "Invalid security frame");
|
updateState('failed', "Invalid security frame");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rfb_auth_scheme = RQ.shift32();
|
rfb_auth_scheme = RQshift32();
|
||||||
}
|
}
|
||||||
updateState('Authentication',
|
updateState('Authentication',
|
||||||
"Authenticating using scheme: " + rfb_auth_scheme);
|
"Authenticating using scheme: " + rfb_auth_scheme);
|
||||||
|
@ -757,12 +795,12 @@ init_msg = function() {
|
||||||
//Util.Debug("Security auth scheme: " + rfb_auth_scheme);
|
//Util.Debug("Security auth scheme: " + rfb_auth_scheme);
|
||||||
switch (rfb_auth_scheme) {
|
switch (rfb_auth_scheme) {
|
||||||
case 0: // connection failed
|
case 0: // connection failed
|
||||||
if (RQ.length < 4) {
|
if (RQlen() < 4) {
|
||||||
//Util.Debug(" waiting for auth reason bytes");
|
//Util.Debug(" waiting for auth reason bytes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
strlen = RQ.shift32();
|
strlen = RQshift32();
|
||||||
reason = RQ.shiftStr(strlen);
|
reason = RQshiftStr(strlen);
|
||||||
updateState('failed',
|
updateState('failed',
|
||||||
"Disconnected: auth failure: " + reason);
|
"Disconnected: auth failure: " + reason);
|
||||||
return;
|
return;
|
||||||
|
@ -774,11 +812,11 @@ init_msg = function() {
|
||||||
updateState('password', "Password Required");
|
updateState('password', "Password Required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (RQ.length < 16) {
|
if (RQlen() < 16) {
|
||||||
//Util.Debug(" waiting for auth challenge bytes");
|
//Util.Debug(" waiting for auth challenge bytes");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
challenge = RQ.shiftBytes(16);
|
challenge = RQshiftBytes(16);
|
||||||
//Util.Debug("Password: " + rfb_password);
|
//Util.Debug("Password: " + rfb_password);
|
||||||
//Util.Debug("Challenge: " + challenge +
|
//Util.Debug("Challenge: " + challenge +
|
||||||
// " (" + challenge.length + ")");
|
// " (" + challenge.length + ")");
|
||||||
|
@ -799,18 +837,18 @@ init_msg = function() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'SecurityResult' :
|
case 'SecurityResult' :
|
||||||
if (RQ.length < 4) {
|
if (RQlen() < 4) {
|
||||||
updateState('failed', "Invalid VNC auth response");
|
updateState('failed', "Invalid VNC auth response");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (RQ.shift32()) {
|
switch (RQshift32()) {
|
||||||
case 0: // OK
|
case 0: // OK
|
||||||
updateState('ServerInitialisation', "Authentication OK");
|
updateState('ServerInitialisation', "Authentication OK");
|
||||||
break;
|
break;
|
||||||
case 1: // failed
|
case 1: // failed
|
||||||
if (rfb_version >= 3.8) {
|
if (rfb_version >= 3.8) {
|
||||||
reason_len = RQ.shift32();
|
reason_len = RQshift32();
|
||||||
reason = RQ.shiftStr(reason_len);
|
reason = RQshiftStr(reason_len);
|
||||||
updateState('failed', reason);
|
updateState('failed', reason);
|
||||||
} else {
|
} else {
|
||||||
updateState('failed', "Authentication failed");
|
updateState('failed', "Authentication failed");
|
||||||
|
@ -825,20 +863,20 @@ init_msg = function() {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'ServerInitialisation' :
|
case 'ServerInitialisation' :
|
||||||
if (RQ.length < 24) {
|
if (RQlen() < 24) {
|
||||||
updateState('failed', "Invalid server initialisation");
|
updateState('failed', "Invalid server initialisation");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Screen size */
|
/* Screen size */
|
||||||
fb_width = RQ.shift16();
|
fb_width = RQshift16();
|
||||||
fb_height = RQ.shift16();
|
fb_height = RQshift16();
|
||||||
|
|
||||||
/* PIXEL_FORMAT */
|
/* PIXEL_FORMAT */
|
||||||
bpp = RQ.shift8();
|
bpp = RQ[RQi++];
|
||||||
depth = RQ.shift8();
|
depth = RQ[RQi++];
|
||||||
big_endian = RQ.shift8();
|
big_endian = RQ[RQi++];
|
||||||
true_color = RQ.shift8();
|
true_color = RQ[RQi++];
|
||||||
|
|
||||||
Util.Info("Screen: " + fb_width + "x" + fb_height +
|
Util.Info("Screen: " + fb_width + "x" + fb_height +
|
||||||
", bpp: " + bpp + ", depth: " + depth +
|
", bpp: " + bpp + ", depth: " + depth +
|
||||||
|
@ -846,9 +884,9 @@ init_msg = function() {
|
||||||
", true_color: " + true_color);
|
", true_color: " + true_color);
|
||||||
|
|
||||||
/* Connection name/title */
|
/* Connection name/title */
|
||||||
RQ.shiftStr(12);
|
RQshiftStr(12);
|
||||||
name_length = RQ.shift32();
|
name_length = RQshift32();
|
||||||
fb_name = RQ.shiftStr(name_length);
|
fb_name = RQshiftStr(name_length);
|
||||||
|
|
||||||
canvas.resize(fb_width, fb_height, conf.true_color);
|
canvas.resize(fb_width, fb_height, conf.true_color);
|
||||||
canvas.start(keyPress, mouseButton, mouseMove);
|
canvas.start(keyPress, mouseButton, mouseMove);
|
||||||
|
@ -891,14 +929,12 @@ normal_msg = function() {
|
||||||
var ret = true, msg_type,
|
var ret = true, msg_type,
|
||||||
c, first_colour, num_colours, red, green, blue;
|
c, first_colour, num_colours, red, green, blue;
|
||||||
|
|
||||||
//Util.Debug(">> msg RQ.slice(0,10): " + RQ.slice(0,20));
|
|
||||||
//Util.Debug(">> msg RQ.slice(-10,-1): " + RQ.slice(RQ.length-10,RQ.length));
|
|
||||||
if (FBU.rects > 0) {
|
if (FBU.rects > 0) {
|
||||||
msg_type = 0;
|
msg_type = 0;
|
||||||
} else if (cuttext !== 'none') {
|
} else if (cuttext !== 'none') {
|
||||||
msg_type = 3;
|
msg_type = 3;
|
||||||
} else {
|
} else {
|
||||||
msg_type = RQ.shift8();
|
msg_type = RQ[RQi++];
|
||||||
}
|
}
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case 0: // FramebufferUpdate
|
case 0: // FramebufferUpdate
|
||||||
|
@ -906,16 +942,16 @@ normal_msg = function() {
|
||||||
break;
|
break;
|
||||||
case 1: // SetColourMapEntries
|
case 1: // SetColourMapEntries
|
||||||
Util.Debug("SetColourMapEntries");
|
Util.Debug("SetColourMapEntries");
|
||||||
RQ.shift8(); // Padding
|
RQ[RQi++]; // Padding
|
||||||
first_colour = RQ.shift16(); // First colour
|
first_colour = RQshift16(); // First colour
|
||||||
num_colours = RQ.shift16();
|
num_colours = RQshift16();
|
||||||
for (c=0; c < num_colours; c+=1) {
|
for (c=0; c < num_colours; c+=1) {
|
||||||
red = RQ.shift16();
|
red = RQshift16();
|
||||||
//Util.Debug("red before: " + red);
|
//Util.Debug("red before: " + red);
|
||||||
red = parseInt(red / 256, 10);
|
red = parseInt(red / 256, 10);
|
||||||
//Util.Debug("red after: " + red);
|
//Util.Debug("red after: " + red);
|
||||||
green = parseInt(RQ.shift16() / 256, 10);
|
green = parseInt(RQshift16() / 256, 10);
|
||||||
blue = parseInt(RQ.shift16() / 256, 10);
|
blue = parseInt(RQshift16() / 256, 10);
|
||||||
canvas.set_colourMap([red, green, blue], first_colour + c);
|
canvas.set_colourMap([red, green, blue], first_colour + c);
|
||||||
}
|
}
|
||||||
Util.Info("Registered " + num_colours + " colourMap entries");
|
Util.Info("Registered " + num_colours + " colourMap entries");
|
||||||
|
@ -931,19 +967,19 @@ normal_msg = function() {
|
||||||
cuttext = 'header';
|
cuttext = 'header';
|
||||||
}
|
}
|
||||||
if (cuttext === 'header') {
|
if (cuttext === 'header') {
|
||||||
if (RQ.length < 7) {
|
if (RQlen() < 7) {
|
||||||
//Util.Debug("waiting for ServerCutText header");
|
//Util.Debug("waiting for ServerCutText header");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RQ.shiftBytes(3); // Padding
|
RQshiftBytes(3); // Padding
|
||||||
cuttext_length = RQ.shift32();
|
cuttext_length = RQshift32();
|
||||||
}
|
}
|
||||||
cuttext = 'bytes';
|
cuttext = 'bytes';
|
||||||
if (RQ.length < cuttext_length) {
|
if (RQlen() < cuttext_length) {
|
||||||
//Util.Debug("waiting for ServerCutText bytes");
|
//Util.Debug("waiting for ServerCutText bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
conf.clipboardReceive(that, RQ.shiftStr(cuttext_length));
|
conf.clipboardReceive(that, RQshiftStr(cuttext_length));
|
||||||
cuttext = 'none';
|
cuttext = 'none';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -961,13 +997,17 @@ framebufferUpdate = function() {
|
||||||
|
|
||||||
if (FBU.rects === 0) {
|
if (FBU.rects === 0) {
|
||||||
//Util.Debug("New FBU: RQ.slice(0,20): " + RQ.slice(0,20));
|
//Util.Debug("New FBU: RQ.slice(0,20): " + RQ.slice(0,20));
|
||||||
if (RQ.length < 3) {
|
if (RQlen() < 3) {
|
||||||
|
if (RQi === 0) {
|
||||||
RQ.unshift(0); // FBU msg_type
|
RQ.unshift(0); // FBU msg_type
|
||||||
Util.Debug(" waiting for FBU header bytes");
|
} else {
|
||||||
|
RQi -= 1;
|
||||||
|
}
|
||||||
|
//Util.Debug(" waiting for FBU header bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RQ.shift8();
|
RQ[RQi++];
|
||||||
FBU.rects = RQ.shift16();
|
FBU.rects = RQshift16();
|
||||||
//Util.Debug("FramebufferUpdate, rects:" + FBU.rects);
|
//Util.Debug("FramebufferUpdate, rects:" + FBU.rects);
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
timing.cur_fbu = 0;
|
timing.cur_fbu = 0;
|
||||||
|
@ -982,17 +1022,18 @@ framebufferUpdate = function() {
|
||||||
if (rfb_state !== "normal") {
|
if (rfb_state !== "normal") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
|
//Util.Debug(" waiting for " + (FBU.bytes - RQlen()) + " FBU bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (FBU.bytes === 0) {
|
if (FBU.bytes === 0) {
|
||||||
if (RQ.length < 12) {
|
if (RQlen() < 12) {
|
||||||
//Util.Debug(" waiting for rect header bytes");
|
//Util.Debug(" waiting for rect header bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* New FramebufferUpdate */
|
/* New FramebufferUpdate */
|
||||||
|
|
||||||
hdr = RQ.shiftBytes(12);
|
hdr = RQshiftBytes(12);
|
||||||
FBU.x = (hdr[0] << 8) + hdr[1];
|
FBU.x = (hdr[0] << 8) + hdr[1];
|
||||||
FBU.y = (hdr[2] << 8) + hdr[3];
|
FBU.y = (hdr[2] << 8) + hdr[3];
|
||||||
FBU.width = (hdr[4] << 8) + hdr[5];
|
FBU.width = (hdr[4] << 8) + hdr[5];
|
||||||
|
@ -1009,7 +1050,7 @@ framebufferUpdate = function() {
|
||||||
msg += " width: " + FBU.width + " height: " + FBU.height;
|
msg += " width: " + FBU.width + " height: " + FBU.height;
|
||||||
msg += " encoding:" + FBU.encoding;
|
msg += " encoding:" + FBU.encoding;
|
||||||
msg += "(" + encNames[FBU.encoding] + ")";
|
msg += "(" + encNames[FBU.encoding] + ")";
|
||||||
msg += ", RQ.length: " + RQ.length;
|
msg += ", RQlen(): " + RQlen();
|
||||||
Util.Debug(msg);
|
Util.Debug(msg);
|
||||||
*/
|
*/
|
||||||
} else {
|
} else {
|
||||||
|
@ -1021,7 +1062,7 @@ framebufferUpdate = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
timing.last_fbu = (new Date()).getTime();
|
timing.last_fbu = (new Date()).getTime();
|
||||||
last_bytes = RQ.length;
|
last_bytes = RQlen();
|
||||||
last_rects = FBU.rects;
|
last_rects = FBU.rects;
|
||||||
|
|
||||||
// false ret means need more data
|
// false ret means need more data
|
||||||
|
@ -1029,7 +1070,7 @@ framebufferUpdate = function() {
|
||||||
|
|
||||||
now = (new Date()).getTime();
|
now = (new Date()).getTime();
|
||||||
timing.cur_fbu += (now - timing.last_fbu);
|
timing.cur_fbu += (now - timing.last_fbu);
|
||||||
timing.h_bytes += last_bytes-RQ.length;
|
timing.h_bytes += last_bytes-RQlen();
|
||||||
|
|
||||||
if (FBU.rects < last_rects) {
|
if (FBU.rects < last_rects) {
|
||||||
// Some work was done
|
// Some work was done
|
||||||
|
@ -1063,6 +1104,9 @@ framebufferUpdate = function() {
|
||||||
timing.fbu_rt_start = 0;
|
timing.fbu_rt_start = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (! ret) {
|
||||||
|
break; // false ret means need more data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -1080,16 +1124,16 @@ encHandlers.RAW = function display_raw() {
|
||||||
FBU.lines = FBU.height;
|
FBU.lines = FBU.height;
|
||||||
}
|
}
|
||||||
FBU.bytes = FBU.width * fb_Bpp; // At least a line
|
FBU.bytes = FBU.width * fb_Bpp; // At least a line
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " RAW bytes");
|
// (FBU.bytes - RQlen()) + " RAW bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cur_y = FBU.y + (FBU.height - FBU.lines);
|
cur_y = FBU.y + (FBU.height - FBU.lines);
|
||||||
cur_height = Math.min(FBU.lines,
|
cur_height = Math.min(FBU.lines,
|
||||||
Math.floor(RQ.length/(FBU.width * fb_Bpp)));
|
Math.floor(RQlen()/(FBU.width * fb_Bpp)));
|
||||||
canvas.blitImage(FBU.x, cur_y, FBU.width, cur_height, RQ, 0);
|
canvas.blitImage(FBU.x, cur_y, FBU.width, cur_height, RQ, RQi);
|
||||||
RQ.shiftBytes(FBU.width * cur_height * fb_Bpp);
|
RQshiftBytes(FBU.width * cur_height * fb_Bpp);
|
||||||
FBU.lines -= cur_height;
|
FBU.lines -= cur_height;
|
||||||
|
|
||||||
if (FBU.lines > 0) {
|
if (FBU.lines > 0) {
|
||||||
|
@ -1106,13 +1150,13 @@ encHandlers.COPYRECT = function display_copy_rect() {
|
||||||
|
|
||||||
var old_x, old_y;
|
var old_x, old_y;
|
||||||
|
|
||||||
if (RQ.length < 4) {
|
if (RQlen() < 4) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " COPYRECT bytes");
|
// (FBU.bytes - RQlen()) + " COPYRECT bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
old_x = RQ.shift16();
|
old_x = RQshift16();
|
||||||
old_y = RQ.shift16();
|
old_y = RQshift16();
|
||||||
canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height);
|
canvas.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height);
|
||||||
FBU.rects -= 1;
|
FBU.rects -= 1;
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
|
@ -1120,25 +1164,25 @@ encHandlers.COPYRECT = function display_copy_rect() {
|
||||||
};
|
};
|
||||||
|
|
||||||
encHandlers.RRE = function display_rre() {
|
encHandlers.RRE = function display_rre() {
|
||||||
//Util.Debug(">> display_rre (" + RQ.length + " bytes)");
|
//Util.Debug(">> display_rre (" + RQlen() + " bytes)");
|
||||||
var color, x, y, width, height, chunk;
|
var color, x, y, width, height, chunk;
|
||||||
|
|
||||||
if (FBU.subrects === 0) {
|
if (FBU.subrects === 0) {
|
||||||
if (RQ.length < 4 + fb_Bpp) {
|
if (RQlen() < 4 + fb_Bpp) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (4 + fb_Bpp - RQ.length) + " RRE bytes");
|
// (4 + fb_Bpp - RQlen()) + " RRE bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
FBU.subrects = RQ.shift32();
|
FBU.subrects = RQshift32();
|
||||||
color = RQ.shiftBytes(fb_Bpp); // Background
|
color = RQshiftBytes(fb_Bpp); // Background
|
||||||
canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
||||||
}
|
}
|
||||||
while ((FBU.subrects > 0) && (RQ.length >= (fb_Bpp + 8))) {
|
while ((FBU.subrects > 0) && (RQlen() >= (fb_Bpp + 8))) {
|
||||||
color = RQ.shiftBytes(fb_Bpp);
|
color = RQshiftBytes(fb_Bpp);
|
||||||
x = RQ.shift16();
|
x = RQshift16();
|
||||||
y = RQ.shift16();
|
y = RQshift16();
|
||||||
width = RQ.shift16();
|
width = RQshift16();
|
||||||
height = RQ.shift16();
|
height = RQshift16();
|
||||||
canvas.fillRect(FBU.x + x, FBU.y + y, width, height, color);
|
canvas.fillRect(FBU.x + x, FBU.y + y, width, height, color);
|
||||||
FBU.subrects -= 1;
|
FBU.subrects -= 1;
|
||||||
}
|
}
|
||||||
|
@ -1158,7 +1202,7 @@ encHandlers.RRE = function display_rre() {
|
||||||
|
|
||||||
encHandlers.HEXTILE = function display_hextile() {
|
encHandlers.HEXTILE = function display_hextile() {
|
||||||
//Util.Debug(">> display_hextile");
|
//Util.Debug(">> display_hextile");
|
||||||
var subencoding, subrects, idx, tile, color, cur_tile,
|
var subencoding, subrects, tile, color, cur_tile,
|
||||||
tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh;
|
tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh;
|
||||||
|
|
||||||
if (FBU.tiles === 0) {
|
if (FBU.tiles === 0) {
|
||||||
|
@ -1168,14 +1212,15 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
FBU.tiles = FBU.total_tiles;
|
FBU.tiles = FBU.total_tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FBU.bytes comes in as 1, RQ.length at least 1 */
|
/* FBU.bytes comes in as 1, RQlen() at least 1 */
|
||||||
while (FBU.tiles > 0) {
|
while (FBU.tiles > 0) {
|
||||||
FBU.bytes = 1;
|
FBU.bytes = 1;
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for HEXTILE subencoding byte");
|
//Util.Debug(" waiting for HEXTILE subencoding byte");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
subencoding = RQ[0]; // Peek
|
//Util.Debug(" 2 RQ length: " + RQlen() + " RQ[RQi]: " + RQ[RQi] + " RQ.slice(RQi,RQi+20): " + RQ.slice(RQi,RQi+20) + ", FBU.rects: " + FBU.rects + ", FBU.tiles: " + FBU.tiles);
|
||||||
|
subencoding = RQ[RQi]; // Peek
|
||||||
if (subencoding > 30) { // Raw
|
if (subencoding > 30) { // Raw
|
||||||
updateState('failed',
|
updateState('failed',
|
||||||
"Disconnected: illegal hextile subencoding " + subencoding);
|
"Disconnected: illegal hextile subencoding " + subencoding);
|
||||||
|
@ -1204,12 +1249,12 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
}
|
}
|
||||||
if (subencoding & 0x08) { // AnySubrects
|
if (subencoding & 0x08) { // AnySubrects
|
||||||
FBU.bytes += 1; // Since we aren't shifting it off
|
FBU.bytes += 1; // Since we aren't shifting it off
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
/* Wait for subrects byte */
|
/* Wait for subrects byte */
|
||||||
//Util.Debug(" waiting for hextile subrects header byte");
|
//Util.Debug(" waiting for hextile subrects header byte");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
subrects = RQ[FBU.bytes-1]; // Peek
|
subrects = RQ[RQi + FBU.bytes-1]; // Peek
|
||||||
if (subencoding & 0x10) { // SubrectsColoured
|
if (subencoding & 0x10) { // SubrectsColoured
|
||||||
FBU.bytes += subrects * (fb_Bpp + 2);
|
FBU.bytes += subrects * (fb_Bpp + 2);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1218,23 +1263,26 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Util.Debug(" tile:" + cur_tile + "/" + (FBU.total_tiles - 1) +
|
/*
|
||||||
// ", subencoding:" + subencoding +
|
Util.Debug(" tile:" + cur_tile + "/" + (FBU.total_tiles - 1) +
|
||||||
// "(last: " + FBU.lastsubencoding + "), subrects:" +
|
" (" + tile_x + "," + tile_y + ")" +
|
||||||
// subrects + ", tile:" + tile_x + "," + tile_y +
|
" [" + x + "," + y + "]@" + w + "x" + h +
|
||||||
// " [" + x + "," + y + "]@" + w + "x" + h +
|
", subenc:" + subencoding +
|
||||||
// ", d.length:" + RQ.length + ", bytes:" + FBU.bytes +
|
"(last: " + FBU.lastsubencoding + "), subrects:" +
|
||||||
// " last:" + RQ.slice(FBU.bytes-10, FBU.bytes) +
|
subrects +
|
||||||
// " next:" + RQ.slice(FBU.bytes-1, FBU.bytes+10));
|
", RQlen():" + RQlen() + ", FBU.bytes:" + FBU.bytes +
|
||||||
if (RQ.length < FBU.bytes) {
|
" last:" + RQ.slice(FBU.bytes-10, FBU.bytes) +
|
||||||
|
" next:" + RQ.slice(FBU.bytes-1, FBU.bytes+10));
|
||||||
|
*/
|
||||||
|
if (RQlen() < FBU.bytes) {
|
||||||
//Util.Debug(" waiting for " +
|
//Util.Debug(" waiting for " +
|
||||||
// (FBU.bytes - RQ.length) + " hextile bytes");
|
// (FBU.bytes - RQlen()) + " hextile bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We know the encoding and have a whole tile */
|
/* We know the encoding and have a whole tile */
|
||||||
FBU.subencoding = RQ[0];
|
FBU.subencoding = RQ[RQi];
|
||||||
idx = 1;
|
RQi += 1;
|
||||||
if (FBU.subencoding === 0) {
|
if (FBU.subencoding === 0) {
|
||||||
if (FBU.lastsubencoding & 0x01) {
|
if (FBU.lastsubencoding & 0x01) {
|
||||||
/* Weird: ignore blanks after RAW */
|
/* Weird: ignore blanks after RAW */
|
||||||
|
@ -1243,35 +1291,36 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
canvas.fillRect(x, y, w, h, FBU.background);
|
canvas.fillRect(x, y, w, h, FBU.background);
|
||||||
}
|
}
|
||||||
} else if (FBU.subencoding & 0x01) { // Raw
|
} else if (FBU.subencoding & 0x01) { // Raw
|
||||||
canvas.blitImage(x, y, w, h, RQ, idx);
|
canvas.blitImage(x, y, w, h, RQ, RQi);
|
||||||
|
RQi += FBU.bytes - 1;
|
||||||
} else {
|
} else {
|
||||||
if (FBU.subencoding & 0x02) { // Background
|
if (FBU.subencoding & 0x02) { // Background
|
||||||
FBU.background = RQ.slice(idx, idx + fb_Bpp);
|
FBU.background = RQ.slice(RQi, RQi + fb_Bpp);
|
||||||
idx += fb_Bpp;
|
RQi += fb_Bpp;
|
||||||
}
|
}
|
||||||
if (FBU.subencoding & 0x04) { // Foreground
|
if (FBU.subencoding & 0x04) { // Foreground
|
||||||
FBU.foreground = RQ.slice(idx, idx + fb_Bpp);
|
FBU.foreground = RQ.slice(RQi, RQi + fb_Bpp);
|
||||||
idx += fb_Bpp;
|
RQi += fb_Bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
tile = canvas.getTile(x, y, w, h, FBU.background);
|
tile = canvas.getTile(x, y, w, h, FBU.background);
|
||||||
if (FBU.subencoding & 0x08) { // AnySubrects
|
if (FBU.subencoding & 0x08) { // AnySubrects
|
||||||
subrects = RQ[idx];
|
subrects = RQ[RQi];
|
||||||
idx += 1;
|
RQi += 1;
|
||||||
for (s = 0; s < subrects; s += 1) {
|
for (s = 0; s < subrects; s += 1) {
|
||||||
if (FBU.subencoding & 0x10) { // SubrectsColoured
|
if (FBU.subencoding & 0x10) { // SubrectsColoured
|
||||||
color = RQ.slice(idx, idx + fb_Bpp);
|
color = RQ.slice(RQi, RQi + fb_Bpp);
|
||||||
idx += fb_Bpp;
|
RQi += fb_Bpp;
|
||||||
} else {
|
} else {
|
||||||
color = FBU.foreground;
|
color = FBU.foreground;
|
||||||
}
|
}
|
||||||
xy = RQ[idx];
|
xy = RQ[RQi];
|
||||||
idx += 1;
|
RQi += 1;
|
||||||
sx = (xy >> 4);
|
sx = (xy >> 4);
|
||||||
sy = (xy & 0x0f);
|
sy = (xy & 0x0f);
|
||||||
|
|
||||||
wh = RQ[idx];
|
wh = RQ[RQi];
|
||||||
idx += 1;
|
RQi += 1;
|
||||||
sw = (wh >> 4) + 1;
|
sw = (wh >> 4) + 1;
|
||||||
sh = (wh & 0x0f) + 1;
|
sh = (wh & 0x0f) + 1;
|
||||||
|
|
||||||
|
@ -1280,7 +1329,7 @@ encHandlers.HEXTILE = function display_hextile() {
|
||||||
}
|
}
|
||||||
canvas.putTile(tile);
|
canvas.putTile(tile);
|
||||||
}
|
}
|
||||||
RQ.shiftBytes(FBU.bytes);
|
//RQshiftBytes(FBU.bytes);
|
||||||
FBU.lastsubencoding = FBU.subencoding;
|
FBU.lastsubencoding = FBU.subencoding;
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
FBU.tiles -= 1;
|
FBU.tiles -= 1;
|
||||||
|
@ -1299,12 +1348,12 @@ encHandlers.TIGHT_PNG = function display_tight_png() {
|
||||||
//Util.Debug(">> display_tight_png");
|
//Util.Debug(">> display_tight_png");
|
||||||
var ctl, cmode, clength, getCLength, color, img;
|
var ctl, cmode, clength, getCLength, color, img;
|
||||||
//Util.Debug(" FBU.rects: " + FBU.rects);
|
//Util.Debug(" FBU.rects: " + FBU.rects);
|
||||||
//Util.Debug(" RQ.length: " + RQ.length);
|
//Util.Debug(" RQlen(): " + RQlen());
|
||||||
//Util.Debug(" RQ.slice(0,20): " + RQ.slice(0,20));
|
//Util.Debug(" RQ.slice(0,20): " + RQ.slice(0,20));
|
||||||
|
|
||||||
|
|
||||||
FBU.bytes = 1; // compression-control byte
|
FBU.bytes = 1; // compression-control byte
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT compression-control byte");
|
Util.Debug(" waiting for TIGHT compression-control byte");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1373,7 @@ encHandlers.TIGHT_PNG = function display_tight_png() {
|
||||||
return [header, data];
|
return [header, data];
|
||||||
};
|
};
|
||||||
|
|
||||||
ctl = RQ[0];
|
ctl = RQ[RQi];
|
||||||
switch (ctl >> 4) {
|
switch (ctl >> 4) {
|
||||||
case 0x08: cmode = "fill"; break;
|
case 0x08: cmode = "fill"; break;
|
||||||
case 0x09: cmode = "jpeg"; break;
|
case 0x09: cmode = "jpeg"; break;
|
||||||
|
@ -1338,44 +1387,44 @@ encHandlers.TIGHT_PNG = function display_tight_png() {
|
||||||
case "png": FBU.bytes += 3; break; // max clength
|
case "png": FBU.bytes += 3; break; // max clength
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Util.Debug(" RQ.slice(0,20): " + RQ.slice(0,20) + " (" + RQ.length + ")");
|
//Util.Debug(" RQ.slice(0,20): " + RQ.slice(0,20) + " (" + RQlen() + ")");
|
||||||
//Util.Debug(" cmode: " + cmode);
|
//Util.Debug(" cmode: " + cmode);
|
||||||
|
|
||||||
// Determine FBU.bytes
|
// Determine FBU.bytes
|
||||||
switch (cmode) {
|
switch (cmode) {
|
||||||
case "fill":
|
case "fill":
|
||||||
RQ.shift8(); // shift off ctl
|
RQ[RQi++]; // shift off ctl
|
||||||
color = RQ.shiftBytes(fb_depth);
|
color = RQshiftBytes(fb_depth);
|
||||||
canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
canvas.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color);
|
||||||
break;
|
break;
|
||||||
case "jpeg":
|
case "jpeg":
|
||||||
case "png":
|
case "png":
|
||||||
clength = getCLength(RQ, 1);
|
clength = getCLength(RQ, 1);
|
||||||
FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data
|
FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data
|
||||||
if (RQ.length < FBU.bytes) {
|
if (RQlen() < FBU.bytes) {
|
||||||
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
Util.Debug(" waiting for TIGHT " + cmode + " bytes");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have everything, render it
|
// We have everything, render it
|
||||||
//Util.Debug(" png, RQ.length: " + RQ.length + ", clength[0]: " + clength[0] + ", clength[1]: " + clength[1]);
|
//Util.Debug(" png, RQlen(): " + RQlen() + ", clength[0]: " + clength[0] + ", clength[1]: " + clength[1]);
|
||||||
RQ.shiftBytes(1 + clength[0]); // shift off ctl + compact length
|
RQshiftBytes(1 + clength[0]); // shift off ctl + compact length
|
||||||
img = new Image();
|
img = new Image();
|
||||||
img.onload = scan_tight_imgs;
|
img.onload = scan_tight_imgs;
|
||||||
FBU.imgs.push([img, FBU.x, FBU.y]);
|
FBU.imgs.push([img, FBU.x, FBU.y]);
|
||||||
img.src = "data:image/" + cmode +
|
img.src = "data:image/" + cmode +
|
||||||
extract_data_uri(RQ.shiftBytes(clength[1]));
|
extract_data_uri(RQshiftBytes(clength[1]));
|
||||||
img = null;
|
img = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
FBU.rects -= 1;
|
FBU.rects -= 1;
|
||||||
//Util.Debug(" ending RQ.length: " + RQ.length);
|
//Util.Debug(" ending RQlen(): " + RQlen());
|
||||||
//Util.Debug(" ending RQ.slice(0,20): " + RQ.slice(0,20));
|
//Util.Debug(" ending RQ.slice(0,20): " + RQ.slice(0,20));
|
||||||
//Util.Debug("<< display_tight_png");
|
//Util.Debug("<< display_tight_png");
|
||||||
return true;
|
return true;
|
||||||
|
@ -1431,7 +1480,7 @@ encHandlers.Cursor = function set_cursor() {
|
||||||
pixelslength = w * h * fb_Bpp;
|
pixelslength = w * h * fb_Bpp;
|
||||||
masklength = Math.floor((w + 7) / 8) * h;
|
masklength = Math.floor((w + 7) / 8) * h;
|
||||||
|
|
||||||
if (RQ.length < (pixelslength + masklength)) {
|
if (RQlen() < (pixelslength + masklength)) {
|
||||||
//Util.Debug("waiting for cursor encoding bytes");
|
//Util.Debug("waiting for cursor encoding bytes");
|
||||||
FBU.bytes = pixelslength + masklength;
|
FBU.bytes = pixelslength + masklength;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1439,8 +1488,8 @@ encHandlers.Cursor = function set_cursor() {
|
||||||
|
|
||||||
//Util.Debug(" set_cursor, x: " + x + ", y: " + y + ", w: " + w + ", h: " + h);
|
//Util.Debug(" set_cursor, x: " + x + ", y: " + y + ", w: " + w + ", h: " + h);
|
||||||
|
|
||||||
canvas.changeCursor(RQ.shiftBytes(pixelslength),
|
canvas.changeCursor(RQshiftBytes(pixelslength),
|
||||||
RQ.shiftBytes(masklength),
|
RQshiftBytes(masklength),
|
||||||
x, y, w, h);
|
x, y, w, h);
|
||||||
|
|
||||||
FBU.bytes = 0;
|
FBU.bytes = 0;
|
||||||
|
@ -1556,13 +1605,16 @@ pointerEvent = function(x, y) {
|
||||||
|
|
||||||
clientCutText = function(text) {
|
clientCutText = function(text) {
|
||||||
//Util.Debug(">> clientCutText");
|
//Util.Debug(">> clientCutText");
|
||||||
var arr;
|
var arr, i, n;
|
||||||
arr = [6]; // msg-type
|
arr = [6]; // msg-type
|
||||||
arr.push8(0); // padding
|
arr.push8(0); // padding
|
||||||
arr.push8(0); // padding
|
arr.push8(0); // padding
|
||||||
arr.push8(0); // padding
|
arr.push8(0); // padding
|
||||||
arr.push32(text.length);
|
arr.push32(text.length);
|
||||||
arr.pushStr(text);
|
n = text.length;
|
||||||
|
for (i=0; i < n; i+=1) {
|
||||||
|
arr.push(text.charCodeAt(i));
|
||||||
|
}
|
||||||
//Util.Debug("<< clientCutText:" + arr);
|
//Util.Debug("<< clientCutText:" + arr);
|
||||||
return arr;
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,68 +34,20 @@ if (!window.$) {
|
||||||
* Make arrays quack
|
* Make arrays quack
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Array.prototype.shift8 = function () {
|
|
||||||
return this.shift();
|
|
||||||
};
|
|
||||||
Array.prototype.push8 = function (num) {
|
Array.prototype.push8 = function (num) {
|
||||||
this.push(num & 0xFF);
|
this.push(num & 0xFF);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.prototype.shift16 = function () {
|
|
||||||
return (this.shift() << 8) +
|
|
||||||
(this.shift() );
|
|
||||||
};
|
|
||||||
Array.prototype.push16 = function (num) {
|
Array.prototype.push16 = function (num) {
|
||||||
this.push((num >> 8) & 0xFF,
|
this.push((num >> 8) & 0xFF,
|
||||||
(num ) & 0xFF );
|
(num ) & 0xFF );
|
||||||
};
|
};
|
||||||
Array.prototype.push16le = function (num) {
|
|
||||||
this.push((num ) & 0xFF,
|
|
||||||
(num >> 8) & 0xFF );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Array.prototype.shift32 = function () {
|
|
||||||
return (this.shift() << 24) +
|
|
||||||
(this.shift() << 16) +
|
|
||||||
(this.shift() << 8) +
|
|
||||||
(this.shift() );
|
|
||||||
};
|
|
||||||
Array.prototype.get32 = function (off) {
|
|
||||||
return (this[off ] << 24) +
|
|
||||||
(this[off + 1] << 16) +
|
|
||||||
(this[off + 2] << 8) +
|
|
||||||
(this[off + 3] );
|
|
||||||
};
|
|
||||||
Array.prototype.push32 = function (num) {
|
Array.prototype.push32 = function (num) {
|
||||||
this.push((num >> 24) & 0xFF,
|
this.push((num >> 24) & 0xFF,
|
||||||
(num >> 16) & 0xFF,
|
(num >> 16) & 0xFF,
|
||||||
(num >> 8) & 0xFF,
|
(num >> 8) & 0xFF,
|
||||||
(num ) & 0xFF );
|
(num ) & 0xFF );
|
||||||
};
|
};
|
||||||
Array.prototype.push32le = function (num) {
|
|
||||||
this.push((num ) & 0xFF,
|
|
||||||
(num >> 8) & 0xFF,
|
|
||||||
(num >> 16) & 0xFF,
|
|
||||||
(num >> 24) & 0xFF );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
Array.prototype.shiftStr = function (len) {
|
|
||||||
var arr = this.splice(0, len);
|
|
||||||
return arr.map(function (num) {
|
|
||||||
return String.fromCharCode(num); } ).join('');
|
|
||||||
};
|
|
||||||
Array.prototype.pushStr = function (str) {
|
|
||||||
var i, n = str.length;
|
|
||||||
for (i=0; i < n; i+=1) {
|
|
||||||
this.push(str.charCodeAt(i));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Array.prototype.shiftBytes = function (len) {
|
|
||||||
return this.splice(0, len);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ------------------------------------------------------
|
* ------------------------------------------------------
|
||||||
|
|
|
@ -45,6 +45,17 @@
|
||||||
var ANDsz = w * h * 4;
|
var ANDsz = w * h * 4;
|
||||||
var XORsz = Math.ceil( (w * h) / 8.0 );
|
var XORsz = Math.ceil( (w * h) / 8.0 );
|
||||||
|
|
||||||
|
// Push multi-byte little-endian values
|
||||||
|
arr.push16le = function (num) {
|
||||||
|
this.push((num ) & 0xFF,
|
||||||
|
(num >> 8) & 0xFF );
|
||||||
|
};
|
||||||
|
arr.push32le = function (num) {
|
||||||
|
this.push((num ) & 0xFF,
|
||||||
|
(num >> 8) & 0xFF,
|
||||||
|
(num >> 16) & 0xFF,
|
||||||
|
(num >> 24) & 0xFF );
|
||||||
|
};
|
||||||
|
|
||||||
// Main header
|
// Main header
|
||||||
arr.push16le(0); // Reserved
|
arr.push16le(0); // Reserved
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>VNC Test</title>
|
<title>VNC Playback</title>
|
||||||
<link rel="stylesheet" href="include/plain.css">
|
<link rel="stylesheet" href="include/plain.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
Loading…
Reference in New Issue