It was broken and unused. Remove it so we can simplify the code.
UI.initSetting('host', window.location.hostname);
UI.initSetting('port', port);
UI.initSetting('encrypt', (window.location.protocol === "https:"));
- UI.initSetting('true_color', true);
UI.initSetting('cursor', !isTouchDevice);
UI.initSetting('clip', false);
UI.initSetting('resize', 'off');
.addEventListener('click', UI.toggleSettingsPanel);
UI.addSettingChangeHandler('encrypt');
- UI.addSettingChangeHandler('true_color');
UI.addSettingChangeHandler('cursor');
UI.addSettingChangeHandler('cursor', UI.updateLocalCursor);
UI.addSettingChangeHandler('resize');
if (UI.connected) {
UI.disableSetting('encrypt');
- UI.disableSetting('true_color');
UI.disableSetting('shared');
UI.disableSetting('host');
UI.disableSetting('port');
UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
} else {
UI.enableSetting('encrypt');
- UI.enableSetting('true_color');
UI.enableSetting('shared');
UI.enableSetting('host');
UI.enableSetting('port');
// Refresh UI elements from saved cookies
UI.updateSetting('encrypt');
- UI.updateSetting('true_color');
if (cursorURIsSupported()) {
UI.updateSetting('cursor');
} else {
UI.closeConnectPanel();
UI.rfb.set_encrypt(UI.getSetting('encrypt'));
- UI.rfb.set_true_color(UI.getSetting('true_color'));
UI.rfb.set_shared(UI.getSetting('shared'));
UI.rfb.set_repeaterID(UI.getSetting('repeaterID'));
this._tile_y = 0;
set_defaults(this, defaults, {
- 'true_color': true,
- 'colourMap': [],
'scale': 1.0,
'viewport': false,
'render_mode': '',
}
if (this._prefer_js) {
- var bgr;
- if (this._true_color) {
- bgr = color;
- } else {
- bgr = this._colourMap[color[0]];
- }
- var red = bgr[2];
- var green = bgr[1];
- var blue = bgr[0];
+ var red = color[2];
+ var green = color[1];
+ var blue = color[0];
var data = this._tile.data;
for (var i = 0; i < width * height * 4; i += 4) {
// update sub-rectangle of the current tile
subTile: function (x, y, w, h, color) {
if (this._prefer_js) {
- var bgr;
- if (this._true_color) {
- bgr = color;
- } else {
- bgr = this._colourMap[color[0]];
- }
- var red = bgr[2];
- var green = bgr[1];
- var blue = bgr[0];
+ var red = color[2];
+ var green = color[1];
+ var blue = color[0];
var xend = x + w;
var yend = y + h;
'width': width,
'height': height,
});
- } else if (this._true_color) {
- this._bgrxImageData(x, y, width, height, arr, offset);
} else {
- this._cmapImageData(x, y, width, height, arr, offset);
+ this._bgrxImageData(x, y, width, height, arr, offset);
}
},
'width': width,
'height': height,
});
- } else if (this._true_color) {
- this._rgbImageData(x, y, width, height, arr, offset);
} else {
- // probably wrong?
- this._cmapImageData(x, y, width, height, arr, offset);
+ this._rgbImageData(x, y, width, height, arr, offset);
}
},
return;
}
- if (this._true_color) {
- Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h);
- } else {
- Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h, this._colourMap);
- }
+ Display.changeCursor(this._target, pixels, mask, hotx, hoty, w, h);
},
defaultCursor: function () {
},
_setFillColor: function (color) {
- var bgr;
- if (this._true_color) {
- bgr = color;
- } else {
- bgr = this._colourMap[color];
- }
-
- var newStyle = 'rgb(' + bgr[2] + ',' + bgr[1] + ',' + bgr[0] + ')';
+ var newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
if (newStyle !== this._prevDrawStyle) {
this._drawCtx.fillStyle = newStyle;
this._prevDrawStyle = newStyle;
this._damage(x, y, img.width, img.height);
},
- _cmapImageData: function (x, y, width, height, arr, offset) {
- var img = this._drawCtx.createImageData(width, height);
- var data = img.data;
- var cmap = this._colourMap;
- for (var i = 0, j = offset; i < width * height * 4; i += 4, j++) {
- var bgr = cmap[arr[j]];
- data[i] = bgr[2];
- data[i + 1] = bgr[1];
- data[i + 2] = bgr[0];
- data[i + 3] = 255; // Alpha
- }
- this._drawCtx.putImageData(img, x, y);
- this._damage(x, y, img.width, img.height);
- },
-
_renderQ_push: function (action) {
this._renderQ.push(action);
if (this._renderQ.length === 1) {
['target', 'wo', 'dom'], // Canvas element for rendering
['context', 'ro', 'raw'], // Canvas 2D context for rendering (read-only)
['logo', 'rw', 'raw'], // Logo to display when cleared: {"width": w, "height": h, "type": mime-type, "data": data}
- ['true_color', 'rw', 'bool'], // Use true-color pixel data
- ['colourMap', 'rw', 'arr'], // Colour map array (when not true-color)
['scale', 'rw', 'float'], // Display area scale factor 0.0 - 1.0
['viewport', 'rw', 'bool'], // Use viewport clipping
['width', 'ro', 'int'], // Display area width
]);
// Class Methods
-Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h, cmap) {
+Display.changeCursor = function (target, pixels, mask, hotx, hoty, w, h) {
if ((w === 0) || (h === 0)) {
target.style.cursor = 'none';
return;
for (x = 0; x < w; x++) {
var idx = y * Math.ceil(w / 8) + Math.floor(x / 8);
var alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0;
- if (cmap) {
- idx = (w * y) + x;
- var rgb = cmap[pixels[idx]];
- cur.push(rgb[0]); // red
- cur.push(rgb[1]); // green
- cur.push(rgb[2]); // blue
- cur.push(alpha); // alpha
- } else {
- idx = ((w * y) + x) * 4;
- cur.push(pixels[idx + 2]); // red
- cur.push(pixels[idx + 1]); // green
- cur.push(pixels[idx]); // blue
- cur.push(alpha); // alpha
- }
+ idx = ((w * y) + x) * 4;
+ cur.push(pixels[idx + 2]); // red
+ cur.push(pixels[idx + 1]); // green
+ cur.push(pixels[idx]); // blue
+ cur.push(alpha); // alpha
}
}
zlib: [] // TIGHT zlib streams
};
- this._fb_Bpp = 4;
- this._fb_depth = 3;
this._fb_width = 0;
this._fb_height = 0;
this._fb_name = "";
'target': 'null', // VNC display rendering Canvas object
'focusContainer': document, // DOM element that captures keyboard input
'encrypt': false, // Use TLS/SSL/wss encryption
- 'true_color': true, // Request true color pixel data
'local_cursor': false, // Request locally rendered cursor
'shared': true, // Request shared mode
'view_only': false, // Disable client mouse/keyboard
// we're past the point where we could backtrack, so it's safe to call this
this._onDesktopName(this, this._fb_name);
- if (this._true_color && this._fb_name === "Intel(r) AMT KVM") {
- Log.Warn("Intel AMT KVM only supports 8/16 bit depths. Disabling true color");
- this._true_color = false;
- }
-
- this._display.set_true_color(this._true_color);
this._display.resize(this._fb_width, this._fb_height);
this._onFBResize(this, this._fb_width, this._fb_height);
if (!this._view_only) { this._keyboard.grab(); }
if (!this._view_only) { this._mouse.grab(); }
- if (this._true_color) {
- this._fb_Bpp = 4;
- this._fb_depth = 3;
- } else {
- this._fb_Bpp = 1;
- this._fb_depth = 1;
- }
-
- RFB.messages.pixelFormat(this._sock, this._fb_Bpp, this._fb_depth, this._true_color);
- RFB.messages.clientEncodings(this._sock, this._encodings, this._local_cursor, this._true_color);
+ RFB.messages.pixelFormat(this._sock, 4, 3, true);
+ RFB.messages.clientEncodings(this._sock, this._encodings, this._local_cursor);
RFB.messages.fbUpdateRequest(this._sock, false, 0, 0, this._fb_width, this._fb_height);
this._timing.fbu_rt_start = (new Date()).getTime();
_handle_set_colour_map_msg: function () {
Log.Debug("SetColorMapEntries");
- this._sock.rQskip8(); // Padding
-
- var first_colour = this._sock.rQshift16();
- var num_colours = this._sock.rQshift16();
- if (this._sock.rQwait('SetColorMapEntries', num_colours * 6, 6)) { return false; }
-
- for (var c = 0; c < num_colours; c++) {
- var red = parseInt(this._sock.rQshift16() / 256, 10);
- var green = parseInt(this._sock.rQshift16() / 256, 10);
- var blue = parseInt(this._sock.rQshift16() / 256, 10);
- this._display.set_colourMap([blue, green, red], first_colour + c);
- }
- Log.Debug("colourMap: " + this._display.get_colourMap());
- Log.Info("Registered " + num_colours + " colourMap entries");
- return true;
+ return this._fail("Protocol error", "Unexpected SetColorMapEntries message");
},
_handle_server_cut_text: function () {
['target', 'wo', 'dom'], // VNC display rendering Canvas object
['focusContainer', 'wo', 'dom'], // DOM element that captures keyboard input
['encrypt', 'rw', 'bool'], // Use TLS/SSL/wss encryption
- ['true_color', 'rw', 'bool'], // Request true color pixel data
['local_cursor', 'rw', 'bool'], // Request locally rendered cursor
['shared', 'rw', 'bool'], // Request shared mode
['view_only', 'rw', 'bool'], // Disable client mouse/keyboard
// Need to send an updated list of encodings if we are connected
if (this._rfb_connection_state === "connected") {
- RFB.messages.clientEncodings(this._sock, this._encodings, cursor,
- this._true_color);
+ RFB.messages.clientEncodings(this._sock, this._encodings, cursor);
}
};
sock.flush();
},
- clientEncodings: function (sock, encodings, local_cursor, true_color) {
+ clientEncodings: function (sock, encodings, local_cursor) {
var buff = sock._sQ;
var offset = sock._sQlen;
for (i = 0; i < encodings.length; i++) {
if (encodings[i][0] === "Cursor" && !local_cursor) {
Log.Debug("Skipping Cursor pseudo-encoding");
- } else if (encodings[i][0] === "TIGHT" && !true_color) {
- // TODO: remove this when we have tight+non-true-color
- Log.Warn("Skipping tight as it is only supported with true color");
} else {
var enc = encodings[i][1];
buff[j] = enc >> 24;
this._FBU.lines = this._FBU.height;
}
- this._FBU.bytes = this._FBU.width * this._fb_Bpp; // at least a line
+ this._FBU.bytes = this._FBU.width * 4; // at least a line
if (this._sock.rQwait("RAW", this._FBU.bytes)) { return false; }
var cur_y = this._FBU.y + (this._FBU.height - this._FBU.lines);
var curr_height = Math.min(this._FBU.lines,
- Math.floor(this._sock.rQlen() / (this._FBU.width * this._fb_Bpp)));
+ Math.floor(this._sock.rQlen() / (this._FBU.width * 4)));
this._display.blitImage(this._FBU.x, cur_y, this._FBU.width,
curr_height, this._sock.get_rQ(),
this._sock.get_rQi());
- this._sock.rQskipBytes(this._FBU.width * curr_height * this._fb_Bpp);
+ this._sock.rQskipBytes(this._FBU.width * curr_height * 4);
this._FBU.lines -= curr_height;
if (this._FBU.lines > 0) {
- this._FBU.bytes = this._FBU.width * this._fb_Bpp; // At least another line
+ this._FBU.bytes = this._FBU.width * 4; // At least another line
} else {
this._FBU.rects--;
this._FBU.bytes = 0;
RRE: function () {
var color;
if (this._FBU.subrects === 0) {
- this._FBU.bytes = 4 + this._fb_Bpp;
- if (this._sock.rQwait("RRE", 4 + this._fb_Bpp)) { return false; }
+ this._FBU.bytes = 4 + 4;
+ if (this._sock.rQwait("RRE", 4 + 4)) { return false; }
this._FBU.subrects = this._sock.rQshift32();
- color = this._sock.rQshiftBytes(this._fb_Bpp); // Background
+ color = this._sock.rQshiftBytes(4); // Background
this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, color);
}
- while (this._FBU.subrects > 0 && this._sock.rQlen() >= (this._fb_Bpp + 8)) {
- color = this._sock.rQshiftBytes(this._fb_Bpp);
+ while (this._FBU.subrects > 0 && this._sock.rQlen() >= (4 + 8)) {
+ color = this._sock.rQshiftBytes(4);
var x = this._sock.rQshift16();
var y = this._sock.rQshift16();
var width = this._sock.rQshift16();
if (this._FBU.subrects > 0) {
var chunk = Math.min(this._rre_chunk_sz, this._FBU.subrects);
- this._FBU.bytes = (this._fb_Bpp + 8) * chunk;
+ this._FBU.bytes = (4 + 8) * chunk;
} else {
this._FBU.rects--;
this._FBU.bytes = 0;
// Figure out how much we are expecting
if (subencoding & 0x01) { // Raw
- this._FBU.bytes += w * h * this._fb_Bpp;
+ this._FBU.bytes += w * h * 4;
} else {
if (subencoding & 0x02) { // Background
- this._FBU.bytes += this._fb_Bpp;
+ this._FBU.bytes += 4;
}
if (subencoding & 0x04) { // Foreground
- this._FBU.bytes += this._fb_Bpp;
+ this._FBU.bytes += 4;
}
if (subencoding & 0x08) { // AnySubrects
this._FBU.bytes++; // Since we aren't shifting it off
if (this._sock.rQwait("hextile subrects header", this._FBU.bytes)) { return false; }
subrects = rQ[rQi + this._FBU.bytes - 1]; // Peek
if (subencoding & 0x10) { // SubrectsColoured
- this._FBU.bytes += subrects * (this._fb_Bpp + 2);
+ this._FBU.bytes += subrects * (4 + 2);
} else {
this._FBU.bytes += subrects * 2;
}
rQi += this._FBU.bytes - 1;
} else {
if (this._FBU.subencoding & 0x02) { // Background
- if (this._fb_Bpp == 1) {
- this._FBU.background = rQ[rQi];
- } else {
- // fb_Bpp is 4
- this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
- }
- rQi += this._fb_Bpp;
+ this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
+ rQi += 4;
}
if (this._FBU.subencoding & 0x04) { // Foreground
- if (this._fb_Bpp == 1) {
- this._FBU.foreground = rQ[rQi];
- } else {
- // this._fb_Bpp is 4
- this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
- }
- rQi += this._fb_Bpp;
+ this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
+ rQi += 4;
}
this._display.startTile(x, y, w, h, this._FBU.background);
for (var s = 0; s < subrects; s++) {
var color;
if (this._FBU.subencoding & 0x10) { // SubrectsColoured
- if (this._fb_Bpp === 1) {
- color = rQ[rQi];
- } else {
- // _fb_Bpp is 4
- color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
- }
- rQi += this._fb_Bpp;
+ color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
+ rQi += 4;
} else {
color = this._FBU.foreground;
}
},
display_tight: function (isTightPNG) {
- if (this._fb_depth === 1) {
- this._fail("Internal error",
- "Tight protocol handler only implements " +
- "true color mode");
- }
-
this._FBU.bytes = 1; // compression-control byte
if (this._sock.rQwait("TIGHT compression-control", this._FBU.bytes)) { return false; }
var handlePalette = function () {
var numColors = rQ[rQi + 2] + 1;
- var paletteSize = numColors * this._fb_depth;
+ var paletteSize = numColors * 3;
this._FBU.bytes += paletteSize;
if (this._sock.rQwait("TIGHT palette " + cmode, this._FBU.bytes)) { return false; }
var handleCopy = function () {
var raw = false;
- var uncompressedSize = this._FBU.width * this._FBU.height * this._fb_depth;
+ var uncompressedSize = this._FBU.width * this._FBU.height * 3;
if (uncompressedSize < 12) {
raw = true;
cl_header = 0;
}
switch (cmode) {
- // fill use fb_depth because TPIXELs drop the padding byte
+ // fill use depth because TPIXELs drop the padding byte
case "fill": // TPIXEL
- this._FBU.bytes += this._fb_depth;
+ this._FBU.bytes += 3;
break;
case "jpeg": // max clength
this._FBU.bytes += 3;
var w = this._FBU.width;
var h = this._FBU.height;
- var pixelslength = w * h * this._fb_Bpp;
+ var pixelslength = w * h * 4;
var masklength = Math.floor((w + 7) / 8) * h;
this._FBU.bytes = pixelslength + masklength;
expect(display).to.have.displayed(checked_data);
});
- it('should support drawing solid colors with color maps', function () {
- display._true_color = false;
- display.set_colourMap({ 0: [0xff, 0, 0], 1: [0, 0xff, 0] });
- display.fillRect(0, 0, 4, 4, 1);
- display.fillRect(0, 0, 2, 2, 0);
- display.fillRect(2, 2, 2, 2, 0);
- display.flip();
- expect(display).to.have.displayed(checked_data);
- });
-
- it('should support drawing blit images with color maps', function () {
- display._true_color = false;
- display.set_colourMap({ 1: [0xff, 0, 0], 0: [0, 0xff, 0] });
- var data = [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1].map(function (elem) { return [elem]; });
- display.blitImage(0, 0, 4, 4, data, 0);
- display.flip();
- expect(display).to.have.displayed(checked_data);
- });
-
it('should support drawing an image object via #drawImage', function () {
var img = make_image_canvas(checked_data);
display.drawImage(img, 0, 0);
expect(client._rfb_connection_state).to.equal('connected');
});
- it('should set the true color mode on the display to the configuration variable', function () {
- client.set_true_color(false);
- sinon.spy(client._display, 'set_true_color');
- send_server_init({ true_color: 1 }, client);
- expect(client._display.set_true_color).to.have.been.calledOnce;
- expect(client._display.set_true_color).to.have.been.calledWith(false);
- });
-
it('should call the resize callback and resize the display', function () {
client.set_onFBResize(sinon.spy());
sinon.spy(client._display, 'resize');
expect(client._mouse.grab).to.have.been.calledOnce;
});
- it('should set the BPP and depth to 4 and 3 respectively if in true color mode', function () {
- client.set_true_color(true);
- send_server_init({}, client);
- expect(client._fb_Bpp).to.equal(4);
- expect(client._fb_depth).to.equal(3);
- });
-
- it('should set the BPP and depth to 1 and 1 respectively if not in true color mode', function () {
- client.set_true_color(false);
- send_server_init({}, client);
- expect(client._fb_Bpp).to.equal(1);
- expect(client._fb_depth).to.equal(1);
- });
-
// TODO(directxman12): test the various options in this configuration matrix
it('should reply with the pixel format, client encodings, and initial update request', function () {
- client.set_true_color(true);
client.set_local_cursor(false);
// we skip the cursor encoding
var expected = {_sQ: new Uint8Array(34 + 4 * (client._encodings.length - 1)),
client._fb_width = 4;
client._fb_height = 4;
client._display.resize(4, 4);
- client._fb_Bpp = 4;
});
it('should handle the RAW encoding', function () {
client._fb_width = 4;
client._fb_height = 4;
client._display.resize(4, 4);
- client._fb_Bpp = 4;
});
it('should handle a tile with fg, bg specified, normal subrects', function () {
client._fb_width = 4;
client._fb_height = 4;
client._display.resize(4, 4);
- client._fb_Bpp = 4;
sinon.spy(client._display, 'resize');
client.set_onFBResize(sinon.spy());
});
});
});
- it('should set the colour map on the display on SetColourMapEntries', function () {
- var expected_cm = [];
- var data = [1, 0, 0, 1, 0, 4];
- var i;
- for (i = 0; i < 4; i++) {
- expected_cm[i + 1] = [i * 10, i * 10 + 1, i * 10 + 2];
- push16(data, expected_cm[i + 1][2] << 8);
- push16(data, expected_cm[i + 1][1] << 8);
- push16(data, expected_cm[i + 1][0] << 8);
- }
-
- client._sock._websocket._receive_data(new Uint8Array(data));
- expect(client._display.get_colourMap()).to.deep.equal(expected_cm);
- });
-
describe('XVP Message Handling', function () {
beforeEach(function () {
client = make_rfb();
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
Connect parameters are provided in query string:
- http://example.com/?host=HOST&port=PORT&encrypt=1&true_color=1
+ http://example.com/?host=HOST&port=PORT&encrypt=1
or the fragment:
- http://example.com/#host=HOST&port=PORT&encrypt=1&true_color=1
+ http://example.com/#host=HOST&port=PORT&encrypt=1
-->
<title>noVNC</title>
<li>
<div class="noVNC_expander">Advanced</div>
<div><ul>
- <li>
- <label><input id="noVNC_setting_true_color" type="checkbox" checked /> True Color</label>
- </li>
<li>
<label><input id="noVNC_setting_cursor" type="checkbox" /> Local Cursor</label>
</li>
This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
Connect parameters are provided in query string:
- http://example.com/?host=HOST&port=PORT&encrypt=1&true_color=1
+ http://example.com/?host=HOST&port=PORT&encrypt=1
or the fragment:
- http://example.com/#host=HOST&port=PORT&encrypt=1&true_color=1
+ http://example.com/#host=HOST&port=PORT&encrypt=1
-->
<title>noVNC</title>
'encrypt': WebUtil.getConfigVar('encrypt',
(window.location.protocol === "https:")),
'repeaterID': WebUtil.getConfigVar('repeaterID', ''),
- 'true_color': WebUtil.getConfigVar('true_color', true),
'local_cursor': WebUtil.getConfigVar('cursor', true),
'shared': WebUtil.getConfigVar('shared', true),
'view_only': WebUtil.getConfigVar('view_only', false),