Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc00821eba | |||
| 0331495382 | |||
| 282834caf1 | |||
| ed7f8c3886 | |||
| 4865278dee | |||
| b2e8311de6 | |||
| df89129ff0 | |||
| 1f84c99938 | |||
| 40ac6f0ab6 | |||
| c42ea22525 | |||
| fda40d8927 | |||
| bd6874e087 | |||
| 795fca23dc | |||
| a86f97e284 | |||
| dbaf49f570 | |||
| ec31f82eda | |||
| e2f1ff8048 | |||
| 58ca1978ea |
@@ -0,0 +1,54 @@
|
||||
How to contribute to noVNC
|
||||
==========================
|
||||
|
||||
We accept code via pull requests on GitHub. There are several guidelines that
|
||||
we expect contributors submitting code requests to follow. If you have issues
|
||||
following any of these guidelines, feel free to drop us a line by leaving a
|
||||
comment in the code request or sending us an email.
|
||||
|
||||
Contributing Guidelines
|
||||
-----------------------
|
||||
|
||||
* While we don't have an official coding style guide, please try to follow
|
||||
the general coding style of the existing code.
|
||||
** Use four spaces instead of tabs
|
||||
** prefix private variables and functions with an `_`
|
||||
|
||||
* Please try to include unit tests for your code. For instance, if you
|
||||
introduce a new encoding, add a test to `tests/test.rfb.js` under the
|
||||
"Encoding Handlers" section (basically, input a small pattern in your
|
||||
encoding and make sure the pattern gets displayed correctly). If you
|
||||
fix a bug, try to add a unit test that would have caught that bug
|
||||
(if possible -- some bugs, especially visual ones, are hard to test for).
|
||||
|
||||
* Squash your commits down in to a clean commit history. For instance, there
|
||||
should not be "cleanup" commits where you fix issues in previous commits in
|
||||
the same pull request. Before you go to commit, use `git rebase -i` to
|
||||
squash these changes into the relevant commits. For instance, a good commit
|
||||
history might look like "Added support for FOO encoding, Added support for
|
||||
BAR message, Placed Button in UI to Trigger BAR" (where each comma denotes
|
||||
a separate commit).
|
||||
|
||||
* Add both a title and description to your commit, if possible. Place more
|
||||
detail on what you did in the description.
|
||||
|
||||
Running the unit tests
|
||||
----------------------
|
||||
|
||||
There are two ways to run the unit tests. For both ways, you should first run
|
||||
`npm install` (not as root).
|
||||
|
||||
The first way to run the tests is to run `npm test`. This will run all the
|
||||
tests in the headless PhantomJS browser (which uses WebKit).
|
||||
|
||||
The second way to run the tests is using the `tests/run_from_console.js` file.
|
||||
This way is a bit more flexible, and can provide more information about what
|
||||
went wrong. To run all the tests, simply run `tests/run_from_console.js`.
|
||||
To run a specific test file, you can use the `-t path/to/test/file.js` option.
|
||||
If you wish to simply generate the HTML for the test, use the `-g` option, and
|
||||
the path to the temporary HTML file will be written to standard out. To open
|
||||
this file in your default browser automatically, pass the `-o` option as well.
|
||||
More information can be found by passing the `--help` or `-h` option.
|
||||
|
||||
|
||||
Thanks, and happy coding!
|
||||
+7
-1
@@ -318,7 +318,7 @@ var Display;
|
||||
// Clearing the current viewport first fixes the issue
|
||||
this._drawCtx.clearRect(0, 0, this._viewportLoc.w, this._viewportLoc.h);
|
||||
}
|
||||
this.resize(640, 20);
|
||||
this.resize(240, 20);
|
||||
this._drawCtx.clearRect(0, 0, this._viewportLoc.w, this._viewportLoc.h);
|
||||
}
|
||||
|
||||
@@ -713,6 +713,12 @@ var Display;
|
||||
cur.push(rgb[1]); // green
|
||||
cur.push(rgb[0]); // red
|
||||
cur.push(alpha); // alpha
|
||||
} else {
|
||||
idx = ((w0 * y) + x) * 4;
|
||||
cur.push(pixels[idx + 2]); // blue
|
||||
cur.push(pixels[idx + 1]); // green
|
||||
cur.push(pixels[idx]); // red
|
||||
cur.push(alpha); // alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+67
-67
@@ -31,7 +31,7 @@ var kbdUtil = (function() {
|
||||
function hasShortcutModifier(charModifier, currentModifiers) {
|
||||
var mods = {};
|
||||
for (var key in currentModifiers) {
|
||||
if (parseInt(key) !== 0xffe1) {
|
||||
if (parseInt(key) !== XK_Shift_L) {
|
||||
mods[key] = currentModifiers[key];
|
||||
}
|
||||
}
|
||||
@@ -65,24 +65,18 @@ var kbdUtil = (function() {
|
||||
// Helper object tracking modifier key state
|
||||
// and generates fake key events to compensate if it gets out of sync
|
||||
function ModifierSync(charModifier) {
|
||||
var ctrl = 0xffe3;
|
||||
var alt = 0xffe9;
|
||||
var altGr = 0xfe03;
|
||||
var shift = 0xffe1;
|
||||
var meta = 0xffe7;
|
||||
|
||||
if (!charModifier) {
|
||||
if (isMac()) {
|
||||
// on Mac, Option (AKA Alt) is used as a char modifier
|
||||
charModifier = [alt];
|
||||
charModifier = [XK_Alt_L];
|
||||
}
|
||||
else if (isWindows()) {
|
||||
// on Windows, Ctrl+Alt is used as a char modifier
|
||||
charModifier = [alt, ctrl];
|
||||
charModifier = [XK_Alt_L, XK_Control_L];
|
||||
}
|
||||
else if (isLinux()) {
|
||||
// on Linux, AltGr is used as a char modifier
|
||||
charModifier = [altGr];
|
||||
// on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier
|
||||
charModifier = [XK_ISO_Level3_Shift];
|
||||
}
|
||||
else {
|
||||
charModifier = [];
|
||||
@@ -90,11 +84,11 @@ var kbdUtil = (function() {
|
||||
}
|
||||
|
||||
var state = {};
|
||||
state[ctrl] = false;
|
||||
state[alt] = false;
|
||||
state[altGr] = false;
|
||||
state[shift] = false;
|
||||
state[meta] = false;
|
||||
state[XK_Control_L] = false;
|
||||
state[XK_Alt_L] = false;
|
||||
state[XK_ISO_Level3_Shift] = false;
|
||||
state[XK_Shift_L] = false;
|
||||
state[XK_Meta_L] = false;
|
||||
|
||||
function sync(evt, keysym) {
|
||||
var result = [];
|
||||
@@ -102,25 +96,30 @@ var kbdUtil = (function() {
|
||||
return {keysym: keysyms.lookup(keysym), type: state[keysym] ? 'keydown' : 'keyup'};
|
||||
}
|
||||
|
||||
if (evt.ctrlKey !== undefined && evt.ctrlKey !== state[ctrl] && keysym !== ctrl) {
|
||||
state[ctrl] = evt.ctrlKey;
|
||||
result.push(syncKey(ctrl));
|
||||
if (evt.ctrlKey !== undefined &&
|
||||
evt.ctrlKey !== state[XK_Control_L] && keysym !== XK_Control_L) {
|
||||
state[XK_Control_L] = evt.ctrlKey;
|
||||
result.push(syncKey(XK_Control_L));
|
||||
}
|
||||
if (evt.altKey !== undefined && evt.altKey !== state[alt] && keysym !== alt) {
|
||||
state[alt] = evt.altKey;
|
||||
result.push(syncKey(alt));
|
||||
if (evt.altKey !== undefined &&
|
||||
evt.altKey !== state[XK_Alt_L] && keysym !== XK_Alt_L) {
|
||||
state[XK_Alt_L] = evt.altKey;
|
||||
result.push(syncKey(XK_Alt_L));
|
||||
}
|
||||
if (evt.altGraphKey !== undefined && evt.altGraphKey !== state[altGr] && keysym !== altGr) {
|
||||
state[altGr] = evt.altGraphKey;
|
||||
result.push(syncKey(altGr));
|
||||
if (evt.altGraphKey !== undefined &&
|
||||
evt.altGraphKey !== state[XK_ISO_Level3_Shift] && keysym !== XK_ISO_Level3_Shift) {
|
||||
state[XK_ISO_Level3_Shift] = evt.altGraphKey;
|
||||
result.push(syncKey(XK_ISO_Level3_Shift));
|
||||
}
|
||||
if (evt.shiftKey !== undefined && evt.shiftKey !== state[shift] && keysym !== shift) {
|
||||
state[shift] = evt.shiftKey;
|
||||
result.push(syncKey(shift));
|
||||
if (evt.shiftKey !== undefined &&
|
||||
evt.shiftKey !== state[XK_Shift_L] && keysym !== XK_Shift_L) {
|
||||
state[XK_Shift_L] = evt.shiftKey;
|
||||
result.push(syncKey(XK_Shift_L));
|
||||
}
|
||||
if (evt.metaKey !== undefined && evt.metaKey !== state[meta] && keysym !== meta) {
|
||||
state[meta] = evt.metaKey;
|
||||
result.push(syncKey(meta));
|
||||
if (evt.metaKey !== undefined &&
|
||||
evt.metaKey !== state[XK_Meta_L] && keysym !== XK_Meta_L) {
|
||||
state[XK_Meta_L] = evt.metaKey;
|
||||
result.push(syncKey(XK_Meta_L));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -211,21 +210,21 @@ var kbdUtil = (function() {
|
||||
return shiftPressed ? keycode : keycode + 32; // A-Z
|
||||
}
|
||||
if (keycode >= 0x60 && keycode <= 0x69) {
|
||||
return 0xffb0 + (keycode - 0x60); // numpad 0-9
|
||||
return XK_KP_0 + (keycode - 0x60); // numpad 0-9
|
||||
}
|
||||
|
||||
switch(keycode) {
|
||||
case 0x20: return 0x20; // space
|
||||
case 0x6a: return 0xffaa; // multiply
|
||||
case 0x6b: return 0xffab; // add
|
||||
case 0x6c: return 0xffac; // separator
|
||||
case 0x6d: return 0xffad; // subtract
|
||||
case 0x6e: return 0xffae; // decimal
|
||||
case 0x6f: return 0xffaf; // divide
|
||||
case 0xbb: return 0x2b; // +
|
||||
case 0xbc: return 0x2c; // ,
|
||||
case 0xbd: return 0x2d; // -
|
||||
case 0xbe: return 0x2e; // .
|
||||
case 0x20: return XK_space;
|
||||
case 0x6a: return XK_KP_Multiply;
|
||||
case 0x6b: return XK_KP_Add;
|
||||
case 0x6c: return XK_KP_Separator;
|
||||
case 0x6d: return XK_KP_Subtract;
|
||||
case 0x6e: return XK_KP_Decimal;
|
||||
case 0x6f: return XK_KP_Divide;
|
||||
case 0xbb: return XK_plus;
|
||||
case 0xbc: return XK_comma;
|
||||
case 0xbd: return XK_minus;
|
||||
case 0xbe: return XK_period;
|
||||
}
|
||||
|
||||
return nonCharacterKey({keyCode: keycode});
|
||||
@@ -239,43 +238,44 @@ var kbdUtil = (function() {
|
||||
var keycode = evt.keyCode;
|
||||
|
||||
if (keycode >= 0x70 && keycode <= 0x87) {
|
||||
return 0xffbe + keycode - 0x70; // F1-F24
|
||||
return XK_F1 + keycode - 0x70; // F1-F24
|
||||
}
|
||||
switch (keycode) {
|
||||
|
||||
case 8 : return 0xFF08; // BACKSPACE
|
||||
case 13 : return 0xFF0D; // ENTER
|
||||
case 8 : return XK_BackSpace;
|
||||
case 13 : return XK_Return;
|
||||
|
||||
case 9 : return 0xFF09; // TAB
|
||||
case 9 : return XK_Tab;
|
||||
|
||||
case 27 : return 0xFF1B; // ESCAPE
|
||||
case 46 : return 0xFFFF; // DELETE
|
||||
case 27 : return XK_Escape;
|
||||
case 46 : return XK_Delete;
|
||||
|
||||
case 36 : return 0xFF50; // HOME
|
||||
case 35 : return 0xFF57; // END
|
||||
case 33 : return 0xFF55; // PAGE_UP
|
||||
case 34 : return 0xFF56; // PAGE_DOWN
|
||||
case 45 : return 0xFF63; // INSERT
|
||||
case 36 : return XK_Home;
|
||||
case 35 : return XK_End;
|
||||
case 33 : return XK_Page_Up;
|
||||
case 34 : return XK_Page_Down;
|
||||
case 45 : return XK_Insert;
|
||||
|
||||
case 37 : return 0xFF51; // LEFT
|
||||
case 38 : return 0xFF52; // UP
|
||||
case 39 : return 0xFF53; // RIGHT
|
||||
case 40 : return 0xFF54; // DOWN
|
||||
case 16 : return 0xFFE1; // SHIFT
|
||||
case 17 : return 0xFFE3; // CONTROL
|
||||
case 18 : return 0xFFE9; // Left ALT (Mac Option)
|
||||
case 37 : return XK_Left;
|
||||
case 38 : return XK_Up;
|
||||
case 39 : return XK_Right;
|
||||
case 40 : return XK_Down;
|
||||
|
||||
case 224 : return 0xFE07; // Meta
|
||||
case 225 : return 0xFE03; // AltGr
|
||||
case 91 : return 0xFFEC; // Super_L (Win Key)
|
||||
case 92 : return 0xFFED; // Super_R (Win Key)
|
||||
case 93 : return 0xFF67; // Menu (Win Menu), Mac Command
|
||||
case 16 : return XK_Shift_L;
|
||||
case 17 : return XK_Control_L;
|
||||
case 18 : return XK_Alt_L; // also: Option-key on Mac
|
||||
|
||||
case 224 : return XK_Meta_L;
|
||||
case 225 : return XK_ISO_Level3_Shift; // AltGr
|
||||
case 91 : return XK_Super_L; // also: Windows-key
|
||||
case 92 : return XK_Super_R; // also: Windows-key
|
||||
case 93 : return XK_Menu; // also: Windows-Menu, Command on Mac
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
return {
|
||||
hasShortcutModifier : hasShortcutModifier,
|
||||
hasCharModifier : hasCharModifier,
|
||||
hasCharModifier : hasCharModifier,
|
||||
ModifierSync : ModifierSync,
|
||||
getKey : getKey,
|
||||
getKeysym : getKeysym,
|
||||
|
||||
@@ -170,6 +170,8 @@ XK_Super_R = 0xffec, /* Right super */
|
||||
XK_Hyper_L = 0xffed, /* Left hyper */
|
||||
XK_Hyper_R = 0xffee, /* Right hyper */
|
||||
|
||||
XK_ISO_Level3_Shift = 0xfe03, /* AltGr */
|
||||
|
||||
/*
|
||||
* Latin 1
|
||||
* (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
|
||||
|
||||
+8
-9
@@ -252,12 +252,12 @@ var RFB;
|
||||
Util.Info("Sending Ctrl-Alt-Del");
|
||||
|
||||
var arr = [];
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFE3, 1)); // Control
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFE9, 1)); // Alt
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFFF, 1)); // Delete
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFFF, 0)); // Delete
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFE9, 0)); // Alt
|
||||
arr = arr.concat(RFB.messages.keyEvent(0xFFE3, 0)); // Control
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Control_L, 1));
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Alt_L, 1));
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Delete, 1));
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Delete, 0));
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Alt_L, 0));
|
||||
arr = arr.concat(RFB.messages.keyEvent(XK_Control_L, 0));
|
||||
this._sock.send(arr);
|
||||
},
|
||||
|
||||
@@ -316,7 +316,7 @@ var RFB;
|
||||
uri += '://' + this._rfb_host + ':' + this._rfb_port + '/' + this._rfb_path;
|
||||
Util.Info("connecting to " + uri);
|
||||
|
||||
this._sock.open(uri, this._sockProtocols);
|
||||
this._sock.open(uri, this._wsProtocols);
|
||||
|
||||
Util.Debug("<< RFB.connect");
|
||||
},
|
||||
@@ -1496,8 +1496,7 @@ var RFB;
|
||||
// Weird: ignore blanks are RAW
|
||||
Util.Debug(" Ignoring blank after RAW");
|
||||
} else {
|
||||
this._display.fillRect(x, y, w, h, rQ, rQi);
|
||||
rQi += this._FBU.bytes - 1;
|
||||
this._display.fillRect(x, y, w, h, this._FBU.background);
|
||||
}
|
||||
} else if (this._FBU.subencoding & 0x01) { // Raw
|
||||
this._display.blitImage(x, y, w, h, rQ, rQi);
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ var UI;
|
||||
"keysymdef.js", "keyboard.js", "input.js", "display.js",
|
||||
"jsunzip.js", "rfb.js", "keysym.js"]);
|
||||
|
||||
var UI = {
|
||||
UI = {
|
||||
|
||||
rfb_state : 'loaded',
|
||||
settingsOpen : false,
|
||||
|
||||
+15
-15
@@ -28,23 +28,23 @@
|
||||
"devDependencies": {
|
||||
"ansi": "^0.3.0",
|
||||
"casperjs": "^1.1.0-beta3",
|
||||
"chai": "^1.9.1",
|
||||
"commander": "^2.2.0",
|
||||
"karma": "^0.12.16",
|
||||
"chai": "^1.10.0",
|
||||
"commander": "^2.5.0",
|
||||
"karma": "^0.12.25",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-mocha": "^0.1.4",
|
||||
"karma-mocha-reporter": "^0.2.5",
|
||||
"karma-mocha": "^0.1.9",
|
||||
"karma-mocha-reporter": "^0.3.1",
|
||||
"karma-phantomjs-launcher": "^0.1.4",
|
||||
"karma-sauce-launcher": "^0.2.8",
|
||||
"karma-sauce-launcher": "^0.2.10",
|
||||
"karma-sinon": "^1.0.3",
|
||||
"karma-sinon-chai": "^0.1.6",
|
||||
"mocha": "^1.20.1",
|
||||
"open": "0.0.5",
|
||||
"phantom": "^0.6.3",
|
||||
"phantomjs": "^1.9.7-9",
|
||||
"sinon": "^1.10.2",
|
||||
"sinon-chai": "^2.5.0",
|
||||
"spooky": "^0.2.4",
|
||||
"temp": "^0.8.0"
|
||||
"karma-sinon-chai-latest": "^0.1.0",
|
||||
"mocha": "^2.0.1",
|
||||
"open": "^0.0.5",
|
||||
"phantom": "^0.7.0",
|
||||
"phantomjs": "^1.9.12",
|
||||
"sinon": "^1.12.1",
|
||||
"sinon-chai": "^2.6.0",
|
||||
"spooky": "^0.2.5",
|
||||
"temp": "^0.8.1"
|
||||
}
|
||||
}
|
||||
|
||||
+30
-4
@@ -1083,8 +1083,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||
|
||||
it('should send an update request if there is sufficient data', function () {
|
||||
var expected_cdr = { cleanBox: { x: 0, y: 0, w: 0, h: 0 },
|
||||
dirtyBoxes: [ { x: 0, y: 0, w: 640, h: 20 } ] };
|
||||
var expected_msg = RFB.messages.fbUpdateRequests(expected_cdr, 640, 20);
|
||||
dirtyBoxes: [ { x: 0, y: 0, w: 240, h: 20 } ] };
|
||||
var expected_msg = RFB.messages.fbUpdateRequests(expected_cdr, 240, 20);
|
||||
|
||||
client._framebufferUpdate = function () { return true; };
|
||||
client._sock._websocket._receive_data(new Uint8Array([0]));
|
||||
@@ -1099,8 +1099,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||
|
||||
it('should resume receiving an update if we previously did not have enough data', function () {
|
||||
var expected_cdr = { cleanBox: { x: 0, y: 0, w: 0, h: 0 },
|
||||
dirtyBoxes: [ { x: 0, y: 0, w: 640, h: 20 } ] };
|
||||
var expected_msg = RFB.messages.fbUpdateRequests(expected_cdr, 640, 20);
|
||||
dirtyBoxes: [ { x: 0, y: 0, w: 240, h: 20 } ] };
|
||||
var expected_msg = RFB.messages.fbUpdateRequests(expected_cdr, 240, 20);
|
||||
|
||||
// just enough to set FBU.rects
|
||||
client._sock._websocket._receive_data(new Uint8Array([0, 0, 0, 3]));
|
||||
@@ -1312,6 +1312,32 @@ describe('Remote Frame Buffer Protocol Client', function() {
|
||||
expect(client._display).to.have.displayed(new Uint8Array(expected));
|
||||
});
|
||||
|
||||
it('should handle a tile with only bg specified and an empty frame afterwards', function () {
|
||||
// set the width so we can have two tiles
|
||||
client._fb_width = 8;
|
||||
client._display._fb_width = 8;
|
||||
client._display._viewportLoc.w = 8;
|
||||
|
||||
var info = [{ x: 0, y: 0, width: 32, height: 4, encoding: 0x05 }];
|
||||
|
||||
var rect = [];
|
||||
|
||||
// send a bg frame
|
||||
rect.push(0x02);
|
||||
rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color
|
||||
|
||||
// send an empty frame
|
||||
rect.push(0x00);
|
||||
|
||||
send_fbu_msg(info, [rect], client);
|
||||
|
||||
var expected = [];
|
||||
var i;
|
||||
for (i = 0; i < 16; i++) { expected.push32(0xff00ff); } // rect 1: solid
|
||||
for (i = 0; i < 16; i++) { expected.push32(0xff00ff); } // rect 2: same bkground color
|
||||
expect(client._display).to.have.displayed(new Uint8Array(expected));
|
||||
});
|
||||
|
||||
it('should handle a tile with bg and coloured subrects', function () {
|
||||
var info = [{ x: 0, y: 0, width: 4, height: 4, encoding: 0x05 }];
|
||||
var rect = [];
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@
|
||||
// Load supporting scripts
|
||||
Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js",
|
||||
"keysymdef.js", "keyboard.js", "input.js", "display.js",
|
||||
"jsunzip.js", "rfb.js"]);
|
||||
"jsunzip.js", "rfb.js", "keysym.js"]);
|
||||
|
||||
var rfb;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user