Use ES6 classes

Always use the shorthand notation if the function is a method of an object or class `{ foo() { ... } }` or `class bar { foo() { ... } }`
unless it's a callback in which case you a fat arrow function should be used `{ cb: () => { ... } }`
This commit is contained in:
Juanjo Diaz 2018-07-05 21:31:56 +02:00
parent 67fefcf184
commit 0e4808bf6f
20 changed files with 977 additions and 972 deletions

View File

@ -1,15 +1,17 @@
{
"env": {
"browser": true,
"es6": true
},
"parserOptions": {
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
"no-constant-condition": ["error", { "checkLoops": false }],
"no-var": "error"
}
"env": {
"browser": true,
"es6": true
},
"parserOptions": {
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
"no-constant-condition": ["error", { "checkLoops": false }],
"no-var": "error",
"no-useless-constructor": "error",
"object-shorthand": ["error", "methods", { "avoidQuotes": true }],
}
}

View File

@ -10,17 +10,17 @@
* Localization Utilities
*/
export function Localizer() {
// Currently configured language
this.language = 'en';
export class Localizer {
constructor() {
// Currently configured language
this.language = 'en';
// Current dictionary of translations
this.dictionary = undefined;
}
// Current dictionary of translations
this.dictionary = undefined;
}
Localizer.prototype = {
// Configure suitable language based on user preferences
setup: function (supportedLanguages) {
setup(supportedLanguages) {
this.language = 'en'; // Default: US English
/*
@ -78,21 +78,22 @@ Localizer.prototype = {
return;
}
}
},
}
// Retrieve localised text
get: function (id) {
get(id) {
if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) {
return this.dictionary[id];
} else {
return id;
}
},
}
// Traverses the DOM and translates relevant fields
// See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
translateDOM: function () {
translateDOM() {
const self = this;
function process(elem, enabled) {
function isAnyOf(searchElement, items) {
return items.indexOf(searchElement) !== -1;
@ -160,8 +161,8 @@ Localizer.prototype = {
}
process(document.body, true);
},
};
}
}
export const l10n = new Localizer();
export default l10n.get.bind(l10n);

190
app/ui.js
View File

@ -41,7 +41,7 @@ const UI = {
reconnect_callback: null,
reconnect_password: null,
prime: function(callback) {
prime(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
UI.load(callback);
} else {
@ -51,12 +51,12 @@ const UI = {
// Setup rfb object, load settings from browser storage, then call
// UI.init to setup the UI/menus
load: function(callback) {
load(callback) {
WebUtil.initSettings(UI.start, callback);
},
// Render default UI and initialize settings menu
start: function(callback) {
start(callback) {
// Setup global variables first
UI.isSafari = (navigator.userAgent.indexOf('Safari') !== -1 &&
@ -116,7 +116,7 @@ const UI = {
}
},
initFullscreen: function() {
initFullscreen() {
// Only show the button if fullscreen is properly supported
// * Safari doesn't support alphanumerical input while in fullscreen
if (!UI.isSafari &&
@ -130,7 +130,7 @@ const UI = {
}
},
initSettings: function() {
initSettings() {
// Logging selection dropdown
const llevels = ['error', 'warn', 'info', 'debug'];
for (let i = 0; i < llevels.length; i += 1) {
@ -169,7 +169,7 @@ const UI = {
UI.setupSettingLabels();
},
// Adds a link to the label elements on the corresponding input elements
setupSettingLabels: function() {
setupSettingLabels() {
const labels = document.getElementsByTagName('LABEL');
for (let i = 0; i < labels.length; i++) {
const htmlFor = labels[i].htmlFor;
@ -195,7 +195,7 @@ const UI = {
* EVENT HANDLERS
* ------v------*/
addControlbarHandlers: function() {
addControlbarHandlers() {
document.getElementById("noVNC_control_bar")
.addEventListener('mousemove', UI.activateControlbar);
document.getElementById("noVNC_control_bar")
@ -228,7 +228,7 @@ const UI = {
}
},
addTouchSpecificHandlers: function() {
addTouchSpecificHandlers() {
document.getElementById("noVNC_mouse_button0")
.addEventListener('click', function () { UI.setMouseButton(1); });
document.getElementById("noVNC_mouse_button1")
@ -277,7 +277,7 @@ const UI = {
.addEventListener('touchmove', UI.dragControlbarHandle);
},
addExtraKeysHandlers: function() {
addExtraKeysHandlers() {
document.getElementById("noVNC_toggle_extra_keys_button")
.addEventListener('click', UI.toggleExtraKeys);
document.getElementById("noVNC_toggle_ctrl_button")
@ -292,7 +292,7 @@ const UI = {
.addEventListener('click', UI.sendCtrlAltDel);
},
addMachineHandlers: function() {
addMachineHandlers() {
document.getElementById("noVNC_shutdown_button")
.addEventListener('click', function() { UI.rfb.machineShutdown(); });
document.getElementById("noVNC_reboot_button")
@ -303,7 +303,7 @@ const UI = {
.addEventListener('click', UI.togglePowerPanel);
},
addConnectionControlHandlers: function() {
addConnectionControlHandlers() {
document.getElementById("noVNC_disconnect_button")
.addEventListener('click', UI.disconnect);
document.getElementById("noVNC_connect_button")
@ -315,7 +315,7 @@ const UI = {
.addEventListener('click', UI.setPassword);
},
addClipboardHandlers: function() {
addClipboardHandlers() {
document.getElementById("noVNC_clipboard_button")
.addEventListener('click', UI.toggleClipboardPanel);
document.getElementById("noVNC_clipboard_text")
@ -326,7 +326,7 @@ const UI = {
// Add a call to save settings when the element changes,
// unless the optional parameter changeFunc is used instead.
addSettingChangeHandler: function(name, changeFunc) {
addSettingChangeHandler(name, changeFunc) {
const settingElem = document.getElementById("noVNC_setting_" + name);
if (changeFunc === undefined) {
changeFunc = function () { UI.saveSetting(name); };
@ -334,7 +334,7 @@ const UI = {
settingElem.addEventListener('change', changeFunc);
},
addSettingsHandlers: function() {
addSettingsHandlers() {
document.getElementById("noVNC_settings_button")
.addEventListener('click', UI.toggleSettingsPanel);
@ -357,7 +357,7 @@ const UI = {
UI.addSettingChangeHandler('reconnect_delay');
},
addFullscreenHandlers: function() {
addFullscreenHandlers() {
document.getElementById("noVNC_fullscreen_button")
.addEventListener('click', UI.toggleFullscreen);
@ -374,7 +374,7 @@ const UI = {
* ------v------*/
// Disable/enable controls depending on connection state
updateVisualState: function(state) {
updateVisualState(state) {
document.documentElement.classList.remove("noVNC_connecting");
document.documentElement.classList.remove("noVNC_connected");
@ -441,7 +441,7 @@ const UI = {
.classList.remove('noVNC_open');
},
showStatus: function(text, status_type, time) {
showStatus(text, status_type, time) {
const statusElem = document.getElementById('noVNC_status');
clearTimeout(UI.statusTimeout);
@ -502,12 +502,12 @@ const UI = {
}
},
hideStatus: function() {
hideStatus() {
clearTimeout(UI.statusTimeout);
document.getElementById('noVNC_status').classList.remove("noVNC_open");
},
activateControlbar: function(event) {
activateControlbar(event) {
clearTimeout(UI.idleControlbarTimeout);
// We manipulate the anchor instead of the actual control
// bar in order to avoid creating new a stacking group
@ -516,27 +516,27 @@ const UI = {
UI.idleControlbarTimeout = window.setTimeout(UI.idleControlbar, 2000);
},
idleControlbar: function() {
idleControlbar() {
document.getElementById('noVNC_control_bar_anchor')
.classList.add("noVNC_idle");
},
keepControlbar: function() {
keepControlbar() {
clearTimeout(UI.closeControlbarTimeout);
},
openControlbar: function() {
openControlbar() {
document.getElementById('noVNC_control_bar')
.classList.add("noVNC_open");
},
closeControlbar: function() {
closeControlbar() {
UI.closeAllPanels();
document.getElementById('noVNC_control_bar')
.classList.remove("noVNC_open");
},
toggleControlbar: function() {
toggleControlbar() {
if (document.getElementById('noVNC_control_bar')
.classList.contains("noVNC_open")) {
UI.closeControlbar();
@ -545,7 +545,7 @@ const UI = {
}
},
toggleControlbarSide: function () {
toggleControlbarSide() {
// Temporarily disable animation, if bar is displayed, to avoid weird
// movement. The transitionend-event will not fire when display=none.
const bar = document.getElementById('noVNC_control_bar');
@ -569,7 +569,7 @@ const UI = {
UI.controlbarDrag = true;
},
showControlbarHint: function (show) {
showControlbarHint(show) {
const hint = document.getElementById('noVNC_control_bar_hint');
if (show) {
hint.classList.add("noVNC_active");
@ -578,7 +578,7 @@ const UI = {
}
},
dragControlbarHandle: function (e) {
dragControlbarHandle(e) {
if (!UI.controlbarGrabbed) return;
const ptr = getPointerEvent(e);
@ -616,7 +616,7 @@ const UI = {
},
// Move the handle but don't allow any position outside the bounds
moveControlbarHandle: function (viewportRelativeY) {
moveControlbarHandle(viewportRelativeY) {
const handle = document.getElementById("noVNC_control_bar_handle");
const handleHeight = handle.getBoundingClientRect().height;
const controlbarBounds = document.getElementById("noVNC_control_bar")
@ -653,7 +653,7 @@ const UI = {
handle.style.transform = "translateY(" + parentRelativeY + "px)";
},
updateControlbarHandle: function () {
updateControlbarHandle() {
// Since the control bar is fixed on the viewport and not the page,
// the move function expects coordinates relative the the viewport.
const handle = document.getElementById("noVNC_control_bar_handle");
@ -661,7 +661,7 @@ const UI = {
UI.moveControlbarHandle(handleBounds.top);
},
controlbarHandleMouseUp: function(e) {
controlbarHandleMouseUp(e) {
if ((e.type == "mouseup") && (e.button != 0)) return;
// mouseup and mousedown on the same place toggles the controlbar
@ -676,7 +676,7 @@ const UI = {
UI.showControlbarHint(false);
},
controlbarHandleMouseDown: function(e) {
controlbarHandleMouseDown(e) {
if ((e.type == "mousedown") && (e.button != 0)) return;
const ptr = getPointerEvent(e);
@ -702,7 +702,7 @@ const UI = {
UI.activateControlbar();
},
toggleExpander: function(e) {
toggleExpander(e) {
if (this.classList.contains("noVNC_open")) {
this.classList.remove("noVNC_open");
} else {
@ -717,7 +717,7 @@ const UI = {
* ------v------*/
// Initial page load read/initialization of settings
initSetting: function(name, defVal) {
initSetting(name, defVal) {
// Check Query string followed by cookie
let val = WebUtil.getConfigVar(name);
if (val === null) {
@ -729,7 +729,7 @@ const UI = {
},
// Set the new value, update and disable form control setting
forceSetting: function(name, val) {
forceSetting(name, val) {
WebUtil.setSetting(name, val);
UI.updateSetting(name);
UI.disableSetting(name);
@ -737,7 +737,7 @@ const UI = {
// Update cookie and form control setting. If value is not set, then
// updates from control to current cookie setting.
updateSetting: function(name) {
updateSetting(name) {
// Update the settings control
let value = UI.getSetting(name);
@ -764,7 +764,7 @@ const UI = {
},
// Save control setting to cookie
saveSetting: function(name) {
saveSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name);
let val;
if (ctrl.type === 'checkbox') {
@ -780,7 +780,7 @@ const UI = {
},
// Read form control compatible setting from cookie
getSetting: function(name) {
getSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name);
let val = WebUtil.readSetting(name);
if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') {
@ -796,13 +796,13 @@ const UI = {
// These helpers compensate for the lack of parent-selectors and
// previous-sibling-selectors in CSS which are needed when we want to
// disable the labels that belong to disabled input elements.
disableSetting: function(name) {
disableSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name);
ctrl.disabled = true;
ctrl.label.classList.add('noVNC_disabled');
},
enableSetting: function(name) {
enableSetting(name) {
const ctrl = document.getElementById('noVNC_setting_' + name);
ctrl.disabled = false;
ctrl.label.classList.remove('noVNC_disabled');
@ -814,7 +814,7 @@ const UI = {
* PANELS
* ------v------*/
closeAllPanels: function() {
closeAllPanels() {
UI.closeSettingsPanel();
UI.closePowerPanel();
UI.closeClipboardPanel();
@ -827,7 +827,7 @@ const UI = {
* SETTINGS (panel)
* ------v------*/
openSettingsPanel: function() {
openSettingsPanel() {
UI.closeAllPanels();
UI.openControlbar();
@ -849,14 +849,14 @@ const UI = {
.classList.add("noVNC_selected");
},
closeSettingsPanel: function() {
closeSettingsPanel() {
document.getElementById('noVNC_settings')
.classList.remove("noVNC_open");
document.getElementById('noVNC_settings_button')
.classList.remove("noVNC_selected");
},
toggleSettingsPanel: function() {
toggleSettingsPanel() {
if (document.getElementById('noVNC_settings')
.classList.contains("noVNC_open")) {
UI.closeSettingsPanel();
@ -871,7 +871,7 @@ const UI = {
* POWER
* ------v------*/
openPowerPanel: function() {
openPowerPanel() {
UI.closeAllPanels();
UI.openControlbar();
@ -881,14 +881,14 @@ const UI = {
.classList.add("noVNC_selected");
},
closePowerPanel: function() {
closePowerPanel() {
document.getElementById('noVNC_power')
.classList.remove("noVNC_open");
document.getElementById('noVNC_power_button')
.classList.remove("noVNC_selected");
},
togglePowerPanel: function() {
togglePowerPanel() {
if (document.getElementById('noVNC_power')
.classList.contains("noVNC_open")) {
UI.closePowerPanel();
@ -898,7 +898,7 @@ const UI = {
},
// Disable/enable power button
updatePowerButton: function() {
updatePowerButton() {
if (UI.connected &&
UI.rfb.capabilities.power &&
!UI.rfb.viewOnly) {
@ -918,7 +918,7 @@ const UI = {
* CLIPBOARD
* ------v------*/
openClipboardPanel: function() {
openClipboardPanel() {
UI.closeAllPanels();
UI.openControlbar();
@ -928,14 +928,14 @@ const UI = {
.classList.add("noVNC_selected");
},
closeClipboardPanel: function() {
closeClipboardPanel() {
document.getElementById('noVNC_clipboard')
.classList.remove("noVNC_open");
document.getElementById('noVNC_clipboard_button')
.classList.remove("noVNC_selected");
},
toggleClipboardPanel: function() {
toggleClipboardPanel() {
if (document.getElementById('noVNC_clipboard')
.classList.contains("noVNC_open")) {
UI.closeClipboardPanel();
@ -944,18 +944,18 @@ const UI = {
}
},
clipboardReceive: function(e) {
clipboardReceive(e) {
Log.Debug(">> UI.clipboardReceive: " + e.detail.text.substr(0,40) + "...");
document.getElementById('noVNC_clipboard_text').value = e.detail.text;
Log.Debug("<< UI.clipboardReceive");
},
clipboardClear: function() {
clipboardClear() {
document.getElementById('noVNC_clipboard_text').value = "";
UI.rfb.clipboardPasteFrom("");
},
clipboardSend: function() {
clipboardSend() {
const text = document.getElementById('noVNC_clipboard_text').value;
Log.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "...");
UI.rfb.clipboardPasteFrom(text);
@ -968,17 +968,17 @@ const UI = {
* CONNECTION
* ------v------*/
openConnectPanel: function() {
openConnectPanel() {
document.getElementById('noVNC_connect_dlg')
.classList.add("noVNC_open");
},
closeConnectPanel: function() {
closeConnectPanel() {
document.getElementById('noVNC_connect_dlg')
.classList.remove("noVNC_open");
},
connect: function(event, password) {
connect(event, password) {
// Ignore when rfb already exists
if (typeof UI.rfb !== 'undefined') {
@ -1040,7 +1040,7 @@ const UI = {
UI.updateViewOnly(); // requires UI.rfb
},
disconnect: function() {
disconnect() {
UI.closeAllPanels();
UI.rfb.disconnect();
@ -1054,7 +1054,7 @@ const UI = {
// Don't display the connection settings until we're actually disconnected
},
reconnect: function() {
reconnect() {
UI.reconnect_callback = null;
// if reconnect has been disabled in the meantime, do nothing.
@ -1065,7 +1065,7 @@ const UI = {
UI.connect(null, UI.reconnect_password);
},
cancelReconnect: function() {
cancelReconnect() {
if (UI.reconnect_callback !== null) {
clearTimeout(UI.reconnect_callback);
UI.reconnect_callback = null;
@ -1077,7 +1077,7 @@ const UI = {
UI.openConnectPanel();
},
connectFinished: function (e) {
connectFinished(e) {
UI.connected = true;
UI.inhibit_reconnect = false;
@ -1094,7 +1094,7 @@ const UI = {
UI.rfb.focus();
},
disconnectFinished: function (e) {
disconnectFinished(e) {
const wasConnected = UI.connected;
// This variable is ideally set when disconnection starts, but
@ -1128,7 +1128,7 @@ const UI = {
UI.openConnectPanel();
},
securityFailed: function (e) {
securityFailed(e) {
let msg = "";
// On security failures we might get a string with a reason
// directly from the server. Note that we can't control if
@ -1148,7 +1148,7 @@ const UI = {
* PASSWORD
* ------v------*/
credentials: function(e) {
credentials(e) {
// FIXME: handle more types
document.getElementById('noVNC_password_dlg')
.classList.add('noVNC_open');
@ -1161,7 +1161,7 @@ const UI = {
UI.showStatus(_("Password is required"), "warning");
},
setPassword: function(e) {
setPassword(e) {
// Prevent actually submitting the form
e.preventDefault();
@ -1181,7 +1181,7 @@ const UI = {
* FULLSCREEN
* ------v------*/
toggleFullscreen: function() {
toggleFullscreen() {
if (document.fullscreenElement || // alternative standard method
document.mozFullScreenElement || // currently working methods
document.webkitFullscreenElement ||
@ -1210,7 +1210,7 @@ const UI = {
UI.updateFullscreenButton();
},
updateFullscreenButton: function() {
updateFullscreenButton() {
if (document.fullscreenElement || // alternative standard method
document.mozFullScreenElement || // currently working methods
document.webkitFullscreenElement ||
@ -1230,7 +1230,7 @@ const UI = {
* ------v------*/
// Apply remote resizing or local scaling
applyResizeMode: function() {
applyResizeMode() {
if (!UI.rfb) return;
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
@ -1244,7 +1244,7 @@ const UI = {
* ------v------*/
// Update parameters that depend on the viewport clip setting
updateViewClip: function() {
updateViewClip() {
if (!UI.rfb) return;
const cur_clip = UI.rfb.clipViewport;
@ -1265,7 +1265,7 @@ const UI = {
},
// Handle special cases where viewport clipping is locked
enableDisableViewClip: function() {
enableDisableViewClip() {
const resizeSetting = UI.getSetting('resize');
if (isTouchDevice) {
UI.forceSetting('view_clip', true);
@ -1282,7 +1282,7 @@ const UI = {
* VIEWDRAG
* ------v------*/
toggleViewDrag: function() {
toggleViewDrag() {
if (!UI.rfb) return;
const drag = UI.rfb.dragViewport;
@ -1290,7 +1290,7 @@ const UI = {
},
// Set the view drag mode which moves the viewport on mouse drags
setViewDrag: function(drag) {
setViewDrag(drag) {
if (!UI.rfb) return;
UI.rfb.dragViewport = drag;
@ -1298,7 +1298,7 @@ const UI = {
UI.updateViewDrag();
},
updateViewDrag: function() {
updateViewDrag() {
if (!UI.connected) return;
const viewDragButton = document.getElementById('noVNC_view_drag_button');
@ -1342,7 +1342,7 @@ const UI = {
* KEYBOARD
* ------v------*/
showVirtualKeyboard: function() {
showVirtualKeyboard() {
if (!isTouchDevice) return;
const input = document.getElementById('noVNC_keyboardinput');
@ -1360,7 +1360,7 @@ const UI = {
}
},
hideVirtualKeyboard: function() {
hideVirtualKeyboard() {
if (!isTouchDevice) return;
const input = document.getElementById('noVNC_keyboardinput');
@ -1370,7 +1370,7 @@ const UI = {
input.blur();
},
toggleVirtualKeyboard: function () {
toggleVirtualKeyboard() {
if (document.getElementById('noVNC_keyboard_button')
.classList.contains("noVNC_selected")) {
UI.hideVirtualKeyboard();
@ -1379,7 +1379,7 @@ const UI = {
}
},
onfocusVirtualKeyboard: function(event) {
onfocusVirtualKeyboard(event) {
document.getElementById('noVNC_keyboard_button')
.classList.add("noVNC_selected");
if (UI.rfb) {
@ -1387,7 +1387,7 @@ const UI = {
}
},
onblurVirtualKeyboard: function(event) {
onblurVirtualKeyboard(event) {
document.getElementById('noVNC_keyboard_button')
.classList.remove("noVNC_selected");
if (UI.rfb) {
@ -1395,7 +1395,7 @@ const UI = {
}
},
keepVirtualKeyboard: function(event) {
keepVirtualKeyboard(event) {
const input = document.getElementById('noVNC_keyboardinput');
// Only prevent focus change if the virtual keyboard is active
@ -1423,13 +1423,13 @@ const UI = {
event.preventDefault();
},
keyboardinputReset: function() {
keyboardinputReset() {
const kbi = document.getElementById('noVNC_keyboardinput');
kbi.value = new Array(UI.defaultKeyboardinputLen).join("_");
UI.lastKeyboardinput = kbi.value;
},
keyEvent: function (keysym, code, down) {
keyEvent(keysym, code, down) {
if (!UI.rfb) return;
UI.rfb.sendKey(keysym, code, down);
@ -1439,7 +1439,7 @@ const UI = {
// the keyboardinput element instead and generate the corresponding key events.
// This code is required since some browsers on Android are inconsistent in
// sending keyCodes in the normal keyboard events when using on screen keyboards.
keyInput: function(event) {
keyInput(event) {
if (!UI.rfb) return;
@ -1506,7 +1506,7 @@ const UI = {
* EXTRA KEYS
* ------v------*/
openExtraKeys: function() {
openExtraKeys() {
UI.closeAllPanels();
UI.openControlbar();
@ -1516,14 +1516,14 @@ const UI = {
.classList.add("noVNC_selected");
},
closeExtraKeys: function() {
closeExtraKeys() {
document.getElementById('noVNC_modifiers')
.classList.remove("noVNC_open");
document.getElementById('noVNC_toggle_extra_keys_button')
.classList.remove("noVNC_selected");
},
toggleExtraKeys: function() {
toggleExtraKeys() {
if(document.getElementById('noVNC_modifiers')
.classList.contains("noVNC_open")) {
UI.closeExtraKeys();
@ -1532,15 +1532,15 @@ const UI = {
}
},
sendEsc: function() {
sendEsc() {
UI.rfb.sendKey(KeyTable.XK_Escape, "Escape");
},
sendTab: function() {
sendTab() {
UI.rfb.sendKey(KeyTable.XK_Tab);
},
toggleCtrl: function() {
toggleCtrl() {
const btn = document.getElementById('noVNC_toggle_ctrl_button');
if (btn.classList.contains("noVNC_selected")) {
UI.rfb.sendKey(KeyTable.XK_Control_L, "ControlLeft", false);
@ -1551,7 +1551,7 @@ const UI = {
}
},
toggleAlt: function() {
toggleAlt() {
const btn = document.getElementById('noVNC_toggle_alt_button');
if (btn.classList.contains("noVNC_selected")) {
UI.rfb.sendKey(KeyTable.XK_Alt_L, "AltLeft", false);
@ -1562,7 +1562,7 @@ const UI = {
}
},
sendCtrlAltDel: function() {
sendCtrlAltDel() {
UI.rfb.sendCtrlAltDel();
},
@ -1572,7 +1572,7 @@ const UI = {
* MISC
* ------v------*/
setMouseButton: function(num) {
setMouseButton(num) {
const view_only = UI.rfb.viewOnly;
if (UI.rfb && !view_only) {
UI.rfb.touchButton = num;
@ -1590,7 +1590,7 @@ const UI = {
}
},
updateViewOnly: function() {
updateViewOnly() {
if (!UI.rfb) return;
UI.rfb.viewOnly = UI.getSetting('view_only');
@ -1609,17 +1609,17 @@ const UI = {
UI.setMouseButton(1); //has it's own logic for hiding/showing
},
updateLogging: function() {
updateLogging() {
WebUtil.init_logging(UI.getSetting('logging'));
},
updateDesktopName: function(e) {
updateDesktopName(e) {
UI.desktopName = e.detail.name;
// Display the desktop name in the document title
document.title = e.detail.name + " - noVNC";
},
bell: function(e) {
bell(e) {
if (WebUtil.getConfigVar('bell', 'on') === 'on') {
const promise = document.getElementById('noVNC_bell').play();
// The standards disagree on the return value here
@ -1638,7 +1638,7 @@ const UI = {
},
//Helper to add options to dropdown.
addOption: function(selectbox, text, value) {
addOption(selectbox, text, value) {
const optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;

View File

@ -11,7 +11,7 @@ export default {
toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
base64Pad : '=',
encode: function (data) {
encode(data) {
"use strict";
let result = '';
const length = data.length;
@ -54,8 +54,7 @@ export default {
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
],
decode: function (data, offset) {
"use strict";
decode(data, offset) {
offset = typeof(offset) !== 'undefined' ? offset : 0;
let data_length = data.indexOf('=') - offset;

View File

@ -10,66 +10,6 @@
import * as Log from './util/logging.js';
import Base64 from "./base64.js";
export default function Display(target) {
this._drawCtx = null;
this._c_forceCanvas = false;
this._renderQ = []; // queue drawing actions for in-oder rendering
this._flushing = false;
// the full frame buffer (logical canvas) size
this._fb_width = 0;
this._fb_height = 0;
this._prevDrawStyle = "";
this._tile = null;
this._tile16x16 = null;
this._tile_x = 0;
this._tile_y = 0;
Log.Debug(">> Display.constructor");
// The visible canvas
this._target = target;
if (!this._target) {
throw new Error("Target must be set");
}
if (typeof this._target === 'string') {
throw new Error('target must be a DOM element');
}
if (!this._target.getContext) {
throw new Error("no getContext method");
}
this._targetCtx = this._target.getContext('2d');
// the visible canvas viewport (i.e. what actually gets seen)
this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
// The hidden canvas, where we do the actual rendering
this._backbuffer = document.createElement('canvas');
this._drawCtx = this._backbuffer.getContext('2d');
this._damageBounds = { left:0, top:0,
right: this._backbuffer.width,
bottom: this._backbuffer.height };
Log.Debug("User Agent: " + navigator.userAgent);
this.clear();
// Check canvas features
if (!('createImageData' in this._drawCtx)) {
throw new Error("Canvas does not support createImageData");
}
this._tile16x16 = this._drawCtx.createImageData(16, 16);
Log.Debug("<< Display.constructor");
}
let SUPPORTS_IMAGEDATA_CONSTRUCTOR = false;
try {
new ImageData(new Uint8ClampedArray(4), 1, 1);
@ -78,41 +18,104 @@ try {
// ignore failure
}
Display.prototype = {
export default class Display {
constructor(target) {
this._drawCtx = null;
this._c_forceCanvas = false;
this._renderQ = []; // queue drawing actions for in-oder rendering
this._flushing = false;
// the full frame buffer (logical canvas) size
this._fb_width = 0;
this._fb_height = 0;
this._prevDrawStyle = "";
this._tile = null;
this._tile16x16 = null;
this._tile_x = 0;
this._tile_y = 0;
Log.Debug(">> Display.constructor");
// The visible canvas
this._target = target;
if (!this._target) {
throw new Error("Target must be set");
}
if (typeof this._target === 'string') {
throw new Error('target must be a DOM element');
}
if (!this._target.getContext) {
throw new Error("no getContext method");
}
this._targetCtx = this._target.getContext('2d');
// the visible canvas viewport (i.e. what actually gets seen)
this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
// The hidden canvas, where we do the actual rendering
this._backbuffer = document.createElement('canvas');
this._drawCtx = this._backbuffer.getContext('2d');
this._damageBounds = { left:0, top:0,
right: this._backbuffer.width,
bottom: this._backbuffer.height };
Log.Debug("User Agent: " + navigator.userAgent);
this.clear();
// Check canvas features
if (!('createImageData' in this._drawCtx)) {
throw new Error("Canvas does not support createImageData");
}
this._tile16x16 = this._drawCtx.createImageData(16, 16);
Log.Debug("<< Display.constructor");
// ===== PROPERTIES =====
this._scale = 1.0;
this._clipViewport = false;
this.logo = null;
// ===== EVENT HANDLERS =====
this.onflush = () => {}; // A flush request has finished
}
// ===== PROPERTIES =====
_scale: 1.0,
get scale() { return this._scale; },
get scale() { return this._scale; }
set scale(scale) {
this._rescale(scale);
},
}
_clipViewport: false,
get clipViewport() { return this._clipViewport; },
get clipViewport() { return this._clipViewport; }
set clipViewport(viewport) {
this._clipViewport = viewport;
// May need to readjust the viewport dimensions
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
},
}
get width() {
return this._fb_width;
},
}
get height() {
return this._fb_height;
},
logo: null,
// ===== EVENT HANDLERS =====
onflush: function () {}, // A flush request has finished
}
// ===== PUBLIC METHODS =====
viewportChangePos: function (deltaX, deltaY) {
viewportChangePos(deltaX, deltaY) {
const vp = this._viewportLoc;
deltaX = Math.floor(deltaX);
deltaY = Math.floor(deltaY);
@ -152,9 +155,9 @@ Display.prototype = {
this._damage(vp.x, vp.y, vp.w, vp.h);
this.flip();
},
}
viewportChangeSize: function(width, height) {
viewportChangeSize(width, height) {
if (!this._clipViewport ||
typeof(width) === "undefined" ||
@ -190,17 +193,17 @@ Display.prototype = {
// Update the visible size of the target canvas
this._rescale(this._scale);
}
},
}
absX: function (x) {
absX(x) {
return x / this._scale + this._viewportLoc.x;
},
}
absY: function (y) {
absY(y) {
return y / this._scale + this._viewportLoc.y;
},
}
resize: function (width, height) {
resize(width, height) {
this._prevDrawStyle = "";
this._fb_width = width;
@ -232,10 +235,10 @@ Display.prototype = {
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
},
}
// Track what parts of the visible canvas that need updating
_damage: function(x, y, w, h) {
_damage(x, y, w, h) {
if (x < this._damageBounds.left) {
this._damageBounds.left = x;
}
@ -248,11 +251,11 @@ Display.prototype = {
if ((y + h) > this._damageBounds.bottom) {
this._damageBounds.bottom = y + h;
}
},
}
// Update the visible canvas with the contents of the
// rendering canvas
flip: function(from_queue) {
flip(from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'flip'
@ -296,9 +299,9 @@ Display.prototype = {
this._damageBounds.left = this._damageBounds.top = 65535;
this._damageBounds.right = this._damageBounds.bottom = 0;
}
},
}
clear: function () {
clear() {
if (this._logo) {
this.resize(this._logo.width, this._logo.height);
this.imageRect(0, 0, this._logo.type, this._logo.data);
@ -307,21 +310,21 @@ Display.prototype = {
this._drawCtx.clearRect(0, 0, this._fb_width, this._fb_height);
}
this.flip();
},
}
pending: function() {
pending() {
return this._renderQ.length > 0;
},
}
flush: function() {
flush() {
if (this._renderQ.length === 0) {
this.onflush();
} else {
this._flushing = true;
}
},
}
fillRect: function (x, y, width, height, color, from_queue) {
fillRect(x, y, width, height, color, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'fill',
@ -336,9 +339,9 @@ Display.prototype = {
this._drawCtx.fillRect(x, y, width, height);
this._damage(x, y, width, height);
}
},
}
copyImage: function (old_x, old_y, new_x, new_y, w, h, from_queue) {
copyImage(old_x, old_y, new_x, new_y, w, h, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
this._renderQ_push({
'type': 'copy',
@ -367,9 +370,9 @@ Display.prototype = {
new_x, new_y, w, h);
this._damage(new_x, new_y, w, h);
}
},
}
imageRect: function(x, y, mime, arr) {
imageRect(x, y, mime, arr) {
const img = new Image();
img.src = "data: " + mime + ";base64," + Base64.encode(arr);
this._renderQ_push({
@ -378,10 +381,10 @@ Display.prototype = {
'x': x,
'y': y
});
},
}
// start updating a tile
startTile: function (x, y, width, height, color) {
startTile(x, y, width, height, color) {
this._tile_x = x;
this._tile_y = y;
if (width === 16 && height === 16) {
@ -401,10 +404,10 @@ Display.prototype = {
data[i + 2] = blue;
data[i + 3] = 255;
}
},
}
// update sub-rectangle of the current tile
subTile: function (x, y, w, h, color) {
subTile(x, y, w, h, color) {
const red = color[2];
const green = color[1];
const blue = color[0];
@ -422,16 +425,16 @@ Display.prototype = {
data[p + 3] = 255;
}
}
},
}
// draw the current tile to the screen
finishTile: function () {
finishTile() {
this._drawCtx.putImageData(this._tile, this._tile_x, this._tile_y);
this._damage(this._tile_x, this._tile_y,
this._tile.width, this._tile.height);
},
}
blitImage: function (x, y, width, height, arr, offset, from_queue) {
blitImage(x, y, width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@ -449,9 +452,9 @@ Display.prototype = {
} else {
this._bgrxImageData(x, y, width, height, arr, offset);
}
},
}
blitRgbImage: function (x, y , width, height, arr, offset, from_queue) {
blitRgbImage(x, y , width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@ -469,9 +472,9 @@ Display.prototype = {
} else {
this._rgbImageData(x, y, width, height, arr, offset);
}
},
}
blitRgbxImage: function (x, y, width, height, arr, offset, from_queue) {
blitRgbxImage(x, y, width, height, arr, offset, from_queue) {
if (this._renderQ.length !== 0 && !from_queue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
@ -489,14 +492,14 @@ Display.prototype = {
} else {
this._rgbxImageData(x, y, width, height, arr, offset);
}
},
}
drawImage: function (img, x, y) {
drawImage(img, x, y) {
this._drawCtx.drawImage(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
autoscale: function (containerWidth, containerHeight) {
autoscale(containerWidth, containerHeight) {
const vp = this._viewportLoc;
const targetAspectRatio = containerWidth / containerHeight;
const fbAspectRatio = vp.w / vp.h;
@ -509,11 +512,11 @@ Display.prototype = {
}
this._rescale(scaleRatio);
},
}
// ===== PRIVATE METHODS =====
_rescale: function (factor) {
_rescale(factor) {
this._scale = factor;
const vp = this._viewportLoc;
@ -529,17 +532,17 @@ Display.prototype = {
this._target.style.width = width;
this._target.style.height = height;
}
},
}
_setFillColor: function (color) {
_setFillColor(color) {
const newStyle = 'rgb(' + color[2] + ',' + color[1] + ',' + color[0] + ')';
if (newStyle !== this._prevDrawStyle) {
this._drawCtx.fillStyle = newStyle;
this._prevDrawStyle = newStyle;
}
},
}
_rgbImageData: function (x, y, width, height, arr, offset) {
_rgbImageData(x, y, width, height, arr, offset) {
const img = this._drawCtx.createImageData(width, height);
const data = img.data;
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 3) {
@ -550,9 +553,9 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_bgrxImageData: function (x, y, width, height, arr, offset) {
_bgrxImageData(x, y, width, height, arr, offset) {
const img = this._drawCtx.createImageData(width, height);
const data = img.data;
for (let i = 0, j = offset; i < width * height * 4; i += 4, j += 4) {
@ -563,9 +566,9 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_rgbxImageData: function (x, y, width, height, arr, offset) {
_rgbxImageData(x, y, width, height, arr, offset) {
// NB(directxman12): arr must be an Type Array view
let img;
if (SUPPORTS_IMAGEDATA_CONSTRUCTOR) {
@ -576,25 +579,25 @@ Display.prototype = {
}
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, img.width, img.height);
},
}
_renderQ_push: function (action) {
_renderQ_push(action) {
this._renderQ.push(action);
if (this._renderQ.length === 1) {
// If this can be rendered immediately it will be, otherwise
// the scanner will wait for the relevant event
this._scan_renderQ();
}
},
}
_resume_renderQ: function() {
_resume_renderQ() {
// "this" is the object that is ready, not the
// display object
this.removeEventListener('load', this._noVNC_display._resume_renderQ);
this._noVNC_display._scan_renderQ();
},
}
_scan_renderQ: function () {
_scan_renderQ() {
let ready = true;
while (ready && this._renderQ.length > 0) {
const a = this._renderQ[0];
@ -639,5 +642,5 @@ Display.prototype = {
this._flushing = false;
this.onflush();
}
},
};
}
}

View File

@ -1,8 +1,17 @@
import { inflateInit, inflate, inflateReset } from "../vendor/pako/lib/zlib/inflate.js";
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
Inflate.prototype = {
inflate: function (data, flush, expected) {
export default class Inflate {
constructor() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.strm.output = new Uint8Array(this.chunkSize);
this.windowBits = 5;
inflateInit(this.strm, this.windowBits);
}
inflate(data, flush, expected) {
this.strm.input = data;
this.strm.avail_in = this.strm.input.length;
this.strm.next_in = 0;
@ -21,18 +30,9 @@ Inflate.prototype = {
inflate(this.strm, flush);
return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
},
}
reset: function () {
reset() {
inflateReset(this.strm);
}
};
export default function Inflate() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.strm.output = new Uint8Array(this.chunkSize);
this.windowBits = 5;
inflateInit(this.strm, this.windowBits);
}

View File

@ -15,32 +15,32 @@ import * as browser from "../util/browser.js";
// Keyboard event handler
//
export default function Keyboard(target) {
this._target = target || null;
export default class Keyboard {
constructor(target) {
this._target = target || null;
this._keyDownList = {}; // List of depressed keys
// (even if they are happy)
this._pendingKey = null; // Key waiting for keypress
this._altGrArmed = false; // Windows AltGr detection
this._keyDownList = {}; // List of depressed keys
// (even if they are happy)
this._pendingKey = null; // Key waiting for keypress
this._altGrArmed = false; // Windows AltGr detection
// keep these here so we can refer to them later
this._eventHandlers = {
'keyup': this._handleKeyUp.bind(this),
'keydown': this._handleKeyDown.bind(this),
'keypress': this._handleKeyPress.bind(this),
'blur': this._allKeysUp.bind(this),
'checkalt': this._checkAlt.bind(this),
};
}
// keep these here so we can refer to them later
this._eventHandlers = {
'keyup': this._handleKeyUp.bind(this),
'keydown': this._handleKeyDown.bind(this),
'keypress': this._handleKeyPress.bind(this),
'blur': this._allKeysUp.bind(this),
'checkalt': this._checkAlt.bind(this),
};
Keyboard.prototype = {
// ===== EVENT HANDLERS =====
// ===== EVENT HANDLERS =====
onkeyevent: function () {}, // Handler for key press/release
this.onkeyevent = () => {}; // Handler for key press/release
}
// ===== PRIVATE METHODS =====
_sendKeyEvent: function (keysym, code, down) {
_sendKeyEvent(keysym, code, down) {
if (down) {
this._keyDownList[code] = keysym;
} else {
@ -54,9 +54,9 @@ Keyboard.prototype = {
Log.Debug("onkeyevent " + (down ? "down" : "up") +
", keysym: " + keysym, ", code: " + code);
this.onkeyevent(keysym, code, down);
},
}
_getKeyCode: function (e) {
_getKeyCode(e) {
const code = KeyboardUtil.getKeycode(e);
if (code !== 'Unidentified') {
return code;
@ -87,9 +87,9 @@ Keyboard.prototype = {
}
return 'Unidentified';
},
}
_handleKeyDown: function (e) {
_handleKeyDown(e) {
const code = this._getKeyCode(e);
let keysym = KeyboardUtil.getKeysym(e);
@ -198,10 +198,10 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
}
// Legacy event for browsers without code/key
_handleKeyPress: function (e) {
_handleKeyPress(e) {
stopEvent(e);
// Are we expecting a keypress?
@ -226,8 +226,9 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
_handleKeyPressTimeout: function (e) {
}
_handleKeyPressTimeout(e) {
// Did someone manage to sort out the key already?
if (this._pendingKey === null) {
return;
@ -259,9 +260,9 @@ Keyboard.prototype = {
}
this._sendKeyEvent(keysym, code, true);
},
}
_handleKeyUp: function (e) {
_handleKeyUp(e) {
stopEvent(e);
const code = this._getKeyCode(e);
@ -282,24 +283,24 @@ Keyboard.prototype = {
}
this._sendKeyEvent(this._keyDownList[code], code, false);
},
}
_handleAltGrTimeout: function () {
_handleAltGrTimeout() {
this._altGrArmed = false;
clearTimeout(this._altGrTimeout);
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
},
}
_allKeysUp: function () {
_allKeysUp() {
Log.Debug(">> Keyboard.allKeysUp");
for (let code in this._keyDownList) {
this._sendKeyEvent(this._keyDownList[code], code, false);
}
Log.Debug("<< Keyboard.allKeysUp");
},
}
// Firefox Alt workaround, see below
_checkAlt: function (e) {
_checkAlt(e) {
if (e.altKey) {
return;
}
@ -316,11 +317,11 @@ Keyboard.prototype = {
code: code });
target.dispatchEvent(event);
});
},
}
// ===== PUBLIC METHODS =====
grab: function () {
grab() {
//Log.Debug(">> Keyboard.grab");
this._target.addEventListener('keydown', this._eventHandlers.keydown);
@ -341,13 +342,13 @@ Keyboard.prototype = {
document.addEventListener(type, handler,
{ capture: true,
passive: true });
});
});
}
//Log.Debug("<< Keyboard.grab");
},
}
ungrab: function () {
ungrab() {
//Log.Debug(">> Keyboard.ungrab");
if (browser.isWindows() && browser.isFirefox()) {
@ -368,5 +369,5 @@ Keyboard.prototype = {
this._allKeysUp();
//Log.Debug(">> Keyboard.ungrab");
},
};
}
}

View File

@ -670,7 +670,7 @@ const codepoints = {
};
export default {
lookup : function(u) {
lookup(u) {
// Latin-1 is one-to-one mapping
if ((u >= 0x20) && (u <= 0xff)) {
return u;

View File

@ -13,44 +13,44 @@ const WHEEL_STEP = 10; // Delta threshold for a mouse wheel step
const WHEEL_STEP_TIMEOUT = 50; // ms
const WHEEL_LINE_HEIGHT = 19;
export default function Mouse(target) {
this._target = target || document;
export default class Mouse {
constructor(target) {
this._target = target || document;
this._doubleClickTimer = null;
this._lastTouchPos = null;
this._doubleClickTimer = null;
this._lastTouchPos = null;
this._pos = null;
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
this._accumulatedWheelDeltaX = 0;
this._accumulatedWheelDeltaY = 0;
this._pos = null;
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
this._accumulatedWheelDeltaX = 0;
this._accumulatedWheelDeltaY = 0;
this._eventHandlers = {
'mousedown': this._handleMouseDown.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mousewheel': this._handleMouseWheel.bind(this),
'mousedisable': this._handleMouseDisable.bind(this)
};
}
this._eventHandlers = {
'mousedown': this._handleMouseDown.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mousewheel': this._handleMouseWheel.bind(this),
'mousedisable': this._handleMouseDisable.bind(this)
};
Mouse.prototype = {
// ===== PROPERTIES =====
// ===== PROPERTIES =====
touchButton: 1, // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
this.touchButton = 1; // Button mask (1, 2, 4) for touch devices (0 means ignore clicks)
// ===== EVENT HANDLERS =====
// ===== EVENT HANDLERS =====
onmousebutton: function () {}, // Handler for mouse button click/release
onmousemove: function () {}, // Handler for mouse movement
this.onmousebutton = () => {}; // Handler for mouse button click/release
this.onmousemove = () => {}; // Handler for mouse movement
}
// ===== PRIVATE METHODS =====
_resetDoubleClickTimer: function () {
_resetDoubleClickTimer() {
this._doubleClickTimer = null;
},
}
_handleMouseButton: function (e, down) {
_handleMouseButton(e, down) {
this._updateMousePosition(e);
let pos = this._pos;
@ -100,25 +100,25 @@ Mouse.prototype = {
this.onmousebutton(pos.x, pos.y, down, bmask);
stopEvent(e);
},
}
_handleMouseDown: function (e) {
_handleMouseDown(e) {
// Touch events have implicit capture
if (e.type === "mousedown") {
setCapture(this._target);
}
this._handleMouseButton(e, 1);
},
}
_handleMouseUp: function (e) {
_handleMouseUp(e) {
this._handleMouseButton(e, 0);
},
}
// Mouse wheel events are sent in steps over VNC. This means that the VNC
// protocol can't handle a wheel event with specific distance or speed.
// Therefor, if we get a lot of small mouse wheel events we combine them.
_generateWheelStepX: function () {
_generateWheelStepX() {
if (this._accumulatedWheelDeltaX < 0) {
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 5);
@ -129,9 +129,9 @@ Mouse.prototype = {
}
this._accumulatedWheelDeltaX = 0;
},
}
_generateWheelStepY: function () {
_generateWheelStepY() {
if (this._accumulatedWheelDeltaY < 0) {
this.onmousebutton(this._pos.x, this._pos.y, 1, 1 << 3);
@ -142,16 +142,16 @@ Mouse.prototype = {
}
this._accumulatedWheelDeltaY = 0;
},
}
_resetWheelStepTimers: function () {
_resetWheelStepTimers() {
window.clearTimeout(this._wheelStepXTimer);
window.clearTimeout(this._wheelStepYTimer);
this._wheelStepXTimer = null;
this._wheelStepYTimer = null;
},
}
_handleMouseWheel: function (e) {
_handleMouseWheel(e) {
this._resetWheelStepTimers();
this._updateMousePosition(e);
@ -192,15 +192,15 @@ Mouse.prototype = {
}
stopEvent(e);
},
}
_handleMouseMove: function (e) {
_handleMouseMove(e) {
this._updateMousePosition(e);
this.onmousemove(this._pos.x, this._pos.y);
stopEvent(e);
},
}
_handleMouseDisable: function (e) {
_handleMouseDisable(e) {
/*
* Stop propagation if inside canvas area
* Note: This is only needed for the 'click' event as it fails
@ -210,10 +210,10 @@ Mouse.prototype = {
if (e.target == this._target) {
stopEvent(e);
}
},
}
// Update coordinates relative to target
_updateMousePosition: function(e) {
_updateMousePosition(e) {
e = getPointerEvent(e);
const bounds = this._target.getBoundingClientRect();
let x;
@ -234,11 +234,11 @@ Mouse.prototype = {
y = e.clientY - bounds.top;
}
this._pos = {x:x, y:y};
},
}
// ===== PUBLIC METHODS =====
grab: function () {
grab() {
const c = this._target;
if (isTouchDevice) {
@ -257,9 +257,9 @@ Mouse.prototype = {
/* preventDefault() on mousedown doesn't stop this event for some
reason so we have to explicitly block it */
c.addEventListener('contextmenu', this._eventHandlers.mousedisable);
},
}
ungrab: function () {
ungrab() {
const c = this._target;
this._resetWheelStepTimers();
@ -278,4 +278,4 @@ Mouse.prototype = {
c.removeEventListener('contextmenu', this._eventHandlers.mousedisable);
}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -8,36 +8,36 @@ import { supportsCursorURIs, isTouchDevice } from './browser.js';
const useFallback = !supportsCursorURIs() || isTouchDevice;
function Cursor(container) {
this._target = null;
export default class Cursor {
constructor(container) {
this._target = null;
this._canvas = document.createElement('canvas');
this._canvas = document.createElement('canvas');
if (useFallback) {
this._canvas.style.position = 'fixed';
this._canvas.style.zIndex = '65535';
this._canvas.style.pointerEvents = 'none';
// Can't use "display" because of Firefox bug #1445997
this._canvas.style.visibility = 'hidden';
document.body.appendChild(this._canvas);
if (useFallback) {
this._canvas.style.position = 'fixed';
this._canvas.style.zIndex = '65535';
this._canvas.style.pointerEvents = 'none';
// Can't use "display" because of Firefox bug #1445997
this._canvas.style.visibility = 'hidden';
document.body.appendChild(this._canvas);
}
this._position = { x: 0, y: 0 };
this._hotSpot = { x: 0, y: 0 };
this._eventHandlers = {
'mouseover': this._handleMouseOver.bind(this),
'mouseleave': this._handleMouseLeave.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'touchstart': this._handleTouchStart.bind(this),
'touchmove': this._handleTouchMove.bind(this),
'touchend': this._handleTouchEnd.bind(this),
};
}
this._position = { x: 0, y: 0 };
this._hotSpot = { x: 0, y: 0 };
this._eventHandlers = {
'mouseover': this._handleMouseOver.bind(this),
'mouseleave': this._handleMouseLeave.bind(this),
'mousemove': this._handleMouseMove.bind(this),
'mouseup': this._handleMouseUp.bind(this),
'touchstart': this._handleTouchStart.bind(this),
'touchmove': this._handleTouchMove.bind(this),
'touchend': this._handleTouchEnd.bind(this),
};
}
Cursor.prototype = {
attach: function (target) {
attach(target) {
if (this._target) {
this.detach();
}
@ -61,9 +61,9 @@ Cursor.prototype = {
}
this.clear();
},
}
detach: function () {
detach() {
if (useFallback) {
const options = { capture: true, passive: true };
this._target.removeEventListener('mouseover', this._eventHandlers.mouseover, options);
@ -77,9 +77,9 @@ Cursor.prototype = {
}
this._target = null;
},
}
change: function (pixels, mask, hotx, hoty, w, h) {
change(pixels, mask, hotx, hoty, w, h) {
if ((w === 0) || (h === 0)) {
this.clear();
return;
@ -125,9 +125,9 @@ Cursor.prototype = {
let url = this._canvas.toDataURL();
this._target.style.cursor = 'url(' + url + ')' + hotx + ' ' + hoty + ', default';
}
},
}
clear: function () {
clear() {
this._target.style.cursor = 'none';
this._canvas.width = 0;
this._canvas.height = 0;
@ -135,71 +135,71 @@ Cursor.prototype = {
this._position.y = this._position.y + this._hotSpot.y;
this._hotSpot.x = 0;
this._hotSpot.y = 0;
},
}
_handleMouseOver: function (event) {
_handleMouseOver(event) {
// This event could be because we're entering the target, or
// moving around amongst its sub elements. Let the move handler
// sort things out.
this._handleMouseMove(event);
},
}
_handleMouseLeave: function (event) {
_handleMouseLeave(event) {
this._hideCursor();
},
}
_handleMouseMove: function (event) {
_handleMouseMove(event) {
this._updateVisibility(event.target);
this._position.x = event.clientX - this._hotSpot.x;
this._position.y = event.clientY - this._hotSpot.y;
this._updatePosition();
},
}
_handleMouseUp: function (event) {
_handleMouseUp(event) {
// We might get this event because of a drag operation that
// moved outside of the target. Check what's under the cursor
// now and adjust visibility based on that.
let target = document.elementFromPoint(event.clientX, event.clientY);
this._updateVisibility(target);
},
}
_handleTouchStart: function (event) {
_handleTouchStart(event) {
// Just as for mouseover, we let the move handler deal with it
this._handleTouchMove(event);
},
}
_handleTouchMove: function (event) {
_handleTouchMove(event) {
this._updateVisibility(event.target);
this._position.x = event.changedTouches[0].clientX - this._hotSpot.x;
this._position.y = event.changedTouches[0].clientY - this._hotSpot.y;
this._updatePosition();
},
}
_handleTouchEnd: function (event) {
_handleTouchEnd(event) {
// Same principle as for mouseup
let target = document.elementFromPoint(event.changedTouches[0].clientX,
event.changedTouches[0].clientY);
this._updateVisibility(target);
},
}
_showCursor: function () {
_showCursor() {
if (this._canvas.style.visibility === 'hidden')
this._canvas.style.visibility = '';
},
}
_hideCursor: function () {
_hideCursor() {
if (this._canvas.style.visibility !== 'hidden')
this._canvas.style.visibility = 'hidden';
},
}
// Should we currently display the cursor?
// (i.e. are we over the target, or a child of the target without a
// different cursor set)
_shouldShowCursor: function (target) {
_shouldShowCursor(target) {
// Easy case
if (target === this._target)
return true;
@ -212,19 +212,17 @@ Cursor.prototype = {
if (window.getComputedStyle(target).cursor !== 'none')
return false;
return true;
},
}
_updateVisibility: function (target) {
_updateVisibility(target) {
if (this._shouldShowCursor(target))
this._showCursor();
else
this._hideCursor();
},
}
_updatePosition: function () {
_updatePosition() {
this._canvas.style.left = this._position.x + "px";
this._canvas.style.top = this._position.y + "px";
},
};
export default Cursor;
}
}

View File

@ -6,10 +6,12 @@
* See README.md for usage and integration instructions.
*/
const EventTargetMixin = {
_listeners: null,
export default class EventTargetMixin {
constructor() {
this._listeners = null;
}
addEventListener: function(type, callback) {
addEventListener(type, callback) {
if (!this._listeners) {
this._listeners = new Map();
}
@ -17,16 +19,16 @@ const EventTargetMixin = {
this._listeners.set(type, new Set());
}
this._listeners.get(type).add(callback);
},
}
removeEventListener: function(type, callback) {
removeEventListener(type, callback) {
if (!this._listeners || !this._listeners.has(type)) {
return;
}
this._listeners.get(type).delete(callback);
},
}
dispatchEvent: function(event) {
dispatchEvent(event) {
if (!this._listeners || !this._listeners.has(event.type)) {
return true;
}
@ -34,7 +36,5 @@ const EventTargetMixin = {
callback.call(this, event);
}, this);
return !event.defaultPrevented;
},
};
export default EventTargetMixin;
}
}

View File

@ -10,6 +10,5 @@
* Decode from UTF-8
*/
export function decodeUTF8 (utf8string) {
"use strict";
return decodeURIComponent(escape(utf8string));
}

View File

@ -14,91 +14,88 @@
import * as Log from './util/logging.js';
export default function Websock() {
"use strict";
this._websocket = null; // WebSocket object
this._rQi = 0; // Receive queue index
this._rQlen = 0; // Next write position in the receive queue
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
this._rQmax = this._rQbufferSize / 8;
// called in init: this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ = null; // Receive queue
this._sQbufferSize = 1024 * 10; // 10 KiB
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
this._sQlen = 0;
this._sQ = null; // Send queue
this._eventHandlers = {
'message': function () {},
'open': function () {},
'close': function () {},
'error': function () {}
};
}
// this has performance issues in some versions Chromium, and
// doesn't gain a tremendous amount of performance increase in Firefox
// at the moment. It may be valuable to turn it on in the future.
const ENABLE_COPYWITHIN = false;
const MAX_RQ_GROW_SIZE = 40 * 1024 * 1024; // 40 MiB
Websock.prototype = {
export default class Websock {
constructor() {
this._websocket = null; // WebSocket object
this._rQi = 0; // Receive queue index
this._rQlen = 0; // Next write position in the receive queue
this._rQbufferSize = 1024 * 1024 * 4; // Receive queue buffer size (4 MiB)
this._rQmax = this._rQbufferSize / 8;
// called in init: this._rQ = new Uint8Array(this._rQbufferSize);
this._rQ = null; // Receive queue
this._sQbufferSize = 1024 * 10; // 10 KiB
// called in init: this._sQ = new Uint8Array(this._sQbufferSize);
this._sQlen = 0;
this._sQ = null; // Send queue
this._eventHandlers = {
message: () => {},
open: () => {},
close: () => {},
error: () => {}
};
}
// Getters and Setters
get_sQ: function () {
get_sQ() {
return this._sQ;
},
}
get_rQ: function () {
get_rQ() {
return this._rQ;
},
}
get_rQi: function () {
get_rQi() {
return this._rQi;
},
}
set_rQi: function (val) {
set_rQi(val) {
this._rQi = val;
},
}
// Receive Queue
rQlen: function () {
rQlen() {
return this._rQlen - this._rQi;
},
}
rQpeek8: function () {
rQpeek8() {
return this._rQ[this._rQi];
},
}
rQshift8: function () {
rQshift8() {
return this._rQ[this._rQi++];
},
}
rQskip8: function () {
rQskip8() {
this._rQi++;
},
}
rQskipBytes: function (num) {
rQskipBytes(num) {
this._rQi += num;
},
}
// TODO(directxman12): test performance with these vs a DataView
rQshift16: function () {
rQshift16() {
return (this._rQ[this._rQi++] << 8) +
this._rQ[this._rQi++];
},
}
rQshift32: function () {
rQshift32() {
return (this._rQ[this._rQi++] << 24) +
(this._rQ[this._rQi++] << 16) +
(this._rQ[this._rQi++] << 8) +
this._rQ[this._rQi++];
},
}
rQshiftStr: function (len) {
rQshiftStr(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); }
let str = "";
// Handle large arrays in steps to avoid long strings on the stack
@ -107,37 +104,37 @@ Websock.prototype = {
str += String.fromCharCode.apply(null, part);
}
return str;
},
}
rQshiftBytes: function (len) {
rQshiftBytes(len) {
if (typeof(len) === 'undefined') { len = this.rQlen(); }
this._rQi += len;
return new Uint8Array(this._rQ.buffer, this._rQi - len, len);
},
}
rQshiftTo: function (target, len) {
rQshiftTo(target, len) {
if (len === undefined) { len = this.rQlen(); }
// TODO: make this just use set with views when using a ArrayBuffer to store the rQ
target.set(new Uint8Array(this._rQ.buffer, this._rQi, len));
this._rQi += len;
},
}
rQwhole: function () {
rQwhole() {
return new Uint8Array(this._rQ.buffer, 0, this._rQlen);
},
}
rQslice: function (start, end) {
rQslice(start, end) {
if (end) {
return new Uint8Array(this._rQ.buffer, this._rQi + start, end - start);
} else {
return new Uint8Array(this._rQ.buffer, this._rQi + start, this._rQlen - this._rQi - start);
}
},
}
// Check to see if we must wait for 'num' bytes (default to FBU.bytes)
// to be available in the receive queue. Return true if we need to
// wait (and possibly print a debug message), otherwise false.
rQwait: function (msg, num, goback) {
rQwait(msg, num, goback) {
const rQlen = this._rQlen - this._rQi; // Skip rQlen() function call
if (rQlen < num) {
if (goback) {
@ -149,50 +146,50 @@ Websock.prototype = {
return true; // true means need more data
}
return false;
},
}
// Send Queue
flush: function () {
flush() {
if (this._sQlen > 0 && this._websocket.readyState === WebSocket.OPEN) {
this._websocket.send(this._encode_message());
this._sQlen = 0;
}
},
}
send: function (arr) {
send(arr) {
this._sQ.set(arr, this._sQlen);
this._sQlen += arr.length;
this.flush();
},
}
send_string: function (str) {
send_string(str) {
this.send(str.split('').map(function (chr) {
return chr.charCodeAt(0);
}));
},
}
// Event Handlers
off: function (evt) {
off(evt) {
this._eventHandlers[evt] = function () {};
},
}
on: function (evt, handler) {
on(evt, handler) {
this._eventHandlers[evt] = handler;
},
}
_allocate_buffers: function () {
_allocate_buffers() {
this._rQ = new Uint8Array(this._rQbufferSize);
this._sQ = new Uint8Array(this._sQbufferSize);
},
}
init: function () {
init() {
this._allocate_buffers();
this._rQi = 0;
this._websocket = null;
},
}
open: function (uri, protocols) {
open(uri, protocols) {
this.init();
this._websocket = new WebSocket(uri, protocols);
@ -218,9 +215,9 @@ Websock.prototype = {
this._eventHandlers.error(e);
Log.Debug("<< WebSock.onerror: " + e);
}).bind(this);
},
}
close: function () {
close() {
if (this._websocket) {
if ((this._websocket.readyState === WebSocket.OPEN) ||
(this._websocket.readyState === WebSocket.CONNECTING)) {
@ -230,16 +227,16 @@ Websock.prototype = {
this._websocket.onmessage = function (e) { return; };
}
},
}
// private methods
_encode_message: function () {
_encode_message() {
// Put in a binary arraybuffer
// according to the spec, you can send ArrayBufferViews with the send method
return new Uint8Array(this._sQ.buffer, 0, this._sQlen);
},
}
_expand_compact_rQ: function (min_fit) {
_expand_compact_rQ(min_fit) {
const resizeNeeded = min_fit || this._rQlen - this._rQi > this._rQbufferSize / 2;
if (resizeNeeded) {
if (!min_fit) {
@ -274,9 +271,9 @@ Websock.prototype = {
this._rQlen = this._rQlen - this._rQi;
this._rQi = 0;
},
}
_decode_message: function (data) {
_decode_message(data) {
// push arraybuffer values onto the end
const u8 = new Uint8Array(data);
if (u8.length > this._rQbufferSize - this._rQlen) {
@ -284,9 +281,9 @@ Websock.prototype = {
}
this._rQ.set(u8, this._rQlen);
this._rQlen += u8.length;
},
}
_recv_message: function (e) {
_recv_message(e) {
this._decode_message(e.data);
if (this.rQlen() > 0) {
this._eventHandlers.message();
@ -301,4 +298,4 @@ Websock.prototype = {
Log.Debug("Ignoring empty message");
}
}
};
}

View File

@ -1,9 +1,9 @@
{
"env": {
"node": true,
"mocha": true
},
"globals": {
"chai": true
}
"env": {
"node": true,
"mocha": true
},
"globals": {
"chai": true
}
}

View File

@ -12,34 +12,34 @@ function make_event(name, props) {
return evt;
}
export default function FakeWebSocket (uri, protocols) {
this.url = uri;
this.binaryType = "arraybuffer";
this.extensions = "";
export default class FakeWebSocket {
constructor(uri, protocols) {
this.url = uri;
this.binaryType = "arraybuffer";
this.extensions = "";
if (!protocols || typeof protocols === 'string') {
this.protocol = protocols;
} else {
this.protocol = protocols[0];
if (!protocols || typeof protocols === 'string') {
this.protocol = protocols;
} else {
this.protocol = protocols[0];
}
this._send_queue = new Uint8Array(20000);
this.readyState = FakeWebSocket.CONNECTING;
this.bufferedAmount = 0;
this.__is_fake = true;
}
this._send_queue = new Uint8Array(20000);
this.readyState = FakeWebSocket.CONNECTING;
this.bufferedAmount = 0;
this.__is_fake = true;
}
FakeWebSocket.prototype = {
close: function (code, reason) {
close(code, reason) {
this.readyState = FakeWebSocket.CLOSED;
if (this.onclose) {
this.onclose(make_event("close", { 'code': code, 'reason': reason, 'wasClean': true }));
}
},
}
send: function (data) {
send(data) {
if (this.protocol == 'base64') {
data = Base64.decode(data);
} else {
@ -47,25 +47,25 @@ FakeWebSocket.prototype = {
}
this._send_queue.set(data, this.bufferedAmount);
this.bufferedAmount += data.length;
},
}
_get_sent_data: function () {
_get_sent_data() {
const res = new Uint8Array(this._send_queue.buffer, 0, this.bufferedAmount);
this.bufferedAmount = 0;
return res;
},
}
_open: function (data) {
_open() {
this.readyState = FakeWebSocket.OPEN;
if (this.onopen) {
this.onopen(make_event('open'));
}
},
}
_receive_data: function (data) {
_receive_data(data) {
this.onmessage(make_event("message", { 'data': data }));
}
};
}
FakeWebSocket.OPEN = WebSocket.OPEN;
FakeWebSocket.CONNECTING = WebSocket.CONNECTING;

View File

@ -53,26 +53,26 @@ function enableUI() {
encoding = VNC_frame_encoding;
}
function IterationPlayer (iterations, frames, encoding) {
this._iterations = iterations;
class IterationPlayer {
constructor(iterations, frames, encoding) {
this._iterations = iterations;
this._iteration = undefined;
this._player = undefined;
this._iteration = undefined;
this._player = undefined;
this._start_time = undefined;
this._start_time = undefined;
this._frames = frames;
this._encoding = encoding;
this._frames = frames;
this._encoding = encoding;
this._state = 'running';
this._state = 'running';
this.onfinish = function() {};
this.oniterationfinish = function() {};
this.rfbdisconnected = function() {};
}
}
IterationPlayer.prototype = {
start: function (mode) {
start(mode) {
this._iteration = 0;
this._start_time = (new Date()).getTime();
@ -80,9 +80,9 @@ IterationPlayer.prototype = {
this._trafficMgmt = !mode.endsWith('-no-mgmt');
this._nextIteration();
},
}
_nextIteration: function () {
_nextIteration() {
const player = new RecordingPlayer(this._frames, this._encoding, this._disconnected.bind(this));
player.onfinish = this._iterationFinish.bind(this);
@ -95,9 +95,9 @@ IterationPlayer.prototype = {
}
player.run(this._realtime, this._trafficMgmt);
},
}
_finish: function () {
_finish() {
const endTime = (new Date()).getTime();
const totalDuration = endTime - this._start_time;
@ -105,18 +105,18 @@ IterationPlayer.prototype = {
evt.duration = totalDuration;
evt.iterations = this._iterations;
this.onfinish(evt);
},
}
_iterationFinish: function (duration) {
_iterationFinish(duration) {
const evt = new Event('iterationfinish');
evt.duration = duration;
evt.number = this._iteration;
this.oniterationfinish(evt);
this._nextIteration();
},
}
_disconnected: function (clean, frame) {
_disconnected(clean, frame) {
if (!clean) {
this._state = 'failed';
}
@ -127,8 +127,8 @@ IterationPlayer.prototype = {
evt.iteration = this._iteration;
this.onrfbdisconnected(evt);
},
};
}
}
function start() {
document.getElementById('startButton').value = "Running";

View File

@ -44,37 +44,37 @@ if (window.setImmediate === undefined) {
window.addEventListener("message", _onMessage);
}
export default function RecordingPlayer (frames, encoding, disconnected) {
this._frames = frames;
this._encoding = encoding;
export default class RecordingPlayer {
constructor(frames, encoding, disconnected) {
this._frames = frames;
this._encoding = encoding;
this._disconnected = disconnected;
this._disconnected = disconnected;
if (this._encoding === undefined) {
if (this._encoding === undefined) {
const frame = this._frames[0];
const start = frame.indexOf('{', 1) + 1;
if (frame.slice(start).startsWith('UkZC')) {
this._encoding = 'base64';
} else {
this._encoding = 'binary';
if (frame.slice(start).startsWith('UkZC')) {
this._encoding = 'base64';
} else {
this._encoding = 'binary';
}
}
}
this._rfb = undefined;
this._frame_length = this._frames.length;
this._rfb = undefined;
this._frame_length = this._frames.length;
this._frame_index = 0;
this._start_time = undefined;
this._realtime = true;
this._trafficManagement = true;
this._frame_index = 0;
this._start_time = undefined;
this._realtime = true;
this._trafficManagement = true;
this._running = false;
this._running = false;
this.onfinish = function () {};
}
}
RecordingPlayer.prototype = {
run: function (realtime, trafficManagement) {
run(realtime, trafficManagement) {
// initialize a new RFB
this._rfb = new RFB(document.getElementById('VNC_screen'), 'wss://test');
this._rfb.viewOnly = true;
@ -92,10 +92,10 @@ RecordingPlayer.prototype = {
this._running = true;
this._queueNextPacket();
},
}
// _enablePlaybackMode mocks out things not required for running playback
_enablePlaybackMode: function () {
_enablePlaybackMode() {
this._rfb._sock.send = function (arr) {};
this._rfb._sock.close = function () {};
this._rfb._sock.flush = function () {};
@ -103,9 +103,9 @@ RecordingPlayer.prototype = {
this.init();
this._eventHandlers.open();
};
},
}
_queueNextPacket: function () {
_queueNextPacket() {
if (!this._running) { return; }
let frame = this._frames[this._frame_index];
@ -138,9 +138,9 @@ RecordingPlayer.prototype = {
} else {
setImmediate(this._doPacket.bind(this));
}
},
}
_doPacket: function () {
_doPacket() {
// Avoid having excessive queue buildup in non-realtime mode
if (this._trafficManagement && this._rfb._flushing) {
const player = this;
@ -170,7 +170,7 @@ RecordingPlayer.prototype = {
this._frame_index++;
this._queueNextPacket();
},
}
_finish() {
if (this._rfb._display.pending()) {
@ -188,10 +188,10 @@ RecordingPlayer.prototype = {
delete this._rfb;
this.onfinish((new Date()).getTime() - this._start_time);
}
},
}
_handleDisconnect(evt) {
this._running = false;
this._disconnected(evt.detail.clean, this._frame_index);
}
};
}

View File

@ -194,7 +194,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
describe('#sendCtrlAlDel', function () {
it('should sent ctrl[down]-alt[down]-del[down] then del[up]-alt[up]-ctrl[up]', function () {
const expected = {_sQ: new Uint8Array(48), _sQlen: 0, flush: function () {}};
const expected = {_sQ: new Uint8Array(48), _sQlen: 0, flush: () => {}};
RFB.messages.keyEvent(expected, 0xFFE3, 1);
RFB.messages.keyEvent(expected, 0xFFE9, 1);
RFB.messages.keyEvent(expected, 0xFFFF, 1);
@ -223,14 +223,14 @@ describe('Remote Frame Buffer Protocol Client', function() {
describe('#sendKey', function () {
it('should send a single key with the given code and state (down = true)', function () {
const expected = {_sQ: new Uint8Array(8), _sQlen: 0, flush: function () {}};
const expected = {_sQ: new Uint8Array(8), _sQlen: 0, flush: () => {}};
RFB.messages.keyEvent(expected, 123, 1);
client.sendKey(123, 'Key123', true);
expect(client._sock).to.have.sent(expected._sQ);
});
it('should send both a down and up event if the state is not specified', function () {
const expected = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function () {}};
const expected = {_sQ: new Uint8Array(16), _sQlen: 0, flush: () => {}};
RFB.messages.keyEvent(expected, 123, 1);
RFB.messages.keyEvent(expected, 123, 0);
client.sendKey(123, 'Key123');
@ -253,7 +253,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
it('should send QEMU extended events if supported', function () {
client._qemuExtKeyEventSupported = true;
const expected = {_sQ: new Uint8Array(12), _sQlen: 0, flush: function () {}};
const expected = {_sQ: new Uint8Array(12), _sQlen: 0, flush: () => {}};
RFB.messages.QEMUExtendedKeyEvent(expected, 0x20, true, 0x0039);
client.sendKey(0x20, 'Space', true);
expect(client._sock).to.have.sent(expected._sQ);
@ -261,7 +261,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
it('should not send QEMU extended events if unknown key code', function () {
client._qemuExtKeyEventSupported = true;
const expected = {_sQ: new Uint8Array(8), _sQlen: 0, flush: function () {}};
const expected = {_sQ: new Uint8Array(8), _sQlen: 0, flush: () => {}};
RFB.messages.keyEvent(expected, 123, 1);
client.sendKey(123, 'FooBar', true);
expect(client._sock).to.have.sent(expected._sQ);
@ -287,7 +287,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
describe('#clipboardPasteFrom', function () {
it('should send the given text in a paste event', function () {
const expected = {_sQ: new Uint8Array(11), _sQlen: 0,
_sQbufferSize: 11, flush: function () {}};
_sQbufferSize: 11, flush: () => {}};
RFB.messages.clientCutText(expected, 'abc');
client.clipboardPasteFrom('abc');
expect(client._sock).to.have.sent(expected._sQ);
@ -1615,7 +1615,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
}
it('should send an update request if there is sufficient data', function () {
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: function() {}};
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: () => {}};
RFB.messages.fbUpdateRequest(expected_msg, true, 0, 0, 640, 20);
client._framebufferUpdate = function () { return true; };
@ -1630,7 +1630,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
});
it('should resume receiving an update if we previously did not have enough data', function () {
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: function() {}};
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: () => {}};
RFB.messages.fbUpdateRequest(expected_msg, true, 0, 0, 640, 20);
// just enough to set FBU.rects
@ -2040,8 +2040,8 @@ describe('Remote Frame Buffer Protocol Client', function() {
});
it('should respond correctly to ServerFence', function () {
const expected_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function() {}};
const incoming_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: function() {}};
const expected_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: () => {}};
const incoming_msg = {_sQ: new Uint8Array(16), _sQlen: 0, flush: () => {}};
const payload = "foo\x00ab9";
@ -2065,7 +2065,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
});
it('should enable continuous updates on first EndOfContinousUpdates', function () {
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: function() {}};
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: () => {}};
RFB.messages.enableContinuousUpdates(expected_msg, true, 0, 0, 640, 20);
@ -2087,7 +2087,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
});
it('should update continuous updates on resize', function () {
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: function() {}};
const expected_msg = {_sQ: new Uint8Array(10), _sQlen: 0, flush: () => {}};
RFB.messages.enableContinuousUpdates(expected_msg, true, 0, 0, 90, 700);
client._resize(450, 160);
@ -2131,14 +2131,14 @@ describe('Remote Frame Buffer Protocol Client', function() {
it('should send a pointer event on mouse button presses', function () {
client._handleMouseButton(10, 12, 1, 0x001);
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: function () {}};
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: () => {}};
RFB.messages.pointerEvent(pointer_msg, 10, 12, 0x001);
expect(client._sock).to.have.sent(pointer_msg._sQ);
});
it('should send a mask of 1 on mousedown', function () {
client._handleMouseButton(10, 12, 1, 0x001);
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: function () {}};
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: () => {}};
RFB.messages.pointerEvent(pointer_msg, 10, 12, 0x001);
expect(client._sock).to.have.sent(pointer_msg._sQ);
});
@ -2146,14 +2146,14 @@ describe('Remote Frame Buffer Protocol Client', function() {
it('should send a mask of 0 on mouseup', function () {
client._mouse_buttonMask = 0x001;
client._handleMouseButton(10, 12, 0, 0x001);
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: function () {}};
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: () => {}};
RFB.messages.pointerEvent(pointer_msg, 10, 12, 0x000);
expect(client._sock).to.have.sent(pointer_msg._sQ);
});
it('should send a pointer event on mouse movement', function () {
client._handleMouseMove(10, 12);
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: function () {}};
const pointer_msg = {_sQ: new Uint8Array(6), _sQlen: 0, flush: () => {}};
RFB.messages.pointerEvent(pointer_msg, 10, 12, 0x000);
expect(client._sock).to.have.sent(pointer_msg._sQ);
});
@ -2161,7 +2161,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
it('should set the button mask so that future mouse movements use it', function () {
client._handleMouseButton(10, 12, 1, 0x010);
client._handleMouseMove(13, 9);
const pointer_msg = {_sQ: new Uint8Array(12), _sQlen: 0, flush: function () {}};
const pointer_msg = {_sQ: new Uint8Array(12), _sQlen: 0, flush: () => {}};
RFB.messages.pointerEvent(pointer_msg, 10, 12, 0x010);
RFB.messages.pointerEvent(pointer_msg, 13, 9, 0x010);
expect(client._sock).to.have.sent(pointer_msg._sQ);
@ -2171,7 +2171,7 @@ describe('Remote Frame Buffer Protocol Client', function() {
describe('Keyboard Event Handlers', function () {
it('should send a key message on a key press', function () {
client._handleKeyEvent(0x41, 'KeyA', true);
const key_msg = {_sQ: new Uint8Array(8), _sQlen: 0, flush: function () {}};
const key_msg = {_sQ: new Uint8Array(8), _sQlen: 0, flush: () => {}};
RFB.messages.keyEvent(key_msg, 0x41, 1);
expect(client._sock).to.have.sent(key_msg._sQ);
});

View File

@ -117,9 +117,9 @@ describe('WebUtil', function() {
window.chrome = {
storage: {
sync: {
get: function(cb){ cb(settings); },
set: function(){},
remove: function() {}
get(cb){ cb(settings); },
set(){},
remove() {}
}
}
};