diff --git a/.gitignore b/.gitignore index a707ba70..da1b8c22 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ tests/data_*.js utils/rebind.so utils/websockify node_modules +build +lib +recordings diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..69a33a54 --- /dev/null +++ b/.npmignore @@ -0,0 +1,21 @@ +app +core +favicon.ico +.gitmodules +node_modules +.* +*~ +*.swp +*.swo +tests +.travis.yml +utils +docs/notes +docs/links +docs/release.txt +docs/rfb_notes +docs/*.pdf +vnc.html +vnc_auto.html +karma.conf.js +docs/flash_policy.txt diff --git a/LICENSE.txt b/LICENSE.txt index 2ec4a642..7b5de592 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -5,19 +5,19 @@ Public License 2.0). The noVNC core library is composed of the Javascript code necessary for full noVNC operation. This includes (but is not limited to): - include/base64.js - include/des.js - include/display.js - include/input.js - include/keysym.js - include/logo.js - include/playback.js - include/rfb.js - include/ui.js - include/util.js - include/websock.js - include/webutil.js - include/xtscancodes.js + core/base64.js + core/des.js + core/display.js + core/input/devices.js + core/input/keysym.js + core/logo.js + core/playback.js + core/rfb.js + app/ui.js + core/util.js + core/websock.js + app/webutil.js + core/input/xtscancodes.js The HTML, CSS, font and images files that included with the noVNC source distibution (or repository) are not considered part of the @@ -29,12 +29,12 @@ The HTML, CSS, font and image files are licensed as follows: *.html : 2-Clause BSD license - include/*.css : 2-Clause BSD license + app/styles/*.css : 2-Clause BSD license - include/Orbitron* : SIL Open Font License 1.1 + app/styles/Orbitron* : SIL Open Font License 1.1 (Copyright 2009 Matt McInerney) - images/ : Creative Commons Attribution-ShareAlike + app/images/ : Creative Commons Attribution-ShareAlike http://creativecommons.org/licenses/by-sa/3.0/ Some portions of noVNC are copyright to their individual authors. @@ -45,18 +45,12 @@ The are several files and projects that have been incorporated into the noVNC core library. Here is a list of those files and the original licenses (all MPL 2.0 compatible): - include/base64.js : MPL 2.0 + core/base64.js : MPL 2.0 - include/des.js : Various BSD style licenses + core/des.js : Various BSD style licenses - include/chrome-app/tcp-stream.js - : Apache 2.0 license - - utils/websockify - utils/websocket.py : LGPL 3 - - utils/inflator.partial.js - include/inflator.js : MIT (for pako) + utils/inflator.mod.js + include/inflator.js : MIT (for pako) Any other files not mentioned above are typically marked with a copyright/license header at the top of the file. The default noVNC diff --git a/images/alt.png b/app/images/alt.png similarity index 100% rename from images/alt.png rename to app/images/alt.png diff --git a/images/clipboard.png b/app/images/clipboard.png similarity index 100% rename from images/clipboard.png rename to app/images/clipboard.png diff --git a/images/connect.png b/app/images/connect.png similarity index 100% rename from images/connect.png rename to app/images/connect.png diff --git a/images/ctrl.png b/app/images/ctrl.png similarity index 100% rename from images/ctrl.png rename to app/images/ctrl.png diff --git a/images/ctrlaltdel.png b/app/images/ctrlaltdel.png similarity index 100% rename from images/ctrlaltdel.png rename to app/images/ctrlaltdel.png diff --git a/images/disconnect.png b/app/images/disconnect.png similarity index 100% rename from images/disconnect.png rename to app/images/disconnect.png diff --git a/images/drag.png b/app/images/drag.png similarity index 100% rename from images/drag.png rename to app/images/drag.png diff --git a/images/esc.png b/app/images/esc.png similarity index 100% rename from images/esc.png rename to app/images/esc.png diff --git a/images/favicon.ico b/app/images/favicon.ico similarity index 100% rename from images/favicon.ico rename to app/images/favicon.ico diff --git a/images/favicon.png b/app/images/favicon.png similarity index 100% rename from images/favicon.png rename to app/images/favicon.png diff --git a/images/fullscreen.png b/app/images/fullscreen.png similarity index 100% rename from images/fullscreen.png rename to app/images/fullscreen.png diff --git a/images/keyboard.png b/app/images/keyboard.png similarity index 100% rename from images/keyboard.png rename to app/images/keyboard.png diff --git a/images/mouse_left.png b/app/images/mouse_left.png similarity index 100% rename from images/mouse_left.png rename to app/images/mouse_left.png diff --git a/images/mouse_middle.png b/app/images/mouse_middle.png similarity index 100% rename from images/mouse_middle.png rename to app/images/mouse_middle.png diff --git a/images/mouse_none.png b/app/images/mouse_none.png similarity index 100% rename from images/mouse_none.png rename to app/images/mouse_none.png diff --git a/images/mouse_right.png b/app/images/mouse_right.png similarity index 100% rename from images/mouse_right.png rename to app/images/mouse_right.png diff --git a/images/power.png b/app/images/power.png similarity index 100% rename from images/power.png rename to app/images/power.png diff --git a/images/screen_320x460.png b/app/images/screen_320x460.png similarity index 100% rename from images/screen_320x460.png rename to app/images/screen_320x460.png diff --git a/images/screen_57x57.png b/app/images/screen_57x57.png similarity index 100% rename from images/screen_57x57.png rename to app/images/screen_57x57.png diff --git a/images/screen_700x700.png b/app/images/screen_700x700.png similarity index 100% rename from images/screen_700x700.png rename to app/images/screen_700x700.png diff --git a/images/settings.png b/app/images/settings.png similarity index 100% rename from images/settings.png rename to app/images/settings.png diff --git a/images/tab.png b/app/images/tab.png similarity index 100% rename from images/tab.png rename to app/images/tab.png diff --git a/images/toggleextrakeys.png b/app/images/toggleextrakeys.png similarity index 100% rename from images/toggleextrakeys.png rename to app/images/toggleextrakeys.png diff --git a/include/Orbitron700.ttf b/app/styles/Orbitron700.ttf similarity index 100% rename from include/Orbitron700.ttf rename to app/styles/Orbitron700.ttf diff --git a/include/Orbitron700.woff b/app/styles/Orbitron700.woff similarity index 100% rename from include/Orbitron700.woff rename to app/styles/Orbitron700.woff diff --git a/include/base.css b/app/styles/base.css similarity index 99% rename from include/base.css rename to app/styles/base.css index 8d88c0f5..382234e3 100644 --- a/include/base.css +++ b/app/styles/base.css @@ -280,7 +280,7 @@ html { /* Control bar */ #noVNC_control_bar { position:fixed; - + display:block; height:36px; left:0; diff --git a/include/black.css b/app/styles/black.css similarity index 100% rename from include/black.css rename to app/styles/black.css diff --git a/include/blue.css b/app/styles/blue.css similarity index 100% rename from include/blue.css rename to app/styles/blue.css diff --git a/include/ui.js b/app/ui.js similarity index 70% rename from include/ui.js rename to app/ui.js index d69a4f6d..78d397d7 100644 --- a/include/ui.js +++ b/app/ui.js @@ -8,19 +8,30 @@ */ /* jslint white: false, browser: true */ -/* global window, $D, Util, WebUtil, RFB, Display */ +/* global window, document.getElementById, Util, WebUtil, RFB, Display */ + +/* [module] + * import Util from "../core/util"; + * import KeyTable from "../core/input/keysym"; + * import RFB from "../core/rfb"; + * import Display from "../core/display"; + * import WebUtil from "./webutil"; + */ var UI; (function () { "use strict"; + /* [begin skip-as-module] */ // Load supporting scripts + WebUtil.load_scripts( + {'core': ["base64.js", "websock.js", "des.js", "input/keysymdef.js", + "input/xtscancodes.js", "input/util.js", "input/devices.js", + "display.js", "inflator.js", "rfb.js", "input/keysym.js"]}); + window.onscriptsload = function () { UI.load(); }; - Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js", - "keysymdef.js", "xtscancodes.js", "keyboard.js", - "input.js", "display.js", "rfb.js", "keysym.js", - "inflator.js"]); + /* [end skip-as-module] */ UI = { @@ -60,13 +71,13 @@ var UI; var sheets = WebUtil.getStylesheets(); var i; for (i = 0; i < sheets.length; i += 1) { - UI.addOption($D('noVNC_setting_stylesheet'),sheets[i].title, sheets[i].title); + UI.addOption(document.getElementById('noVNC_setting_stylesheet'),sheets[i].title, sheets[i].title); } // Logging selection dropdown var llevels = ['error', 'warn', 'info', 'debug']; for (i = 0; i < llevels.length; i += 1) { - UI.addOption($D('noVNC_setting_logging'),llevels[i], llevels[i]); + UI.addOption(document.getElementById('noVNC_setting_logging'),llevels[i], llevels[i]); } // Settings with immediate effects @@ -114,12 +125,12 @@ var UI; UI.updateVisualState(); - $D('noVNC_setting_host').focus(); + document.getElementById('noVNC_setting_host').focus(); // Show mouse selector buttons on touch screen devices if (UI.isTouchDevice) { // Show mobile buttons - $D('noVNC_mobile_buttons').style.display = "inline"; + document.getElementById('noVNC_mobile_buttons').style.display = "inline"; UI.setMouseButton(); // Remove the address bar setTimeout(function() { window.scrollTo(0, 1); }, 100); @@ -131,7 +142,7 @@ var UI; UI.setViewClip(); UI.setBarPosition(); - Util.addEvent(window, 'resize', function () { + window.addEventListener('resize', function () { UI.applyResizeMode(); UI.setViewClip(); UI.updateViewDrag(); @@ -148,18 +159,18 @@ var UI; document.documentElement.mozRequestFullScreen || document.documentElement.webkitRequestFullscreen || document.body.msRequestFullscreen)) { - $D('noVNC_fullscreen_button').style.display = "inline"; - Util.addEvent(window, 'fullscreenchange', UI.updateFullscreenButton); - Util.addEvent(window, 'mozfullscreenchange', UI.updateFullscreenButton); - Util.addEvent(window, 'webkitfullscreenchange', UI.updateFullscreenButton); - Util.addEvent(window, 'msfullscreenchange', UI.updateFullscreenButton); + document.getElementById('noVNC_fullscreen_button').style.display = "inline"; + window.addEventListener('fullscreenchange', UI.updateFullscreenButton); + window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('webkitfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('msfullscreenchange', UI.updateFullscreenButton); } - Util.addEvent(window, 'load', UI.keyboardinputReset); + window.addEventListener('load', UI.keyboardinputReset); // While connected we want to display a confirmation dialogue // if the user tries to leave the page - Util.addEvent(window, 'beforeunload', function (e) { + window.addEventListener('beforeunload', function (e) { if (UI.rfb && UI.rfb_state === 'normal') { var msg = "You are currently connected."; e.returnValue = msg; @@ -172,7 +183,7 @@ var UI; // Show description by default when hosted at for kanaka.github.com if (location.host === "kanaka.github.io") { // Open the description dialog - $D('noVNC_description').style.display = "block"; + document.getElementById('noVNC_description').style.display = "block"; } else { // Show the connect panel on first load unless autoconnecting if (autoconnect === UI.connSettingsOpen) { @@ -190,7 +201,7 @@ var UI; initRFB: function() { try { - UI.rfb = new RFB({'target': $D('noVNC_canvas'), + UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), 'onUpdateState': UI.updateState, 'onXvpInit': UI.updateXvpButton, 'onClipboard': UI.clipboardReceive, @@ -206,49 +217,49 @@ var UI; addMouseHandlers: function() { // Setup interface handlers that can't be inline - $D("noVNC_view_drag_button").onclick = UI.toggleViewDrag; - $D("noVNC_mouse_button0").onclick = function () { UI.setMouseButton(1); }; - $D("noVNC_mouse_button1").onclick = function () { UI.setMouseButton(2); }; - $D("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); }; - $D("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); }; - $D("noVNC_keyboard_button").onclick = UI.showKeyboard; + document.getElementById("noVNC_view_drag_button").onclick = UI.toggleViewDrag; + document.getElementById("noVNC_mouse_button0").onclick = function () { UI.setMouseButton(1); }; + document.getElementById("noVNC_mouse_button1").onclick = function () { UI.setMouseButton(2); }; + document.getElementById("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); }; + document.getElementById("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); }; + document.getElementById("noVNC_keyboard_button").onclick = UI.showKeyboard; - $D("noVNC_keyboardinput").oninput = UI.keyInput; - $D("noVNC_keyboardinput").onblur = UI.hideKeyboard; - $D("noVNC_keyboardinput").onsubmit = function () { return false; }; + document.getElementById("noVNC_keyboardinput").oninput = UI.keyInput; + document.getElementById("noVNC_keyboardinput").onblur = UI.hideKeyboard; + document.getElementById("noVNC_keyboardinput").onsubmit = function () { return false; }; - $D("noVNC_toggleExtraKeys_button").onclick = UI.toggleExtraKeys; - $D("noVNC_toggleCtrl_button").onclick = UI.toggleCtrl; - $D("noVNC_toggleAlt_button").onclick = UI.toggleAlt; - $D("noVNC_sendTab_button").onclick = UI.sendTab; - $D("noVNC_sendEsc_button").onclick = UI.sendEsc; + document.getElementById("noVNC_toggleExtraKeys_button").onclick = UI.toggleExtraKeys; + document.getElementById("noVNC_toggleCtrl_button").onclick = UI.toggleCtrl; + document.getElementById("noVNC_toggleAlt_button").onclick = UI.toggleAlt; + document.getElementById("noVNC_sendTab_button").onclick = UI.sendTab; + document.getElementById("noVNC_sendEsc_button").onclick = UI.sendEsc; - $D("noVNC_sendCtrlAltDel_button").onclick = UI.sendCtrlAltDel; - $D("noVNC_xvpShutdown_button").onclick = function() { UI.rfb.xvpShutdown(); }, - $D("noVNC_xvpReboot_button").onclick = function() { UI.rfb.xvpReboot(); }, - $D("noVNC_xvpReset_button").onclick = function() { UI.rfb.xvpReset(); }, - $D("noVNC_status").onclick = UI.popupStatus; - $D("noVNC_popup_status").onclick = UI.closePopup; - $D("noVNC_toggleXvp_button").onclick = UI.toggleXvpPanel; - $D("noVNC_clipboard_button").onclick = UI.toggleClipboardPanel; - $D("noVNC_fullscreen_button").onclick = UI.toggleFullscreen; - $D("noVNC_settings_button").onclick = UI.toggleSettingsPanel; - $D("noVNC_connectPanel_button").onclick = UI.toggleConnectPanel; - $D("noVNC_disconnect_button").onclick = UI.disconnect; - $D("noVNC_description_button").onclick = UI.toggleConnectPanel; + document.getElementById("noVNC_sendCtrlAltDel_button").onclick = UI.sendCtrlAltDel; + document.getElementById("noVNC_xvpShutdown_button").onclick = function() { UI.rfb.xvpShutdown(); }, + document.getElementById("noVNC_xvpReboot_button").onclick = function() { UI.rfb.xvpReboot(); }, + document.getElementById("noVNC_xvpReset_button").onclick = function() { UI.rfb.xvpReset(); }, + document.getElementById("noVNC_status").onclick = UI.popupStatus; + document.getElementById("noVNC_popup_status").onclick = UI.closePopup; + document.getElementById("noVNC_toggleXvp_button").onclick = UI.toggleXvpPanel; + document.getElementById("noVNC_clipboard_button").onclick = UI.toggleClipboardPanel; + document.getElementById("noVNC_fullscreen_button").onclick = UI.toggleFullscreen; + document.getElementById("noVNC_settings_button").onclick = UI.toggleSettingsPanel; + document.getElementById("noVNC_connectPanel_button").onclick = UI.toggleConnectPanel; + document.getElementById("noVNC_disconnect_button").onclick = UI.disconnect; + document.getElementById("noVNC_description_button").onclick = UI.toggleConnectPanel; - $D("noVNC_clipboard_text").onfocus = UI.displayBlur; - $D("noVNC_clipboard_text").onblur = UI.displayFocus; - $D("noVNC_clipboard_text").onchange = UI.clipboardSend; - $D("noVNC_clipboard_clear_button").onclick = UI.clipboardClear; + document.getElementById("noVNC_clipboard_text").onfocus = UI.displayBlur; + document.getElementById("noVNC_clipboard_text").onblur = UI.displayFocus; + document.getElementById("noVNC_clipboard_text").onchange = UI.clipboardSend; + document.getElementById("noVNC_clipboard_clear_button").onclick = UI.clipboardClear; - $D("noVNC_settings_menu").onmouseover = UI.displayBlur; - $D("noVNC_settings_menu").onmouseover = UI.displayFocus; - $D("noVNC_settings_apply").onclick = UI.settingsApply; + document.getElementById("noVNC_settings_menu").onmouseover = UI.displayBlur; + document.getElementById("noVNC_settings_menu").onmouseover = UI.displayFocus; + document.getElementById("noVNC_settings_apply").onclick = UI.settingsApply; - $D("noVNC_connect_button").onclick = UI.connect; + document.getElementById("noVNC_connect_button").onclick = UI.connect; - $D("noVNC_setting_resize").onchange = UI.enableDisableViewClip; + document.getElementById("noVNC_setting_resize").onchange = UI.enableDisableViewClip; }, /* ------^------- @@ -269,8 +280,8 @@ var UI; klass = "noVNC_status_normal"; break; case 'disconnected': - $D('noVNC_logo').style.display = "block"; - $D('noVNC_screen').style.display = "none"; + document.getElementById('noVNC_logo').style.display = "block"; + document.getElementById('noVNC_screen').style.display = "none"; /* falls through */ case 'loaded': klass = "noVNC_status_normal"; @@ -278,9 +289,9 @@ var UI; case 'password': UI.toggleConnectPanel(); - $D('noVNC_connect_button').value = "Send Password"; - $D('noVNC_connect_button').onclick = UI.setPassword; - $D('noVNC_setting_password').focus(); + document.getElementById('noVNC_connect_button').value = "Send Password"; + document.getElementById('noVNC_connect_button').onclick = UI.setPassword; + document.getElementById('noVNC_setting_password').focus(); klass = "noVNC_status_warn"; break; @@ -290,8 +301,8 @@ var UI; } if (typeof(msg) !== 'undefined') { - $D('noVNC_control_bar').setAttribute("class", klass); - $D('noVNC_status').innerHTML = msg; + document.getElementById('noVNC_control_bar').setAttribute("class", klass); + document.getElementById('noVNC_status').innerHTML = msg; } UI.updateVisualState(); @@ -302,35 +313,35 @@ var UI; var connected = UI.rfb && UI.rfb_state === 'normal'; //Util.Debug(">> updateVisualState"); - $D('noVNC_setting_encrypt').disabled = connected; - $D('noVNC_setting_true_color').disabled = connected; + document.getElementById('noVNC_setting_encrypt').disabled = connected; + document.getElementById('noVNC_setting_true_color').disabled = connected; if (Util.browserSupportsCursorURIs()) { - $D('noVNC_setting_cursor').disabled = connected; + document.getElementById('noVNC_setting_cursor').disabled = connected; } else { UI.updateSetting('cursor', !UI.isTouchDevice); - $D('noVNC_setting_cursor').disabled = true; + document.getElementById('noVNC_setting_cursor').disabled = true; } UI.enableDisableViewClip(); - $D('noVNC_setting_resize').disabled = connected; - $D('noVNC_setting_shared').disabled = connected; - $D('noVNC_setting_view_only').disabled = connected; - $D('noVNC_setting_path').disabled = connected; - $D('noVNC_setting_repeaterID').disabled = connected; + document.getElementById('noVNC_setting_resize').disabled = connected; + document.getElementById('noVNC_setting_shared').disabled = connected; + document.getElementById('noVNC_setting_view_only').disabled = connected; + document.getElementById('noVNC_setting_path').disabled = connected; + document.getElementById('noVNC_setting_repeaterID').disabled = connected; if (connected) { UI.setViewClip(); UI.setMouseButton(1); - $D('noVNC_clipboard_button').style.display = "inline"; - $D('noVNC_keyboard_button').style.display = "inline"; - $D('noVNC_extra_keys').style.display = ""; - $D('noVNC_sendCtrlAltDel_button').style.display = "inline"; + document.getElementById('noVNC_clipboard_button').style.display = "inline"; + document.getElementById('noVNC_keyboard_button').style.display = "inline"; + document.getElementById('noVNC_extra_keys').style.display = ""; + document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "inline"; } else { UI.setMouseButton(); - $D('noVNC_clipboard_button').style.display = "none"; - $D('noVNC_keyboard_button').style.display = "none"; - $D('noVNC_extra_keys').style.display = "none"; - $D('noVNC_sendCtrlAltDel_button').style.display = "none"; + document.getElementById('noVNC_clipboard_button').style.display = "none"; + document.getElementById('noVNC_keyboard_button').style.display = "none"; + document.getElementById('noVNC_extra_keys').style.display = "none"; + document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "none"; UI.updateXvpButton(0); } @@ -342,18 +353,18 @@ var UI; case 'fatal': case 'failed': case 'disconnected': - $D('noVNC_connectPanel_button').style.display = ""; - $D('noVNC_disconnect_button').style.display = "none"; + document.getElementById('noVNC_connectPanel_button').style.display = ""; + document.getElementById('noVNC_disconnect_button').style.display = "none"; UI.connSettingsOpen = false; UI.toggleConnectPanel(); break; case 'loaded': - $D('noVNC_connectPanel_button').style.display = ""; - $D('noVNC_disconnect_button').style.display = "none"; + document.getElementById('noVNC_connectPanel_button').style.display = ""; + document.getElementById('noVNC_disconnect_button').style.display = "none"; break; default: - $D('noVNC_connectPanel_button').style.display = "none"; - $D('noVNC_disconnect_button').style.display = ""; + document.getElementById('noVNC_connectPanel_button').style.display = "none"; + document.getElementById('noVNC_disconnect_button').style.display = ""; break; } @@ -361,14 +372,14 @@ var UI; }, popupStatus: function(text) { - var psp = $D('noVNC_popup_status'); + var psp = document.getElementById('noVNC_popup_status'); clearTimeout(UI.popupStatusTimeout); if (typeof text === 'string') { psp.innerHTML = text; } else { - psp.innerHTML = $D('noVNC_status').innerHTML; + psp.innerHTML = document.getElementById('noVNC_status').innerHTML; } psp.style.display = "block"; psp.style.left = window.innerWidth/2 - @@ -380,7 +391,7 @@ var UI; closePopup: function() { clearTimeout(UI.popupStatusTimeout); - $D('noVNC_popup_status').style.display = "none"; + document.getElementById('noVNC_popup_status').style.display = "none"; }, /* ------^------- @@ -412,7 +423,7 @@ var UI; // Update the settings control value = UI.getSetting(name); - var ctrl = $D('noVNC_setting_' + name); + var ctrl = document.getElementById('noVNC_setting_' + name); if (ctrl.type === 'checkbox') { ctrl.checked = value; @@ -435,7 +446,7 @@ var UI; // Save control setting to cookie saveSetting: function(name) { - var val, ctrl = $D('noVNC_setting_' + name); + var val, ctrl = document.getElementById('noVNC_setting_' + name); if (ctrl.type === 'checkbox') { val = ctrl.checked; } else if (typeof ctrl.options !== 'undefined') { @@ -456,7 +467,7 @@ var UI; // Read form control compatible setting from cookie getSetting: function(name) { - var ctrl = $D('noVNC_setting_' + name); + var ctrl = document.getElementById('noVNC_setting_' + name); var val = WebUtil.readSetting(name); if (typeof val !== 'undefined' && val !== null && ctrl.type === 'checkbox') { if (val.toString().toLowerCase() in {'0':1, 'no':1, 'false':1}) { @@ -502,7 +513,7 @@ var UI; // Open menu openSettingsMenu: function() { // Close the description panel - $D('noVNC_description').style.display = "none"; + document.getElementById('noVNC_description').style.display = "none"; // Close clipboard panel if open if (UI.clipboardOpen === true) { UI.toggleClipboardPanel(); @@ -515,15 +526,15 @@ var UI; if (UI.xvpOpen === true) { UI.toggleXvpPanel(); } - $D('noVNC_settings').style.display = "block"; - $D('noVNC_settings_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_settings').style.display = "block"; + document.getElementById('noVNC_settings_button').className = "noVNC_status_button_selected"; UI.settingsOpen = true; }, // Close menu (without applying settings) closeSettingsMenu: function() { - $D('noVNC_settings').style.display = "none"; - $D('noVNC_settings_button').className = "noVNC_status_button"; + document.getElementById('noVNC_settings').style.display = "none"; + document.getElementById('noVNC_settings_button').className = "noVNC_status_button"; UI.settingsOpen = false; }, @@ -532,7 +543,7 @@ var UI; // On close, settings are applied toggleSettingsPanel: function() { // Close the description panel - $D('noVNC_description').style.display = "none"; + document.getElementById('noVNC_description').style.display = "none"; if (UI.settingsOpen) { UI.settingsApply(); UI.closeSettingsMenu(); @@ -543,7 +554,7 @@ var UI; UI.updateSetting('cursor'); } else { UI.updateSetting('cursor', !UI.isTouchDevice); - $D('noVNC_setting_cursor').disabled = true; + document.getElementById('noVNC_setting_cursor').disabled = true; } UI.updateSetting('clip'); UI.updateSetting('resize'); @@ -567,7 +578,7 @@ var UI; // Show the XVP panel toggleXvpPanel: function() { // Close the description panel - $D('noVNC_description').style.display = "none"; + document.getElementById('noVNC_description').style.display = "none"; // Close settings if open if (UI.settingsOpen === true) { UI.settingsApply(); @@ -583,12 +594,12 @@ var UI; } // Toggle XVP panel if (UI.xvpOpen === true) { - $D('noVNC_xvp').style.display = "none"; - $D('noVNC_toggleXvp_button').className = "noVNC_status_button"; + document.getElementById('noVNC_xvp').style.display = "none"; + document.getElementById('noVNC_toggleXvp_button').className = "noVNC_status_button"; UI.xvpOpen = false; } else { - $D('noVNC_xvp').style.display = "block"; - $D('noVNC_toggleXvp_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_xvp').style.display = "block"; + document.getElementById('noVNC_toggleXvp_button').className = "noVNC_status_button_selected"; UI.xvpOpen = true; } }, @@ -596,9 +607,9 @@ var UI; // Disable/enable XVP button updateXvpButton: function(ver) { if (ver >= 1) { - $D('noVNC_toggleXvp_button').style.display = 'inline'; + document.getElementById('noVNC_toggleXvp_button').style.display = 'inline'; } else { - $D('noVNC_toggleXvp_button').style.display = 'none'; + document.getElementById('noVNC_toggleXvp_button').style.display = 'none'; // Close XVP panel if open if (UI.xvpOpen === true) { UI.toggleXvpPanel(); @@ -615,7 +626,7 @@ var UI; // Show the clipboard panel toggleClipboardPanel: function() { // Close the description panel - $D('noVNC_description').style.display = "none"; + document.getElementById('noVNC_description').style.display = "none"; // Close settings if open if (UI.settingsOpen === true) { UI.settingsApply(); @@ -631,29 +642,29 @@ var UI; } // Toggle Clipboard Panel if (UI.clipboardOpen === true) { - $D('noVNC_clipboard').style.display = "none"; - $D('noVNC_clipboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_clipboard').style.display = "none"; + document.getElementById('noVNC_clipboard_button').className = "noVNC_status_button"; UI.clipboardOpen = false; } else { - $D('noVNC_clipboard').style.display = "block"; - $D('noVNC_clipboard_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_clipboard').style.display = "block"; + document.getElementById('noVNC_clipboard_button').className = "noVNC_status_button_selected"; UI.clipboardOpen = true; } }, clipboardReceive: function(rfb, text) { Util.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "..."); - $D('noVNC_clipboard_text').value = text; + document.getElementById('noVNC_clipboard_text').value = text; Util.Debug("<< UI.clipboardReceive"); }, clipboardClear: function() { - $D('noVNC_clipboard_text').value = ""; + document.getElementById('noVNC_clipboard_text').value = ""; UI.rfb.clipboardPasteFrom(""); }, clipboardSend: function() { - var text = $D('noVNC_clipboard_text').value; + var text = document.getElementById('noVNC_clipboard_text').value; Util.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "..."); UI.rfb.clipboardPasteFrom(text); Util.Debug("<< UI.clipboardSend"); @@ -668,12 +679,12 @@ var UI; // Show the connection settings panel/menu toggleConnectPanel: function() { // Close the description panel - $D('noVNC_description').style.display = "none"; + document.getElementById('noVNC_description').style.display = "none"; // Close connection settings if open if (UI.settingsOpen === true) { UI.settingsApply(); UI.closeSettingsMenu(); - $D('noVNC_connectPanel_button').className = "noVNC_status_button"; + document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button"; } // Close clipboard panel if open if (UI.clipboardOpen === true) { @@ -686,18 +697,18 @@ var UI; // Toggle Connection Panel if (UI.connSettingsOpen === true) { - $D('noVNC_controls').style.display = "none"; - $D('noVNC_connectPanel_button').className = "noVNC_status_button"; + document.getElementById('noVNC_controls').style.display = "none"; + document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button"; UI.connSettingsOpen = false; UI.saveSetting('host'); UI.saveSetting('port'); UI.saveSetting('token'); //UI.saveSetting('password'); } else { - $D('noVNC_controls').style.display = "block"; - $D('noVNC_connectPanel_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_controls').style.display = "block"; + document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button_selected"; UI.connSettingsOpen = true; - $D('noVNC_setting_host').focus(); + document.getElementById('noVNC_setting_host').focus(); } }, @@ -705,11 +716,11 @@ var UI; UI.closeSettingsMenu(); UI.toggleConnectPanel(); - var host = $D('noVNC_setting_host').value; - var port = $D('noVNC_setting_port').value; - var password = $D('noVNC_setting_password').value; - var token = $D('noVNC_setting_token').value; - var path = $D('noVNC_setting_path').value; + var host = document.getElementById('noVNC_setting_host').value; + var port = document.getElementById('noVNC_setting_port').value; + var password = document.getElementById('noVNC_setting_password').value; + var token = document.getElementById('noVNC_setting_token').value; + var path = document.getElementById('noVNC_setting_path').value; //if token is in path then ignore the new token variable if (token) { @@ -733,8 +744,8 @@ var UI; //Close dialog. setTimeout(UI.setBarPosition, 100); - $D('noVNC_logo').style.display = "none"; - $D('noVNC_screen').style.display = "inline"; + document.getElementById('noVNC_logo').style.display = "none"; + document.getElementById('noVNC_screen').style.display = "inline"; }, disconnect: function() { @@ -744,17 +755,17 @@ var UI; // Restore the callback used for initial resize UI.rfb.set_onFBUComplete(UI.initialResize); - $D('noVNC_logo').style.display = "block"; - $D('noVNC_screen').style.display = "none"; + document.getElementById('noVNC_logo').style.display = "block"; + document.getElementById('noVNC_screen').style.display = "none"; // Don't display the connection settings until we're actually disconnected }, setPassword: function() { - UI.rfb.sendPassword($D('noVNC_setting_password').value); + UI.rfb.sendPassword(document.getElementById('noVNC_setting_password').value); //Reset connect button. - $D('noVNC_connect_button').value = "Connect"; - $D('noVNC_connect_button').onclick = UI.connect; + document.getElementById('noVNC_connect_button').value = "Connect"; + document.getElementById('noVNC_connect_button').onclick = UI.connect; //Hide connection panel. UI.toggleConnectPanel(); return false; @@ -800,9 +811,9 @@ var UI; document.mozFullScreenElement || // currently working methods document.webkitFullscreenElement || document.msFullscreenElement ) { - $D('noVNC_fullscreen_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_fullscreen_button').className = "noVNC_status_button_selected"; } else { - $D('noVNC_fullscreen_button').className = "noVNC_status_button"; + document.getElementById('noVNC_fullscreen_button').className = "noVNC_status_button"; } }, @@ -856,7 +867,7 @@ var UI; // The screen is always the same size as the available viewport // in the browser window minus the height of the control bar screenSize: function() { - var screen = $D('noVNC_screen'); + var screen = document.getElementById('noVNC_screen'); // Hide the scrollbars until the size is calculated screen.style.overflow = "hidden"; @@ -931,13 +942,13 @@ var UI; display.set_maxHeight(size.h); // Hide potential scrollbars that can skew the position - $D('noVNC_screen').style.overflow = "hidden"; + document.getElementById('noVNC_screen').style.overflow = "hidden"; // The x position marks the left margin of the canvas, // remove the margin from both sides to keep it centered - var new_w = size.w - (2 * Util.getPosition($D('noVNC_canvas')).x); + var new_w = size.w - (2 * Util.getPosition(document.getElementById('noVNC_canvas')).x); - $D('noVNC_screen').style.overflow = "visible"; + document.getElementById('noVNC_screen').style.overflow = "visible"; display.viewportChangeSize(new_w, size.h); } @@ -946,18 +957,18 @@ var UI; // Handle special cases where clipping is forced on/off or locked enableDisableViewClip: function() { - var resizeSetting = $D('noVNC_setting_resize'); + var resizeSetting = document.getElementById('noVNC_setting_resize'); var connected = UI.rfb && UI.rfb_state === 'normal'; if (UI.isSafari) { // Safari auto-hides the scrollbars which makes them // impossible to use in most cases UI.setViewClip(true); - $D('noVNC_setting_clip').disabled = true; + document.getElementById('noVNC_setting_clip').disabled = true; } else if (resizeSetting.value === 'downscale' || resizeSetting.value === 'scale') { // Disable clipping if we are scaling UI.setViewClip(false); - $D('noVNC_setting_clip').disabled = true; + document.getElementById('noVNC_setting_clip').disabled = true; } else if (document.msFullscreenElement) { // The browser is IE and we are in fullscreen mode. // - We need to force clipping while in fullscreen since @@ -965,13 +976,13 @@ var UI; UI.popupStatus("Forcing clipping mode since scrollbars aren't supported by IE in fullscreen"); UI.rememberedClipSetting = UI.getSetting('clip'); UI.setViewClip(true); - $D('noVNC_setting_clip').disabled = true; + document.getElementById('noVNC_setting_clip').disabled = true; } else if (document.body.msRequestFullscreen && UI.rememberedClip !== null) { // Restore view clip to what it was before fullscreen on IE UI.setViewClip(UI.rememberedClipSetting); - $D('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; + document.getElementById('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; } else { - $D('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; + document.getElementById('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; if (UI.isTouchDevice) { UI.setViewClip(true); } @@ -988,7 +999,7 @@ var UI; updateViewDrag: function(drag) { if (!UI.rfb) return; - var viewDragButton = $D('noVNC_view_drag_button'); + var viewDragButton = document.getElementById('noVNC_view_drag_button'); // Check if viewport drag is possible. It is only possible // if the remote display is clipping the client display. @@ -1033,7 +1044,7 @@ var UI; toggleViewDrag: function() { if (!UI.rfb) return; - var viewDragButton = $D('noVNC_view_drag_button'); + var viewDragButton = document.getElementById('noVNC_view_drag_button'); if (UI.rfb.get_viewportDrag()) { viewDragButton.className = "noVNC_status_button"; UI.rfb.set_viewportDrag(false); @@ -1051,8 +1062,8 @@ var UI; // On touch devices, show the OS keyboard showKeyboard: function() { - var kbi = $D('noVNC_keyboardinput'); - var skb = $D('noVNC_keyboard_button'); + var kbi = document.getElementById('noVNC_keyboardinput'); + var skb = document.getElementById('noVNC_keyboard_button'); var l = kbi.value.length; if(UI.keyboardVisible === false) { kbi.focus(); @@ -1068,7 +1079,7 @@ var UI; }, hideKeyboard: function() { - $D('noVNC_keyboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button"; //Weird bug in iOS if you change keyboardVisible //here it does not actually occur so next time //you click keyboard icon it doesnt work. @@ -1080,16 +1091,16 @@ var UI; keepKeyboard: function() { clearTimeout(UI.hideKeyboardTimeout); if(UI.keyboardVisible === true) { - $D('noVNC_keyboardinput').focus(); - $D('noVNC_keyboard_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_keyboardinput').focus(); + document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button_selected"; } else if(UI.keyboardVisible === false) { - $D('noVNC_keyboardinput').blur(); - $D('noVNC_keyboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_keyboardinput').blur(); + document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button"; } }, keyboardinputReset: function() { - var kbi = $D('noVNC_keyboardinput'); + var kbi = document.getElementById('noVNC_keyboardinput'); kbi.value = new Array(UI.defaultKeyboardinputLen).join("_"); UI.lastKeyboardinput = kbi.value; }, @@ -1141,7 +1152,7 @@ var UI; // Send the key events for (i = 0; i < backspaces; i++) { - UI.rfb.sendKey(XK_BackSpace); + UI.rfb.sendKey(KeyTable.XK_BackSpace); } for (i = newLen - inputs; i < newLen; i++) { UI.rfb.sendKey(newValue.charCodeAt(i)); @@ -1168,41 +1179,41 @@ var UI; toggleExtraKeys: function() { UI.keepKeyboard(); if(UI.extraKeysVisible === false) { - $D('noVNC_toggleCtrl_button').style.display = "inline"; - $D('noVNC_toggleAlt_button').style.display = "inline"; - $D('noVNC_sendTab_button').style.display = "inline"; - $D('noVNC_sendEsc_button').style.display = "inline"; - $D('noVNC_toggleExtraKeys_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_toggleCtrl_button').style.display = "inline"; + document.getElementById('noVNC_toggleAlt_button').style.display = "inline"; + document.getElementById('noVNC_sendTab_button').style.display = "inline"; + document.getElementById('noVNC_sendEsc_button').style.display = "inline"; + document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button_selected"; UI.extraKeysVisible = true; } else if(UI.extraKeysVisible === true) { - $D('noVNC_toggleCtrl_button').style.display = ""; - $D('noVNC_toggleAlt_button').style.display = ""; - $D('noVNC_sendTab_button').style.display = ""; - $D('noVNC_sendEsc_button').style.display = ""; - $D('noVNC_toggleExtraKeys_button').className = "noVNC_status_button"; + document.getElementById('noVNC_toggleCtrl_button').style.display = ""; + document.getElementById('noVNC_toggleAlt_button').style.display = ""; + document.getElementById('noVNC_sendTab_button').style.display = ""; + document.getElementById('noVNC_sendEsc_button').style.display = ""; + document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button"; UI.extraKeysVisible = false; } }, sendEsc: function() { UI.keepKeyboard(); - UI.rfb.sendKey(XK_Escape); + UI.rfb.sendKey(KeyTable.XK_Escape); }, sendTab: function() { UI.keepKeyboard(); - UI.rfb.sendKey(XK_Tab); + UI.rfb.sendKey(KeyTable.XK_Tab); }, toggleCtrl: function() { UI.keepKeyboard(); if(UI.ctrlOn === false) { - UI.rfb.sendKey(XK_Control_L, true); - $D('noVNC_toggleCtrl_button').className = "noVNC_status_button_selected"; + UI.rfb.sendKey(KeyTable.XK_Control_L, true); + document.getElementById('noVNC_toggleCtrl_button').className = "noVNC_status_button_selected"; UI.ctrlOn = true; } else if(UI.ctrlOn === true) { - UI.rfb.sendKey(XK_Control_L, false); - $D('noVNC_toggleCtrl_button').className = "noVNC_status_button"; + UI.rfb.sendKey(KeyTable.XK_Control_L, false); + document.getElementById('noVNC_toggleCtrl_button').className = "noVNC_status_button"; UI.ctrlOn = false; } }, @@ -1210,12 +1221,12 @@ var UI; toggleAlt: function() { UI.keepKeyboard(); if(UI.altOn === false) { - UI.rfb.sendKey(XK_Alt_L, true); - $D('noVNC_toggleAlt_button').className = "noVNC_status_button_selected"; + UI.rfb.sendKey(KeyTable.XK_Alt_L, true); + document.getElementById('noVNC_toggleAlt_button').className = "noVNC_status_button_selected"; UI.altOn = true; } else if(UI.altOn === true) { - UI.rfb.sendKey(XK_Alt_L, false); - $D('noVNC_toggleAlt_button').className = "noVNC_status_button"; + UI.rfb.sendKey(KeyTable.XK_Alt_L, false); + document.getElementById('noVNC_toggleAlt_button').className = "noVNC_status_button"; UI.altOn = false; } }, @@ -1241,7 +1252,7 @@ var UI; var blist = [0, 1,2,4]; for (var b = 0; b < blist.length; b++) { - var button = $D('noVNC_mouse_button' + blist[b]); + var button = document.getElementById('noVNC_mouse_button' + blist[b]); if (blist[b] === num) { button.style.display = ""; } else { @@ -1278,11 +1289,11 @@ var UI; }, setBarPosition: function() { - $D('noVNC_control_bar').style.top = (window.pageYOffset) + 'px'; - $D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px'; + document.getElementById('noVNC_control_bar').style.top = (window.pageYOffset) + 'px'; + document.getElementById('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px'; - var vncwidth = $D('noVNC_container').style.offsetWidth; - $D('noVNC_control_bar').style.width = vncwidth + 'px'; + var vncwidth = document.getElementById('noVNC_container').style.offsetWidth; + document.getElementById('noVNC_control_bar').style.width = vncwidth + 'px'; } /* ------^------- @@ -1290,4 +1301,8 @@ var UI; * ============== */ }; + + /* [module] UI.load(); */ })(); + +/* [module] export default UI; */ diff --git a/include/webutil.js b/app/webutil.js similarity index 72% rename from include/webutil.js rename to app/webutil.js index 9ee34730..7f234dbf 100644 --- a/include/webutil.js +++ b/app/webutil.js @@ -10,25 +10,12 @@ /*jslint bitwise: false, white: false, browser: true, devel: true */ /*global Util, window, document */ -// Globals defined here -var WebUtil = {}, $D; - -/* - * Simple DOM selector by ID +/* [module] + * import Util from "../core/util"; */ -if (!window.$D) { - window.$D = function (id) { - if (document.getElementById) { - return document.getElementById(id); - } else if (document.all) { - return document.all[id]; - } else if (document.layers) { - return document.layers[id]; - } - return undefined; - }; -} +// Globals defined here +var WebUtil = {}; /* * ------------------------------------------------------ @@ -290,3 +277,74 @@ WebUtil.injectParamIfMissing = function (path, param, value) { return elem.pathname + elem.search + elem.hash; } }; + +// Dynamically load scripts without using document.write() +// Reference: http://unixpapa.com/js/dyna.html +// +// Handles the case where load_scripts is invoked from a script that +// itself is loaded via load_scripts. Once all scripts are loaded the +// window.onscriptsloaded handler is called (if set). +WebUtil.get_include_uri = function (root_dir) { + return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/'; +}; +WebUtil._loading_scripts = []; +WebUtil._pending_scripts = []; +WebUtil.load_scripts = function (files_by_dir) { + "use strict"; + var head = document.getElementsByTagName('head')[0], script, + ls = WebUtil._loading_scripts, ps = WebUtil._pending_scripts; + + var loadFunc = function (e) { + while (ls.length > 0 && (ls[0].readyState === 'loaded' || + ls[0].readyState === 'complete')) { + // For IE, append the script to trigger execution + var s = ls.shift(); + //console.log("loaded script: " + s.src); + head.appendChild(s); + } + if (!this.readyState || + (Util.Engine.presto && this.readyState === 'loaded') || + this.readyState === 'complete') { + if (ps.indexOf(this) >= 0) { + this.onload = this.onreadystatechange = null; + //console.log("completed script: " + this.src); + ps.splice(ps.indexOf(this), 1); + + // Call window.onscriptsload after last script loads + if (ps.length === 0 && window.onscriptsload) { + window.onscriptsload(); + } + } + } + }; + + var root_dirs = Object.keys(files_by_dir); + + for (var d = 0; d < root_dirs.length; d++) { + var root_dir = root_dirs[d]; + var files = files_by_dir[root_dir]; + + for (var f = 0; f < files.length; f++) { + script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = WebUtil.get_include_uri(root_dir) + files[f]; + //console.log("loading script: " + script.src); + script.onload = script.onreadystatechange = loadFunc; + // In-order script execution tricks + if (Util.Engine.trident) { + // For IE wait until readyState is 'loaded' before + // appending it which will trigger execution + // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order + ls.push(script); + } else { + // For webkit and firefox set async=false and append now + // https://developer.mozilla.org/en-US/docs/HTML/Element/script + script.async = false; + head.appendChild(script); + } + ps.push(script); + } + } +}; + +/* [module] export default WebUtil; */ diff --git a/include/base64.js b/core/base64.js similarity index 99% rename from include/base64.js rename to core/base64.js index 651fbadc..2b4f948f 100644 --- a/include/base64.js +++ b/core/base64.js @@ -85,7 +85,7 @@ var Base64 = { console.error("Illegal character code " + data.charCodeAt(i) + " at position " + i); continue; } - + // Collect data into leftdata, update bitcount leftdata = (leftdata << 6) | c; leftbits += 6; @@ -111,3 +111,5 @@ var Base64 = { return result; } }; /* End of Base64 namespace */ + +/* [module] export default Base64; */ diff --git a/include/des.js b/core/des.js similarity index 99% rename from include/des.js rename to core/des.js index ecbc819e..c9a4753a 100644 --- a/include/des.js +++ b/core/des.js @@ -25,16 +25,16 @@ * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and - * without fee is hereby granted, provided that this copyright notice is kept - * intact. - * + * without fee is hereby granted, provided that this copyright notice is kept + * intact. + * * WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. - * + * * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT @@ -77,7 +77,7 @@ /* jslint white: false */ -function DES(passwd) { +/* [module] export default */ function DES(passwd) { "use strict"; // Tables, permutations, S-boxes, etc. @@ -273,4 +273,4 @@ function DES(passwd) { setKeys(passwd); // Setup keys return {'encrypt': encrypt}; // Public interface -} // function DES +}; // function DES diff --git a/include/display.js b/core/display.js similarity index 92% rename from include/display.js rename to core/display.js index ade0451a..e6239f48 100644 --- a/include/display.js +++ b/core/display.js @@ -10,7 +10,89 @@ /*jslint browser: true, white: false */ /*global Util, Base64, changeCursor */ -var Display; +/* [module] + * import Util from "./util"; + * import Base64 from "./base64"; + */ + +/* [module] export default */ function Display(defaults) { + this._drawCtx = null; + this._c_forceCanvas = false; + + this._renderQ = []; // queue drawing actions for in-oder rendering + + // the full frame buffer (logical canvas) size + this._fb_width = 0; + this._fb_height = 0; + + // the size limit of the viewport (start disabled) + this._maxWidth = 0; + this._maxHeight = 0; + + // the visible "physical canvas" viewport + this._viewportLoc = { 'x': 0, 'y': 0, 'w': 0, 'h': 0 }; + this._cleanRect = { 'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1 }; + + this._prevDrawStyle = ""; + this._tile = null; + this._tile16x16 = null; + this._tile_x = 0; + this._tile_y = 0; + + Util.set_defaults(this, defaults, { + 'true_color': true, + 'colourMap': [], + 'scale': 1.0, + 'viewport': false, + 'render_mode': '' + }); + + Util.Debug(">> Display.constructor"); + + 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"); + } + + if (!this._drawCtx) { + this._drawCtx = this._target.getContext('2d'); + } + + Util.Debug("User Agent: " + navigator.userAgent); + if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); } + if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); } + if (Util.Engine.trident) { Util.Debug("Browser: trident " + Util.Engine.trident); } + if (Util.Engine.presto) { Util.Debug("Browser: presto " + Util.Engine.presto); } + + this.clear(); + + // Check canvas features + if ('createImageData' in this._drawCtx) { + this._render_mode = 'canvas rendering'; + } else { + throw new Error("Canvas does not support createImageData"); + } + + if (this._prefer_js === null) { + Util.Info("Prefering javascript operations"); + this._prefer_js = true; + } + + // Determine browser support for setting the cursor via data URI scheme + if (this._cursor_uri || this._cursor_uri === null || + this._cursor_uri === undefined) { + this._cursor_uri = Util.browserSupportsCursorURIs(); + } + + Util.Debug("<< Display.constructor"); +}; (function () { "use strict"; @@ -23,84 +105,6 @@ var Display; // ignore failure } - Display = function (defaults) { - this._drawCtx = null; - this._c_forceCanvas = false; - - this._renderQ = []; // queue drawing actions for in-oder rendering - - // the full frame buffer (logical canvas) size - this._fb_width = 0; - this._fb_height = 0; - - // the size limit of the viewport (start disabled) - this._maxWidth = 0; - this._maxHeight = 0; - - // the visible "physical canvas" viewport - this._viewportLoc = { 'x': 0, 'y': 0, 'w': 0, 'h': 0 }; - this._cleanRect = { 'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1 }; - - this._prevDrawStyle = ""; - this._tile = null; - this._tile16x16 = null; - this._tile_x = 0; - this._tile_y = 0; - - Util.set_defaults(this, defaults, { - 'true_color': true, - 'colourMap': [], - 'scale': 1.0, - 'viewport': false, - 'render_mode': '' - }); - - Util.Debug(">> Display.constructor"); - - 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"); - } - - if (!this._drawCtx) { - this._drawCtx = this._target.getContext('2d'); - } - - Util.Debug("User Agent: " + navigator.userAgent); - if (Util.Engine.gecko) { Util.Debug("Browser: gecko " + Util.Engine.gecko); } - if (Util.Engine.webkit) { Util.Debug("Browser: webkit " + Util.Engine.webkit); } - if (Util.Engine.trident) { Util.Debug("Browser: trident " + Util.Engine.trident); } - if (Util.Engine.presto) { Util.Debug("Browser: presto " + Util.Engine.presto); } - - this.clear(); - - // Check canvas features - if ('createImageData' in this._drawCtx) { - this._render_mode = 'canvas rendering'; - } else { - throw new Error("Canvas does not support createImageData"); - } - - if (this._prefer_js === null) { - Util.Info("Prefering javascript operations"); - this._prefer_js = true; - } - - // Determine browser support for setting the cursor via data URI scheme - if (this._cursor_uri || this._cursor_uri === null || - this._cursor_uri === undefined) { - this._cursor_uri = Util.browserSupportsCursorURIs(); - } - - Util.Debug("<< Display.constructor"); - }; Display.prototype = { // Public methods @@ -774,7 +778,7 @@ var Display; } if (this._renderQ.length > 0) { - requestAnimFrame(this._scan_renderQ.bind(this)); + requestAnimationFrame(this._scan_renderQ.bind(this)); } }, }; diff --git a/include/inflator.js b/core/inflator.js similarity index 95% rename from include/inflator.js rename to core/inflator.js index 48ede208..973836d7 100644 --- a/include/inflator.js +++ b/core/inflator.js @@ -1,4 +1,46 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.inflator = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o this.chunkSize) { + this.chunkSize = expected; + this.strm.output = new Uint8Array(this.chunkSize); + } + + this.strm.avail_out = this.chunkSize; + + zlib.inflate(this.strm, flush); + + return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); + }, + + reset: function () { + zlib.inflateReset(this.strm); + } +}; + +module.exports = { Inflate: Inflate }; + +},{"pako/lib/zlib/inflate.js":6,"pako/lib/zlib/zstream.js":8}],2:[function(require,module,exports){ 'use strict'; @@ -40,28 +82,28 @@ exports.shrinkBuf = function (buf, size) { var fnTyped = { arraySet: function (dest, src, src_offs, len, dest_offs) { if (src.subarray && dest.subarray) { - dest.set(src.subarray(src_offs, src_offs+len), dest_offs); + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); return; } // Fallback to ordinary array - for (var i=0; i>> 1)) : (c >>> 1)); + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); } table[n] = c; } @@ -167,7 +209,7 @@ function crc32(crc, buf, len, pos) { var t = crcTable, end = pos + len; - crc = crc ^ (-1); + crc ^= -1; for (var i = pos; i < end; i++) { crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; @@ -179,7 +221,7 @@ function crc32(crc, buf, len, pos) { module.exports = crc32; -},{}],4:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ 'use strict'; // See state defs from inflate.js @@ -507,14 +549,14 @@ module.exports = function inflate_fast(strm, start) { return; }; -},{}],5:[function(require,module,exports){ +},{}],6:[function(require,module,exports){ 'use strict'; -var utils = require('../utils/common'); -var adler32 = require('./adler32'); -var crc32 = require('./crc32'); -var inflate_fast = require('./inffast'); +var utils = require('../utils/common'); +var adler32 = require('./adler32'); +var crc32 = require('./crc32'); +var inflate_fast = require('./inffast'); var inflate_table = require('./inftrees'); var CODES = 0; @@ -602,7 +644,7 @@ var MAX_WBITS = 15; var DEF_WBITS = MAX_WBITS; -function ZSWAP32(q) { +function zswap32(q) { return (((q >>> 24) & 0xff) + ((q >>> 8) & 0xff00) + ((q & 0xff00) << 8) + @@ -795,13 +837,13 @@ function fixedtables(state) { while (sym < 280) { state.lens[sym++] = 7; } while (sym < 288) { state.lens[sym++] = 8; } - inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9}); + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); /* distance table */ sym = 0; while (sym < 32) { state.lens[sym++] = 5; } - inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5}); + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); /* do this just once */ virgin = false; @@ -843,7 +885,7 @@ function updatewindow(strm, src, end, copy) { /* copy state->wsize or less output bytes into the circular window */ if (copy >= state.wsize) { - utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0); + utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); state.wnext = 0; state.whave = state.wsize; } @@ -853,11 +895,11 @@ function updatewindow(strm, src, end, copy) { dist = copy; } //zmemcpy(state->window + state->wnext, end - copy, dist); - utils.arraySet(state.window,src, end - copy, dist, state.wnext); + utils.arraySet(state.window, src, end - copy, dist, state.wnext); copy -= dist; if (copy) { //zmemcpy(state->window, end - copy, copy); - utils.arraySet(state.window,src, end - copy, copy, 0); + utils.arraySet(state.window, src, end - copy, copy, 0); state.wnext = copy; state.whave = state.wsize; } @@ -894,7 +936,7 @@ function inflate(strm, flush) { var n; // temporary var for NEED_BITS var order = /* permutation of code lengths */ - [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; if (!strm || !strm.state || !strm.output || @@ -1221,7 +1263,7 @@ function inflate(strm, flush) { state.head.hcrc = ((state.flags >> 9) & 1); state.head.done = true; } - strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/; + strm.adler = state.check = 0; state.mode = TYPE; break; case DICTID: @@ -1233,7 +1275,7 @@ function inflate(strm, flush) { bits += 8; } //===// - strm.adler = state.check = ZSWAP32(hold); + strm.adler = state.check = zswap32(hold); //=== INITBITS(); hold = 0; bits = 0; @@ -1425,7 +1467,7 @@ function inflate(strm, flush) { state.lencode = state.lendyn; state.lenbits = 7; - opts = {bits: state.lenbits}; + opts = { bits: state.lenbits }; ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); state.lenbits = opts.bits; @@ -1556,7 +1598,7 @@ function inflate(strm, flush) { concerning the ENOUGH constants, which depend on those values */ state.lenbits = 9; - opts = {bits: state.lenbits}; + opts = { bits: state.lenbits }; ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); // We have separate tables & no pointers. 2 commented lines below not needed. // state.next_index = opts.table_index; @@ -1573,7 +1615,7 @@ function inflate(strm, flush) { //state.distcode.copy(state.codes); // Switch to use dynamic table state.distcode = state.distdyn; - opts = {bits: state.distbits}; + opts = { bits: state.distbits }; ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); // We have separate tables & no pointers. 2 commented lines below not needed. // state.next_index = opts.table_index; @@ -1621,7 +1663,7 @@ function inflate(strm, flush) { } state.back = 0; for (;;) { - here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/ + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ here_bits = here >>> 24; here_op = (here >>> 16) & 0xff; here_val = here & 0xffff; @@ -1640,7 +1682,7 @@ function inflate(strm, flush) { last_val = here_val; for (;;) { here = state.lencode[last_val + - ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; here_bits = here >>> 24; here_op = (here >>> 16) & 0xff; here_val = here & 0xffff; @@ -1697,7 +1739,7 @@ function inflate(strm, flush) { bits += 8; } //===// - state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; //--- DROPBITS(state.extra) ---// hold >>>= state.extra; bits -= state.extra; @@ -1710,7 +1752,7 @@ function inflate(strm, flush) { /* falls through */ case DIST: for (;;) { - here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/ + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ here_bits = here >>> 24; here_op = (here >>> 16) & 0xff; here_val = here & 0xffff; @@ -1729,7 +1771,7 @@ function inflate(strm, flush) { last_val = here_val; for (;;) { here = state.distcode[last_val + - ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; here_bits = here >>> 24; here_op = (here >>> 16) & 0xff; here_val = here & 0xffff; @@ -1773,7 +1815,7 @@ function inflate(strm, flush) { bits += 8; } //===// - state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; //--- DROPBITS(state.extra) ---// hold >>>= state.extra; bits -= state.extra; @@ -1867,8 +1909,8 @@ function inflate(strm, flush) { } _out = left; - // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too - if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) { + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { strm.msg = 'incorrect data check'; state.mode = BAD; break; @@ -1990,6 +2032,41 @@ function inflateGetHeader(strm, head) { return Z_OK; } +function inflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var state; + var dictid; + var ret; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; + } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} exports.inflateReset = inflateReset; exports.inflateReset2 = inflateReset2; @@ -1999,6 +2076,7 @@ exports.inflateInit2 = inflateInit2; exports.inflate = inflate; exports.inflateEnd = inflateEnd; exports.inflateGetHeader = inflateGetHeader; +exports.inflateSetDictionary = inflateSetDictionary; exports.inflateInfo = 'pako inflate (from Nodeca project)'; /* Not implemented @@ -2006,13 +2084,12 @@ exports.inflateCopy = inflateCopy; exports.inflateGetDictionary = inflateGetDictionary; exports.inflateMark = inflateMark; exports.inflatePrime = inflatePrime; -exports.inflateSetDictionary = inflateSetDictionary; exports.inflateSync = inflateSync; exports.inflateSyncPoint = inflateSyncPoint; exports.inflateUndermine = inflateUndermine; */ -},{"../utils/common":1,"./adler32":2,"./crc32":3,"./inffast":4,"./inftrees":6}],6:[function(require,module,exports){ +},{"../utils/common":2,"./adler32":3,"./crc32":4,"./inffast":5,"./inftrees":7}],7:[function(require,module,exports){ 'use strict'; @@ -2072,8 +2149,8 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta var base_index = 0; // var shoextra; /* extra bits table to use */ var end; /* use base and extra for symbol > end */ - var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */ - var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */ + var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ var extra = null; var extra_index = 0; @@ -2242,7 +2319,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 1; } - var i=0; + var i = 0; /* process all codes and make table entries */ for (;;) { i++; @@ -2341,7 +2418,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta return 0; }; -},{"../utils/common":1}],7:[function(require,module,exports){ +},{"../utils/common":2}],8:[function(require,module,exports){ 'use strict'; @@ -2372,47 +2449,5 @@ function ZStream() { module.exports = ZStream; -},{}],8:[function(require,module,exports){ -var zlib = require('../node_modules/pako/lib/zlib/inflate.js'); -var ZStream = require('../node_modules/pako/lib/zlib/zstream.js'); - -var Inflate = function () { - this.strm = new ZStream(); - this.chunkSize = 1024 * 10 * 10; - this.strm.output = new Uint8Array(this.chunkSize); - this.windowBits = 5; - - zlib.inflateInit(this.strm, this.windowBits); -}; - -Inflate.prototype = { - inflate: function (data, flush, expected) { - this.strm.input = data; - this.strm.avail_in = this.strm.input.length; - this.strm.next_in = 0; - this.strm.next_out = 0; - - // resize our output buffer if it's too small - // (we could just use multiple chunks, but that would cause an extra - // allocation each time to flatten the chunks) - if (expected > this.chunkSize) { - this.chunkSize = expected; - this.strm.output = new Uint8Array(this.chunkSize); - } - - this.strm.avail_out = this.chunkSize; - - zlib.inflate(this.strm, flush); - - return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out); - }, - - reset: function () { - zlib.inflateReset(this.strm); - } -}; - -module.exports = {Inflate: Inflate}; - -},{"../node_modules/pako/lib/zlib/inflate.js":5,"../node_modules/pako/lib/zlib/zstream.js":7}]},{},[8])(8) +},{}]},{},[1])(1) }); \ No newline at end of file diff --git a/utils/inflator.partial.js b/core/inflator.mod.js similarity index 83% rename from utils/inflator.partial.js rename to core/inflator.mod.js index 8b6d1095..26e6441b 100644 --- a/utils/inflator.partial.js +++ b/core/inflator.mod.js @@ -1,7 +1,7 @@ -var zlib = require('../node_modules/pako/lib/zlib/inflate.js'); -var ZStream = require('../node_modules/pako/lib/zlib/zstream.js'); +var zlib = require('pako/lib/zlib/inflate.js'); +var ZStream = require('pako/lib/zlib/zstream.js'); -var Inflate = function () { +function Inflate() { this.strm = new ZStream(); this.chunkSize = 1024 * 10 * 10; this.strm.output = new Uint8Array(this.chunkSize); @@ -37,4 +37,4 @@ Inflate.prototype = { } }; -module.exports = {Inflate: Inflate}; +module.exports = { Inflate: Inflate }; diff --git a/include/input.js b/core/input/devices.js similarity index 79% rename from include/input.js rename to core/input/devices.js index eb4d18a3..d283fc4e 100644 --- a/include/input.js +++ b/core/input/devices.js @@ -8,7 +8,12 @@ /*jslint browser: true, white: false */ /*global window, Util */ -var Keyboard, Mouse; +/* [module] + * import Util from "../util"; + * import KeyboardUtil from "./util"; + */ + +/* [module] export */ var Keyboard; (function () { "use strict"; @@ -27,10 +32,10 @@ var Keyboard, Mouse; }); // create the keyboard handler - this._handler = new KeyEventDecoder(kbdUtil.ModifierSync(), - VerifyCharModifier( /* jshint newcap: false */ - TrackKeyState( - EscapeModifiers(this._handleRfbEvent.bind(this)) + this._handler = new KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), + KeyboardUtil.VerifyCharModifier( /* jshint newcap: false */ + KeyboardUtil.TrackKeyState( + KeyboardUtil.EscapeModifiers(this._handleRfbEvent.bind(this)) ) ) ); /* jshint newcap: true */ @@ -56,8 +61,8 @@ var Keyboard, Mouse; }, setQEMUVNCKeyboardHandler: function () { - this._handler = new QEMUKeyEventDecoder(kbdUtil.ModifierSync(), - TrackQEMUKeyState( + this._handler = new KeyboardUtil.QEMUKeyEventDecoder(KeyboardUtil.ModifierSync(), + KeyboardUtil.TrackQEMUKeyState( this._handleRfbEvent.bind(this) ) ); @@ -117,12 +122,12 @@ var Keyboard, Mouse; //Util.Debug(">> Keyboard.grab"); var c = this._target; - Util.addEvent(c, 'keydown', this._eventHandlers.keydown); - Util.addEvent(c, 'keyup', this._eventHandlers.keyup); - Util.addEvent(c, 'keypress', this._eventHandlers.keypress); + c.addEventListener('keydown', this._eventHandlers.keydown); + c.addEventListener('keyup', this._eventHandlers.keyup); + c.addEventListener('keypress', this._eventHandlers.keypress); // Release (key up) if window loses focus - Util.addEvent(window, 'blur', this._eventHandlers.blur); + window.addEventListener('blur', this._eventHandlers.blur); //Util.Debug("<< Keyboard.grab"); }, @@ -131,10 +136,10 @@ var Keyboard, Mouse; //Util.Debug(">> Keyboard.ungrab"); var c = this._target; - Util.removeEvent(c, 'keydown', this._eventHandlers.keydown); - Util.removeEvent(c, 'keyup', this._eventHandlers.keyup); - Util.removeEvent(c, 'keypress', this._eventHandlers.keypress); - Util.removeEvent(window, 'blur', this._eventHandlers.blur); + c.removeEventListener('keydown', this._eventHandlers.keydown); + c.removeEventListener('keyup', this._eventHandlers.keyup); + c.removeEventListener('keypress', this._eventHandlers.keypress); + window.removeEventListener('blur', this._eventHandlers.blur); // Release (key up) all keys that are in a down state this._allKeysUp(); @@ -153,11 +158,11 @@ var Keyboard, Mouse; ['onKeyPress', 'rw', 'func'] // Handler for key press/release ]); +})(); - // - // Mouse event handler - // +/* [module] export */ var Mouse; +(function () { Mouse = function (defaults) { this._mouseCaptured = false; @@ -342,44 +347,44 @@ var Keyboard, Mouse; var c = this._target; if ('ontouchstart' in document.documentElement) { - Util.addEvent(c, 'touchstart', this._eventHandlers.mousedown); - Util.addEvent(window, 'touchend', this._eventHandlers.mouseup); - Util.addEvent(c, 'touchend', this._eventHandlers.mouseup); - Util.addEvent(c, 'touchmove', this._eventHandlers.mousemove); + c.addEventListener('touchstart', this._eventHandlers.mousedown); + window.addEventListener('touchend', this._eventHandlers.mouseup); + c.addEventListener('touchend', this._eventHandlers.mouseup); + c.addEventListener('touchmove', this._eventHandlers.mousemove); } else { - Util.addEvent(c, 'mousedown', this._eventHandlers.mousedown); - Util.addEvent(window, 'mouseup', this._eventHandlers.mouseup); - Util.addEvent(c, 'mouseup', this._eventHandlers.mouseup); - Util.addEvent(c, 'mousemove', this._eventHandlers.mousemove); - Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', + c.addEventListener('mousedown', this._eventHandlers.mousedown); + window.addEventListener('mouseup', this._eventHandlers.mouseup); + c.addEventListener('mouseup', this._eventHandlers.mouseup); + c.addEventListener('mousemove', this._eventHandlers.mousemove); + c.addEventListener((Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', this._eventHandlers.mousewheel); } /* Work around right and middle click browser behaviors */ - Util.addEvent(document, 'click', this._eventHandlers.mousedisable); - Util.addEvent(document.body, 'contextmenu', this._eventHandlers.mousedisable); + document.addEventListener('click', this._eventHandlers.mousedisable); + document.body.addEventListener('contextmenu', this._eventHandlers.mousedisable); }, ungrab: function () { var c = this._target; if ('ontouchstart' in document.documentElement) { - Util.removeEvent(c, 'touchstart', this._eventHandlers.mousedown); - Util.removeEvent(window, 'touchend', this._eventHandlers.mouseup); - Util.removeEvent(c, 'touchend', this._eventHandlers.mouseup); - Util.removeEvent(c, 'touchmove', this._eventHandlers.mousemove); + c.removeEventListener('touchstart', this._eventHandlers.mousedown); + window.removeEventListener('touchend', this._eventHandlers.mouseup); + c.removeEventListener('touchend', this._eventHandlers.mouseup); + c.removeEventListener('touchmove', this._eventHandlers.mousemove); } else { - Util.removeEvent(c, 'mousedown', this._eventHandlers.mousedown); - Util.removeEvent(window, 'mouseup', this._eventHandlers.mouseup); - Util.removeEvent(c, 'mouseup', this._eventHandlers.mouseup); - Util.removeEvent(c, 'mousemove', this._eventHandlers.mousemove); - Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', + c.removeEventListener('mousedown', this._eventHandlers.mousedown); + window.removeEventListener('mouseup', this._eventHandlers.mouseup); + c.removeEventListener('mouseup', this._eventHandlers.mouseup); + c.removeEventListener('mousemove', this._eventHandlers.mousemove); + c.removeEventListener((Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', this._eventHandlers.mousewheel); } /* Work around right and middle click browser behaviors */ - Util.removeEvent(document, 'click', this._eventHandlers.mousedisable); - Util.removeEvent(document.body, 'contextmenu', this._eventHandlers.mousedisable); + document.removeEventListener('click', this._eventHandlers.mousedisable); + document.body.removeEventListener('contextmenu', this._eventHandlers.mousedisable); } }; diff --git a/core/input/keysym.js b/core/input/keysym.js new file mode 100644 index 00000000..5983c38a --- /dev/null +++ b/core/input/keysym.js @@ -0,0 +1,382 @@ +var KeyTable = { + XK_VoidSymbol: 0xffffff, /* Void symbol */ + + XK_BackSpace: 0xff08, /* Back space, back char */ + XK_Tab: 0xff09, + XK_Linefeed: 0xff0a, /* Linefeed, LF */ + XK_Clear: 0xff0b, + XK_Return: 0xff0d, /* Return, enter */ + XK_Pause: 0xff13, /* Pause, hold */ + XK_Scroll_Lock: 0xff14, + XK_Sys_Req: 0xff15, + XK_Escape: 0xff1b, + XK_Delete: 0xffff, /* Delete, rubout */ + + /* Cursor control & motion */ + + XK_Home: 0xff50, + XK_Left: 0xff51, /* Move left, left arrow */ + XK_Up: 0xff52, /* Move up, up arrow */ + XK_Right: 0xff53, /* Move right, right arrow */ + XK_Down: 0xff54, /* Move down, down arrow */ + XK_Prior: 0xff55, /* Prior, previous */ + XK_Page_Up: 0xff55, + XK_Next: 0xff56, /* Next */ + XK_Page_Down: 0xff56, + XK_End: 0xff57, /* EOL */ + XK_Begin: 0xff58, /* BOL */ + + + /* Misc functions */ + + XK_Select: 0xff60, /* Select, mark */ + XK_Print: 0xff61, + XK_Execute: 0xff62, /* Execute, run, do */ + XK_Insert: 0xff63, /* Insert, insert here */ + XK_Undo: 0xff65, + XK_Redo: 0xff66, /* Redo, again */ + XK_Menu: 0xff67, + XK_Find: 0xff68, /* Find, search */ + XK_Cancel: 0xff69, /* Cancel, stop, abort, exit */ + XK_Help: 0xff6a, /* Help */ + XK_Break: 0xff6b, + XK_Mode_switch: 0xff7e, /* Character set switch */ + XK_script_switch: 0xff7e, /* Alias for mode_switch */ + XK_Num_Lock: 0xff7f, + + /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ + + XK_KP_Space: 0xff80, /* Space */ + XK_KP_Tab: 0xff89, + XK_KP_Enter: 0xff8d, /* Enter */ + XK_KP_F1: 0xff91, /* PF1, KP_A, ... */ + XK_KP_F2: 0xff92, + XK_KP_F3: 0xff93, + XK_KP_F4: 0xff94, + XK_KP_Home: 0xff95, + XK_KP_Left: 0xff96, + XK_KP_Up: 0xff97, + XK_KP_Right: 0xff98, + XK_KP_Down: 0xff99, + XK_KP_Prior: 0xff9a, + XK_KP_Page_Up: 0xff9a, + XK_KP_Next: 0xff9b, + XK_KP_Page_Down: 0xff9b, + XK_KP_End: 0xff9c, + XK_KP_Begin: 0xff9d, + XK_KP_Insert: 0xff9e, + XK_KP_Delete: 0xff9f, + XK_KP_Equal: 0xffbd, /* Equals */ + XK_KP_Multiply: 0xffaa, + XK_KP_Add: 0xffab, + XK_KP_Separator: 0xffac, /* Separator, often comma */ + XK_KP_Subtract: 0xffad, + XK_KP_Decimal: 0xffae, + XK_KP_Divide: 0xffaf, + + XK_KP_0: 0xffb0, + XK_KP_1: 0xffb1, + XK_KP_2: 0xffb2, + XK_KP_3: 0xffb3, + XK_KP_4: 0xffb4, + XK_KP_5: 0xffb5, + XK_KP_6: 0xffb6, + XK_KP_7: 0xffb7, + XK_KP_8: 0xffb8, + XK_KP_9: 0xffb9, + + /* + * Auxiliary functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufacturers have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + + XK_F1: 0xffbe, + XK_F2: 0xffbf, + XK_F3: 0xffc0, + XK_F4: 0xffc1, + XK_F5: 0xffc2, + XK_F6: 0xffc3, + XK_F7: 0xffc4, + XK_F8: 0xffc5, + XK_F9: 0xffc6, + XK_F10: 0xffc7, + XK_F11: 0xffc8, + XK_L1: 0xffc8, + XK_F12: 0xffc9, + XK_L2: 0xffc9, + XK_F13: 0xffca, + XK_L3: 0xffca, + XK_F14: 0xffcb, + XK_L4: 0xffcb, + XK_F15: 0xffcc, + XK_L5: 0xffcc, + XK_F16: 0xffcd, + XK_L6: 0xffcd, + XK_F17: 0xffce, + XK_L7: 0xffce, + XK_F18: 0xffcf, + XK_L8: 0xffcf, + XK_F19: 0xffd0, + XK_L9: 0xffd0, + XK_F20: 0xffd1, + XK_L10: 0xffd1, + XK_F21: 0xffd2, + XK_R1: 0xffd2, + XK_F22: 0xffd3, + XK_R2: 0xffd3, + XK_F23: 0xffd4, + XK_R3: 0xffd4, + XK_F24: 0xffd5, + XK_R4: 0xffd5, + XK_F25: 0xffd6, + XK_R5: 0xffd6, + XK_F26: 0xffd7, + XK_R6: 0xffd7, + XK_F27: 0xffd8, + XK_R7: 0xffd8, + XK_F28: 0xffd9, + XK_R8: 0xffd9, + XK_F29: 0xffda, + XK_R9: 0xffda, + XK_F30: 0xffdb, + XK_R10: 0xffdb, + XK_F31: 0xffdc, + XK_R11: 0xffdc, + XK_F32: 0xffdd, + XK_R12: 0xffdd, + XK_F33: 0xffde, + XK_R13: 0xffde, + XK_F34: 0xffdf, + XK_R14: 0xffdf, + XK_F35: 0xffe0, + XK_R15: 0xffe0, + + /* Modifiers */ + + XK_Shift_L: 0xffe1, /* Left shift */ + XK_Shift_R: 0xffe2, /* Right shift */ + XK_Control_L: 0xffe3, /* Left control */ + XK_Control_R: 0xffe4, /* Right control */ + XK_Caps_Lock: 0xffe5, /* Caps lock */ + XK_Shift_Lock: 0xffe6, /* Shift lock */ + + XK_Meta_L: 0xffe7, /* Left meta */ + XK_Meta_R: 0xffe8, /* Right meta */ + XK_Alt_L: 0xffe9, /* Left alt */ + XK_Alt_R: 0xffea, /* Right alt */ + XK_Super_L: 0xffeb, /* Left super */ + 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) + * Byte 3: 0 + */ + + XK_space: 0x0020, /* U+0020 SPACE */ + XK_exclam: 0x0021, /* U+0021 EXCLAMATION MARK */ + XK_quotedbl: 0x0022, /* U+0022 QUOTATION MARK */ + XK_numbersign: 0x0023, /* U+0023 NUMBER SIGN */ + XK_dollar: 0x0024, /* U+0024 DOLLAR SIGN */ + XK_percent: 0x0025, /* U+0025 PERCENT SIGN */ + XK_ampersand: 0x0026, /* U+0026 AMPERSAND */ + XK_apostrophe: 0x0027, /* U+0027 APOSTROPHE */ + XK_quoteright: 0x0027, /* deprecated */ + XK_parenleft: 0x0028, /* U+0028 LEFT PARENTHESIS */ + XK_parenright: 0x0029, /* U+0029 RIGHT PARENTHESIS */ + XK_asterisk: 0x002a, /* U+002A ASTERISK */ + XK_plus: 0x002b, /* U+002B PLUS SIGN */ + XK_comma: 0x002c, /* U+002C COMMA */ + XK_minus: 0x002d, /* U+002D HYPHEN-MINUS */ + XK_period: 0x002e, /* U+002E FULL STOP */ + XK_slash: 0x002f, /* U+002F SOLIDUS */ + XK_0: 0x0030, /* U+0030 DIGIT ZERO */ + XK_1: 0x0031, /* U+0031 DIGIT ONE */ + XK_2: 0x0032, /* U+0032 DIGIT TWO */ + XK_3: 0x0033, /* U+0033 DIGIT THREE */ + XK_4: 0x0034, /* U+0034 DIGIT FOUR */ + XK_5: 0x0035, /* U+0035 DIGIT FIVE */ + XK_6: 0x0036, /* U+0036 DIGIT SIX */ + XK_7: 0x0037, /* U+0037 DIGIT SEVEN */ + XK_8: 0x0038, /* U+0038 DIGIT EIGHT */ + XK_9: 0x0039, /* U+0039 DIGIT NINE */ + XK_colon: 0x003a, /* U+003A COLON */ + XK_semicolon: 0x003b, /* U+003B SEMICOLON */ + XK_less: 0x003c, /* U+003C LESS-THAN SIGN */ + XK_equal: 0x003d, /* U+003D EQUALS SIGN */ + XK_greater: 0x003e, /* U+003E GREATER-THAN SIGN */ + XK_question: 0x003f, /* U+003F QUESTION MARK */ + XK_at: 0x0040, /* U+0040 COMMERCIAL AT */ + XK_A: 0x0041, /* U+0041 LATIN CAPITAL LETTER A */ + XK_B: 0x0042, /* U+0042 LATIN CAPITAL LETTER B */ + XK_C: 0x0043, /* U+0043 LATIN CAPITAL LETTER C */ + XK_D: 0x0044, /* U+0044 LATIN CAPITAL LETTER D */ + XK_E: 0x0045, /* U+0045 LATIN CAPITAL LETTER E */ + XK_F: 0x0046, /* U+0046 LATIN CAPITAL LETTER F */ + XK_G: 0x0047, /* U+0047 LATIN CAPITAL LETTER G */ + XK_H: 0x0048, /* U+0048 LATIN CAPITAL LETTER H */ + XK_I: 0x0049, /* U+0049 LATIN CAPITAL LETTER I */ + XK_J: 0x004a, /* U+004A LATIN CAPITAL LETTER J */ + XK_K: 0x004b, /* U+004B LATIN CAPITAL LETTER K */ + XK_L: 0x004c, /* U+004C LATIN CAPITAL LETTER L */ + XK_M: 0x004d, /* U+004D LATIN CAPITAL LETTER M */ + XK_N: 0x004e, /* U+004E LATIN CAPITAL LETTER N */ + XK_O: 0x004f, /* U+004F LATIN CAPITAL LETTER O */ + XK_P: 0x0050, /* U+0050 LATIN CAPITAL LETTER P */ + XK_Q: 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */ + XK_R: 0x0052, /* U+0052 LATIN CAPITAL LETTER R */ + XK_S: 0x0053, /* U+0053 LATIN CAPITAL LETTER S */ + XK_T: 0x0054, /* U+0054 LATIN CAPITAL LETTER T */ + XK_U: 0x0055, /* U+0055 LATIN CAPITAL LETTER U */ + XK_V: 0x0056, /* U+0056 LATIN CAPITAL LETTER V */ + XK_W: 0x0057, /* U+0057 LATIN CAPITAL LETTER W */ + XK_X: 0x0058, /* U+0058 LATIN CAPITAL LETTER X */ + XK_Y: 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */ + XK_Z: 0x005a, /* U+005A LATIN CAPITAL LETTER Z */ + XK_bracketleft: 0x005b, /* U+005B LEFT SQUARE BRACKET */ + XK_backslash: 0x005c, /* U+005C REVERSE SOLIDUS */ + XK_bracketright: 0x005d, /* U+005D RIGHT SQUARE BRACKET */ + XK_asciicircum: 0x005e, /* U+005E CIRCUMFLEX ACCENT */ + XK_underscore: 0x005f, /* U+005F LOW LINE */ + XK_grave: 0x0060, /* U+0060 GRAVE ACCENT */ + XK_quoteleft: 0x0060, /* deprecated */ + XK_a: 0x0061, /* U+0061 LATIN SMALL LETTER A */ + XK_b: 0x0062, /* U+0062 LATIN SMALL LETTER B */ + XK_c: 0x0063, /* U+0063 LATIN SMALL LETTER C */ + XK_d: 0x0064, /* U+0064 LATIN SMALL LETTER D */ + XK_e: 0x0065, /* U+0065 LATIN SMALL LETTER E */ + XK_f: 0x0066, /* U+0066 LATIN SMALL LETTER F */ + XK_g: 0x0067, /* U+0067 LATIN SMALL LETTER G */ + XK_h: 0x0068, /* U+0068 LATIN SMALL LETTER H */ + XK_i: 0x0069, /* U+0069 LATIN SMALL LETTER I */ + XK_j: 0x006a, /* U+006A LATIN SMALL LETTER J */ + XK_k: 0x006b, /* U+006B LATIN SMALL LETTER K */ + XK_l: 0x006c, /* U+006C LATIN SMALL LETTER L */ + XK_m: 0x006d, /* U+006D LATIN SMALL LETTER M */ + XK_n: 0x006e, /* U+006E LATIN SMALL LETTER N */ + XK_o: 0x006f, /* U+006F LATIN SMALL LETTER O */ + XK_p: 0x0070, /* U+0070 LATIN SMALL LETTER P */ + XK_q: 0x0071, /* U+0071 LATIN SMALL LETTER Q */ + XK_r: 0x0072, /* U+0072 LATIN SMALL LETTER R */ + XK_s: 0x0073, /* U+0073 LATIN SMALL LETTER S */ + XK_t: 0x0074, /* U+0074 LATIN SMALL LETTER T */ + XK_u: 0x0075, /* U+0075 LATIN SMALL LETTER U */ + XK_v: 0x0076, /* U+0076 LATIN SMALL LETTER V */ + XK_w: 0x0077, /* U+0077 LATIN SMALL LETTER W */ + XK_x: 0x0078, /* U+0078 LATIN SMALL LETTER X */ + XK_y: 0x0079, /* U+0079 LATIN SMALL LETTER Y */ + XK_z: 0x007a, /* U+007A LATIN SMALL LETTER Z */ + XK_braceleft: 0x007b, /* U+007B LEFT CURLY BRACKET */ + XK_bar: 0x007c, /* U+007C VERTICAL LINE */ + XK_braceright: 0x007d, /* U+007D RIGHT CURLY BRACKET */ + XK_asciitilde: 0x007e, /* U+007E TILDE */ + + XK_nobreakspace: 0x00a0, /* U+00A0 NO-BREAK SPACE */ + XK_exclamdown: 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */ + XK_cent: 0x00a2, /* U+00A2 CENT SIGN */ + XK_sterling: 0x00a3, /* U+00A3 POUND SIGN */ + XK_currency: 0x00a4, /* U+00A4 CURRENCY SIGN */ + XK_yen: 0x00a5, /* U+00A5 YEN SIGN */ + XK_brokenbar: 0x00a6, /* U+00A6 BROKEN BAR */ + XK_section: 0x00a7, /* U+00A7 SECTION SIGN */ + XK_diaeresis: 0x00a8, /* U+00A8 DIAERESIS */ + XK_copyright: 0x00a9, /* U+00A9 COPYRIGHT SIGN */ + XK_ordfeminine: 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */ + XK_guillemotleft: 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ + XK_notsign: 0x00ac, /* U+00AC NOT SIGN */ + XK_hyphen: 0x00ad, /* U+00AD SOFT HYPHEN */ + XK_registered: 0x00ae, /* U+00AE REGISTERED SIGN */ + XK_macron: 0x00af, /* U+00AF MACRON */ + XK_degree: 0x00b0, /* U+00B0 DEGREE SIGN */ + XK_plusminus: 0x00b1, /* U+00B1 PLUS-MINUS SIGN */ + XK_twosuperior: 0x00b2, /* U+00B2 SUPERSCRIPT TWO */ + XK_threesuperior: 0x00b3, /* U+00B3 SUPERSCRIPT THREE */ + XK_acute: 0x00b4, /* U+00B4 ACUTE ACCENT */ + XK_mu: 0x00b5, /* U+00B5 MICRO SIGN */ + XK_paragraph: 0x00b6, /* U+00B6 PILCROW SIGN */ + XK_periodcentered: 0x00b7, /* U+00B7 MIDDLE DOT */ + XK_cedilla: 0x00b8, /* U+00B8 CEDILLA */ + XK_onesuperior: 0x00b9, /* U+00B9 SUPERSCRIPT ONE */ + XK_masculine: 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */ + XK_guillemotright: 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ + XK_onequarter: 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */ + XK_onehalf: 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */ + XK_threequarters: 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */ + XK_questiondown: 0x00bf, /* U+00BF INVERTED QUESTION MARK */ + XK_Agrave: 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ + XK_Aacute: 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ + XK_Acircumflex: 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ + XK_Atilde: 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ + XK_Adiaeresis: 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ + XK_Aring: 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ + XK_AE: 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */ + XK_Ccedilla: 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ + XK_Egrave: 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ + XK_Eacute: 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ + XK_Ecircumflex: 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ + XK_Ediaeresis: 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ + XK_Igrave: 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ + XK_Iacute: 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ + XK_Icircumflex: 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ + XK_Idiaeresis: 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ + XK_ETH: 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */ + XK_Eth: 0x00d0, /* deprecated */ + XK_Ntilde: 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ + XK_Ograve: 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ + XK_Oacute: 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ + XK_Ocircumflex: 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ + XK_Otilde: 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ + XK_Odiaeresis: 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ + XK_multiply: 0x00d7, /* U+00D7 MULTIPLICATION SIGN */ + XK_Oslash: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ + XK_Ooblique: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ + XK_Ugrave: 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ + XK_Uacute: 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ + XK_Ucircumflex: 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ + XK_Udiaeresis: 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ + XK_Yacute: 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ + XK_THORN: 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */ + XK_Thorn: 0x00de, /* deprecated */ + XK_ssharp: 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */ + XK_agrave: 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ + XK_aacute: 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ + XK_acircumflex: 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ + XK_atilde: 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ + XK_adiaeresis: 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ + XK_aring: 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ + XK_ae: 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */ + XK_ccedilla: 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ + XK_egrave: 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ + XK_eacute: 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ + XK_ecircumflex: 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ + XK_ediaeresis: 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ + XK_igrave: 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ + XK_iacute: 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ + XK_icircumflex: 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ + XK_idiaeresis: 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ + XK_eth: 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */ + XK_ntilde: 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ + XK_ograve: 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ + XK_oacute: 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ + XK_ocircumflex: 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ + XK_otilde: 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ + XK_odiaeresis: 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ + XK_division: 0x00f7, /* U+00F7 DIVISION SIGN */ + XK_oslash: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ + XK_ooblique: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ + XK_ugrave: 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ + XK_uacute: 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ + XK_ucircumflex: 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ + XK_udiaeresis: 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ + XK_yacute: 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ + XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */ + XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ +}; + +/* [module] export default KeyTable; */ diff --git a/include/keysymdef.js b/core/input/keysymdef.js similarity index 99% rename from include/keysymdef.js rename to core/input/keysymdef.js index f94445cf..f45d9d90 100644 --- a/include/keysymdef.js +++ b/core/input/keysymdef.js @@ -2,6 +2,7 @@ // (and optionally, key names) expected by the RFB protocol // How this file was generated: // node /Users/jalf/dev/mi/novnc/utils/parse.js /opt/X11/include/X11/keysymdef.h + var keysyms = (function(){ "use strict"; var keynames = null; @@ -13,3 +14,5 @@ var keysyms = (function(){ lookup : lookup }; })(); + +/* [module] export default keysyms */ diff --git a/include/keyboard.js b/core/input/util.js similarity index 81% rename from include/keyboard.js rename to core/input/util.js index 26543dbf..efdccedc 100644 --- a/include/keyboard.js +++ b/core/input/util.js @@ -1,4 +1,11 @@ -var kbdUtil = (function() { +/* [module] + * import KeyTable from "./keysym"; + * import keysyms from "./keysymdef"; + */ + +var KeyboardUtil = {}; + +(function() { "use strict"; function substituteCodepoint(cp) { @@ -31,7 +38,7 @@ var kbdUtil = (function() { function hasShortcutModifier(charModifier, currentModifiers) { var mods = {}; for (var key in currentModifiers) { - if (parseInt(key) !== XK_Shift_L) { + if (parseInt(key) !== KeyTable.XK_Shift_L) { mods[key] = currentModifiers[key]; } } @@ -68,15 +75,15 @@ var kbdUtil = (function() { if (!charModifier) { if (isMac()) { // on Mac, Option (AKA Alt) is used as a char modifier - charModifier = [XK_Alt_L]; + charModifier = [KeyTable.XK_Alt_L]; } else if (isWindows()) { // on Windows, Ctrl+Alt is used as a char modifier - charModifier = [XK_Alt_L, XK_Control_L]; + charModifier = [KeyTable.XK_Alt_L, KeyTable.XK_Control_L]; } else if (isLinux()) { // on Linux, ISO Level 3 Shift (AltGr) is used as a char modifier - charModifier = [XK_ISO_Level3_Shift]; + charModifier = [KeyTable.XK_ISO_Level3_Shift]; } else { charModifier = []; @@ -84,11 +91,11 @@ var kbdUtil = (function() { } var state = {}; - 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; + state[KeyTable.XK_Control_L] = false; + state[KeyTable.XK_Alt_L] = false; + state[KeyTable.XK_ISO_Level3_Shift] = false; + state[KeyTable.XK_Shift_L] = false; + state[KeyTable.XK_Meta_L] = false; function sync(evt, keysym) { var result = []; @@ -97,29 +104,29 @@ var kbdUtil = (function() { } 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)); + evt.ctrlKey !== state[KeyTable.XK_Control_L] && keysym !== KeyTable.XK_Control_L) { + state[KeyTable.XK_Control_L] = evt.ctrlKey; + result.push(syncKey(KeyTable.XK_Control_L)); } 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)); + evt.altKey !== state[KeyTable.XK_Alt_L] && keysym !== KeyTable.XK_Alt_L) { + state[KeyTable.XK_Alt_L] = evt.altKey; + result.push(syncKey(KeyTable.XK_Alt_L)); } 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)); + evt.altGraphKey !== state[KeyTable.XK_ISO_Level3_Shift] && keysym !== KeyTable.XK_ISO_Level3_Shift) { + state[KeyTable.XK_ISO_Level3_Shift] = evt.altGraphKey; + result.push(syncKey(KeyTable.XK_ISO_Level3_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)); + evt.shiftKey !== state[KeyTable.XK_Shift_L] && keysym !== KeyTable.XK_Shift_L) { + state[KeyTable.XK_Shift_L] = evt.shiftKey; + result.push(syncKey(KeyTable.XK_Shift_L)); } 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)); + evt.metaKey !== state[KeyTable.XK_Meta_L] && keysym !== KeyTable.XK_Meta_L) { + state[KeyTable.XK_Meta_L] = evt.metaKey; + result.push(syncKey(KeyTable.XK_Meta_L)); } return result; } @@ -210,21 +217,21 @@ var kbdUtil = (function() { return shiftPressed ? keycode : keycode + 32; // A-Z } if (keycode >= 0x60 && keycode <= 0x69) { - return XK_KP_0 + (keycode - 0x60); // numpad 0-9 + return KeyTable.XK_KP_0 + (keycode - 0x60); // numpad 0-9 } switch(keycode) { - 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; + case 0x20: return KeyTable.XK_space; + case 0x6a: return KeyTable.XK_KP_Multiply; + case 0x6b: return KeyTable.XK_KP_Add; + case 0x6c: return KeyTable.XK_KP_Separator; + case 0x6d: return KeyTable.XK_KP_Subtract; + case 0x6e: return KeyTable.XK_KP_Decimal; + case 0x6f: return KeyTable.XK_KP_Divide; + case 0xbb: return KeyTable.XK_plus; + case 0xbc: return KeyTable.XK_comma; + case 0xbd: return KeyTable.XK_minus; + case 0xbe: return KeyTable.XK_period; } return nonCharacterKey({keyCode: keycode}); @@ -238,54 +245,53 @@ var kbdUtil = (function() { var keycode = evt.keyCode; if (keycode >= 0x70 && keycode <= 0x87) { - return XK_F1 + keycode - 0x70; // F1-F24 + return KeyTable.XK_F1 + keycode - 0x70; // F1-F24 } switch (keycode) { - case 8 : return XK_BackSpace; - case 13 : return XK_Return; + case 8 : return KeyTable.XK_BackSpace; + case 13 : return KeyTable.XK_Return; - case 9 : return XK_Tab; + case 9 : return KeyTable.XK_Tab; - case 27 : return XK_Escape; - case 46 : return XK_Delete; + case 27 : return KeyTable.XK_Escape; + case 46 : return KeyTable.XK_Delete; - 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 36 : return KeyTable.XK_Home; + case 35 : return KeyTable.XK_End; + case 33 : return KeyTable.XK_Page_Up; + case 34 : return KeyTable.XK_Page_Down; + case 45 : return KeyTable.XK_Insert; - case 37 : return XK_Left; - case 38 : return XK_Up; - case 39 : return XK_Right; - case 40 : return XK_Down; + case 37 : return KeyTable.XK_Left; + case 38 : return KeyTable.XK_Up; + case 39 : return KeyTable.XK_Right; + case 40 : return KeyTable.XK_Down; - case 16 : return XK_Shift_L; - case 17 : return XK_Control_L; - case 18 : return XK_Alt_L; // also: Option-key on Mac + case 16 : return KeyTable.XK_Shift_L; + case 17 : return KeyTable.XK_Control_L; + case 18 : return KeyTable.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 + case 224 : return KeyTable.XK_Meta_L; + case 225 : return KeyTable.XK_ISO_Level3_Shift; // AltGr + case 91 : return KeyTable.XK_Super_L; // also: Windows-key + case 92 : return KeyTable.XK_Super_R; // also: Windows-key + case 93 : return KeyTable.XK_Menu; // also: Windows-Menu, Command on Mac default: return null; } } - return { - hasShortcutModifier : hasShortcutModifier, - hasCharModifier : hasCharModifier, - ModifierSync : ModifierSync, - getKey : getKey, - getKeysym : getKeysym, - keysymFromKeyCode : keysymFromKeyCode, - nonCharacterKey : nonCharacterKey, - substituteCodepoint : substituteCodepoint - }; + + KeyboardUtil.hasShortcutModifier = hasShortcutModifier; + KeyboardUtil.hasCharModifier = hasCharModifier; + KeyboardUtil.ModifierSync = ModifierSync; + KeyboardUtil.getKey = getKey; + KeyboardUtil.getKeysym = getKeysym; + KeyboardUtil.keysymFromKeyCode = keysymFromKeyCode; + KeyboardUtil.nonCharacterKey = nonCharacterKey; + KeyboardUtil.substituteCodepoint = substituteCodepoint; })(); -function QEMUKeyEventDecoder(modifierState, next) { +KeyboardUtil.QEMUKeyEventDecoder = function(modifierState, next) { "use strict"; function sendAll(evts) { @@ -331,7 +337,7 @@ function QEMUKeyEventDecoder(modifierState, next) { var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); var isShift = evt.keyCode === 0x10 || evt.key === 'Shift'; - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!kbdUtil.nonCharacterKey(evt)); + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); next(result); return suppress; @@ -353,9 +359,9 @@ function QEMUKeyEventDecoder(modifierState, next) { }, releaseAll: function() { next({type: 'releaseall'}); } }; -} +}; -function TrackQEMUKeyState(next) { +KeyboardUtil.TrackQEMUKeyState = function(next) { "use strict"; var state = []; @@ -414,7 +420,7 @@ function TrackQEMUKeyState(next) { state = []; } }; -} +}; // Takes a DOM keyboard event and: // - determines which keysym it represents @@ -423,7 +429,7 @@ function TrackQEMUKeyState(next) { // - marks each event with an 'escape' property if a modifier was down which should be "escaped" // - generates a "stall" event in cases where it might be necessary to wait and see if a keypress event follows a keydown // This information is collected into an object which is passed to the next() function. (one call per event) -function KeyEventDecoder(modifierState, next) { +KeyboardUtil.KeyEventDecoder = function(modifierState, next) { "use strict"; function sendAll(evts) { for (var i = 0; i < evts.length; ++i) { @@ -432,18 +438,18 @@ function KeyEventDecoder(modifierState, next) { } function process(evt, type) { var result = {type: type}; - var keyId = kbdUtil.getKey(evt); + var keyId = KeyboardUtil.getKey(evt); if (keyId) { result.keyId = keyId; } - var keysym = kbdUtil.getKeysym(evt); + var keysym = KeyboardUtil.getKeysym(evt); var hasModifier = modifierState.hasShortcutModifier() || !!modifierState.activeCharModifier(); // Is this a case where we have to decide on the keysym right away, rather than waiting for the keypress? // "special" keys like enter, tab or backspace don't send keypress events, // and some browsers don't send keypresses at all if a modifier is down - if (keysym && (type !== 'keydown' || kbdUtil.nonCharacterKey(evt) || hasModifier)) { + if (keysym && (type !== 'keydown' || KeyboardUtil.nonCharacterKey(evt) || hasModifier)) { result.keysym = keysym; } @@ -452,11 +458,11 @@ function KeyEventDecoder(modifierState, next) { // Should we prevent the browser from handling the event? // Doing so on a keydown (in most browsers) prevents keypress from being generated // so only do that if we have to. - var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!kbdUtil.nonCharacterKey(evt)); + var suppress = !isShift && (type !== 'keydown' || modifierState.hasShortcutModifier() || !!KeyboardUtil.nonCharacterKey(evt)); // If a char modifier is down on a keydown, we need to insert a stall, // so VerifyCharModifier knows to wait and see if a keypress is comnig - var stall = type === 'keydown' && modifierState.activeCharModifier() && !kbdUtil.nonCharacterKey(evt); + var stall = type === 'keydown' && modifierState.activeCharModifier() && !KeyboardUtil.nonCharacterKey(evt); // if a char modifier is pressed, get the keys it consists of (on Windows, AltGr is equivalent to Ctrl+Alt) var active = modifierState.activeCharModifier(); @@ -502,7 +508,7 @@ function KeyEventDecoder(modifierState, next) { }, releaseAll: function() { next({type: 'releaseall'}); } }; -} +}; // Combines keydown and keypress events where necessary to handle char modifiers. // On some OS'es, a char modifier is sometimes used as a shortcut modifier. @@ -510,7 +516,7 @@ function KeyEventDecoder(modifierState, next) { // so when used with the '2' key, Ctrl-Alt counts as a char modifier (and should be escaped), but when used with 'D', it does not. // The only way we can distinguish these cases is to wait and see if a keypress event arrives // When we receive a "stall" event, wait a few ms before processing the next keydown. If a keypress has also arrived, merge the two -function VerifyCharModifier(next) { +KeyboardUtil.VerifyCharModifier = function(next) { "use strict"; var queue = []; var timer = null; @@ -560,14 +566,14 @@ function VerifyCharModifier(next) { queue.push(evt); process(); }; -} +}; // Keeps track of which keys we (and the server) believe are down // When a keyup is received, match it against this list, to determine the corresponding keysym(s) // in some cases, a single key may produce multiple keysyms, so the corresponding keyup event must release all of these chars // key repeat events should be merged into a single entry. // Because we can't always identify which entry a keydown or keyup event corresponds to, we sometimes have to guess -function TrackKeyState(next) { +KeyboardUtil.TrackKeyState = function(next) { "use strict"; var state = []; @@ -647,11 +653,11 @@ function TrackKeyState(next) { state = []; } }; -} +}; // Handles "escaping" of modifiers: if a char modifier is used to produce a keysym (such as AltGr-2 to generate an @), // then the modifier must be "undone" before sending the @, and "redone" afterwards. -function EscapeModifiers(next) { +KeyboardUtil.EscapeModifiers = function(next) { "use strict"; return function(evt) { if (evt.type !== 'keydown' || evt.escape === undefined) { @@ -671,4 +677,6 @@ function EscapeModifiers(next) { } /* jshint shadow: false */ }; -} +}; + +/* [module] export default KeyboardUtil; */ diff --git a/core/input/xtscancodes.js b/core/input/xtscancodes.js new file mode 100644 index 00000000..89d824cc --- /dev/null +++ b/core/input/xtscancodes.js @@ -0,0 +1,149 @@ +var XtScancode = { + "Escape": 0x0001, + "Digit1": 0x0002, + "Digit2": 0x0003, + "Digit3": 0x0004, + "Digit4": 0x0005, + "Digit5": 0x0006, + "Digit6": 0x0007, + "Digit7": 0x0008, + "Digit8": 0x0009, + "Digit9": 0x000A, + "Digit0": 0x000B, + "Minus": 0x000C, + "Equal": 0x000D, + "Backspace": 0x000E, + "Tab": 0x000F, + "KeyQ": 0x0010, + "KeyW": 0x0011, + "KeyE": 0x0012, + "KeyR": 0x0013, + "KeyT": 0x0014, + "KeyY": 0x0015, + "KeyU": 0x0016, + "KeyI": 0x0017, + "KeyO": 0x0018, + "KeyP": 0x0019, + "BracketLeft": 0x001A, + "BracketRight": 0x001B, + "Enter": 0x001C, + "ControlLeft": 0x001D, + "KeyA": 0x001E, + "KeyS": 0x001F, + "KeyD": 0x0020, + "KeyF": 0x0021, + "KeyG": 0x0022, + "KeyH": 0x0023, + "KeyJ": 0x0024, + "KeyK": 0x0025, + "KeyL": 0x0026, + "Semicolon": 0x0027, + "Quote": 0x0028, + "Backquote": 0x0029, + "ShiftLeft": 0x002A, + "Backslash": 0x002B, + "KeyZ": 0x002C, + "KeyX": 0x002D, + "KeyC": 0x002E, + "KeyV": 0x002F, + "KeyB": 0x0030, + "KeyN": 0x0031, + "KeyM": 0x0032, + "Comma": 0x0033, + "Period": 0x0034, + "Slash": 0x0035, + "ShiftRight": 0x0036, + "NumpadMultiply": 0x0037, + "AltLeft": 0x0038, + "Space": 0x0039, + "CapsLock": 0x003A, + "F1": 0x003B, + "F2": 0x003C, + "F3": 0x003D, + "F4": 0x003E, + "F5": 0x003F, + "F6": 0x0040, + "F7": 0x0041, + "F8": 0x0042, + "F9": 0x0043, + "F10": 0x0044, + "Pause": 0xE045, + "ScrollLock": 0x0046, + "Numpad7": 0x0047, + "Numpad8": 0x0048, + "Numpad9": 0x0049, + "NumpadSubtract": 0x004A, + "Numpad4": 0x004B, + "Numpad5": 0x004C, + "Numpad6": 0x004D, + "NumpadAdd": 0x004E, + "Numpad1": 0x004F, + "Numpad2": 0x0050, + "Numpad3": 0x0051, + "Numpad0": 0x0052, + "NumpadDecimal": 0x0053, + "IntlBackslash": 0x0056, + "F11": 0x0057, + "F12": 0x0058, + "IntlYen": 0x007D, + "MediaTrackPrevious": 0xE010, + "MediaTrackNext": 0xE019, + "NumpadEnter": 0xE01C, + "ControlRight": 0xE01D, + "VolumeMute": 0xE020, + "MediaPlayPause": 0xE022, + "MediaStop": 0xE024, + "VolumeDown": 0xE02E, + "VolumeUp": 0xE030, + "BrowserHome": 0xE032, + "NumpadDivide": 0xE035, + "PrintScreen": 0xE037, + "AltRight": 0xE038, + "NumLock": 0x0045, + "Home": 0xE047, + "ArrowUp": 0xE048, + "PageUp": 0xE049, + "ArrowLeft": 0xE04B, + "ArrowRight": 0xE04D, + "End": 0xE04F, + "ArrowDown": 0xE050, + "PageDown": 0xE051, + "Insert": 0xE052, + "Delete": 0xE053, + "OSLeft": 0xE05B, + "OSRight": 0xE05C, + "ContextMenu": 0xE05D, + "BrowserSearch": 0xE065, + "BrowserFavorites": 0xE066, + "BrowserRefresh": 0xE067, + "BrowserStop": 0xE068, + "BrowserForward": 0xE069, + "BrowserBack": 0xE06A, + "NumpadComma": 0x007E, + "NumpadEqual": 0x0059, + "F13": 0x0064, + "F14": 0x0065, + "F15": 0x0066, + "F16": 0x0067, + "F17": 0x0068, + "F18": 0x0069, + "F19": 0x006A, + "F20": 0x006B, + "F21": 0x006C, + "F22": 0x006D, + "F23": 0x006E, + "F24": 0x0076, + "KanaMode": 0x0070, + "Lang2": 0x0071, + "Lang1": 0x0072, + "IntlRo": 0x0073, + "Convert": 0x0079, + "NonConvert": 0x007B, + "LaunchApp2": 0xE021, + "Power": 0xE05E, + "LaunchApp1": 0xE06B, + "LaunchMail": 0xE06C, + "MediaSelect": 0xE06D, +}; + +/* [module] export default XtScancode */ diff --git a/include/rfb.js b/core/rfb.js similarity index 89% rename from include/rfb.js rename to core/rfb.js index ec2fd84c..135d3a75 100644 --- a/include/rfb.js +++ b/core/rfb.js @@ -10,236 +10,240 @@ * (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca) */ +/* [module] + * import Util from "./util"; + * import Display from "./display"; + * import { Keyboard, Mouse } from "./input/devices" + * import Websock from "./websock" + * import Base64 from "./base64"; + * import DES from "./des"; + * import KeyTable from "./input/keysym"; + * import XtScancode from "./input/xtscancodes"; + * import Inflator from "./inflator.mod"; + */ /*jslint white: false, browser: true */ -/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES */ +/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, KeyTable, Inflator, XtScancode */ -var RFB; - -(function () { +/* [module] export default */ function RFB(defaults) { "use strict"; - RFB = function (defaults) { - if (!defaults) { - defaults = {}; - } + if (!defaults) { + defaults = {}; + } - this._rfb_host = ''; - this._rfb_port = 5900; - this._rfb_password = ''; - this._rfb_path = ''; + this._rfb_host = ''; + this._rfb_port = 5900; + this._rfb_password = ''; + this._rfb_path = ''; - this._rfb_state = 'disconnected'; - this._rfb_version = 0; - this._rfb_max_version = 3.8; - this._rfb_auth_scheme = ''; + this._rfb_state = 'disconnected'; + this._rfb_version = 0; + this._rfb_max_version = 3.8; + this._rfb_auth_scheme = ''; - this._rfb_tightvnc = false; - this._rfb_xvp_ver = 0; + this._rfb_tightvnc = false; + this._rfb_xvp_ver = 0; - // In preference order - this._encodings = [ - ['COPYRECT', 0x01 ], - ['TIGHT', 0x07 ], - ['TIGHT_PNG', -260 ], - ['HEXTILE', 0x05 ], - ['RRE', 0x02 ], - ['RAW', 0x00 ], + // In preference order + this._encodings = [ + ['COPYRECT', 0x01 ], + ['TIGHT', 0x07 ], + ['TIGHT_PNG', -260 ], + ['HEXTILE', 0x05 ], + ['RRE', 0x02 ], + ['RAW', 0x00 ], - // Psuedo-encoding settings + // Psuedo-encoding settings - //['JPEG_quality_lo', -32 ], - ['JPEG_quality_med', -26 ], - //['JPEG_quality_hi', -23 ], - //['compress_lo', -255 ], - ['compress_hi', -247 ], + //['JPEG_quality_lo', -32 ], + ['JPEG_quality_med', -26 ], + //['JPEG_quality_hi', -23 ], + //['compress_lo', -255 ], + ['compress_hi', -247 ], - ['DesktopSize', -223 ], - ['last_rect', -224 ], - ['Cursor', -239 ], - ['QEMUExtendedKeyEvent', -258 ], - ['ExtendedDesktopSize', -308 ], - ['xvp', -309 ], - ['Fence', -312 ], - ['ContinuousUpdates', -313 ] - ]; + ['DesktopSize', -223 ], + ['last_rect', -224 ], + ['Cursor', -239 ], + ['QEMUExtendedKeyEvent', -258 ], + ['ExtendedDesktopSize', -308 ], + ['xvp', -309 ], + ['Fence', -312 ], + ['ContinuousUpdates', -313 ] + ]; - this._encHandlers = {}; - this._encNames = {}; - this._encStats = {}; + this._encHandlers = {}; + this._encNames = {}; + this._encStats = {}; - this._sock = null; // Websock object - this._display = null; // Display object - this._keyboard = null; // Keyboard input handler object - this._mouse = null; // Mouse input handler object - this._disconnTimer = null; // disconnection timer - this._msgTimer = null; // queued handle_msg timer + this._sock = null; // Websock object + this._display = null; // Display object + this._keyboard = null; // Keyboard input handler object + this._mouse = null; // Mouse input handler object + this._disconnTimer = null; // disconnection timer + this._msgTimer = null; // queued handle_msg timer - this._supportsFence = false; + this._supportsFence = false; - this._supportsContinuousUpdates = false; - this._enabledContinuousUpdates = false; + this._supportsContinuousUpdates = false; + this._enabledContinuousUpdates = false; - // Frame buffer update state - this._FBU = { - rects: 0, - subrects: 0, // RRE - lines: 0, // RAW - tiles: 0, // HEXTILE - bytes: 0, - x: 0, - y: 0, - width: 0, - height: 0, - encoding: 0, - subencoding: -1, - background: null, - zlib: [] // TIGHT zlib streams - }; - - this._fb_Bpp = 4; - this._fb_depth = 3; - this._fb_width = 0; - this._fb_height = 0; - this._fb_name = ""; - - this._destBuff = null; - this._paletteBuff = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel) - - this._rre_chunk_sz = 100; - - this._timing = { - last_fbu: 0, - fbu_total: 0, - fbu_total_cnt: 0, - full_fbu_total: 0, - full_fbu_cnt: 0, - - fbu_rt_start: 0, - fbu_rt_total: 0, - fbu_rt_cnt: 0, - pixels: 0 - }; - - this._supportsSetDesktopSize = false; - this._screen_id = 0; - this._screen_flags = 0; - - // Mouse state - this._mouse_buttonMask = 0; - this._mouse_arr = []; - this._viewportDragging = false; - this._viewportDragPos = {}; - this._viewportHasMoved = false; - - // QEMU Extended Key Event support - default to false - this._qemuExtKeyEventSupported = false; - - // set the default value on user-facing properties - Util.set_defaults(this, defaults, { - '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 - 'xvp_password_sep': '@', // Separator for XVP password fields - 'disconnectTimeout': 3, // Time (s) to wait for disconnection - 'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection - 'repeaterID': '', // [UltraVNC] RepeaterID to connect to - 'viewportDrag': false, // Move the viewport on mouse drags - - // Callback functions - 'onUpdateState': function () { }, // onUpdateState(rfb, state, oldstate, statusMsg): state update/change - 'onPasswordRequired': function () { }, // onPasswordRequired(rfb): VNC password is required - 'onClipboard': function () { }, // onClipboard(rfb, text): RFB clipboard contents received - 'onBell': function () { }, // onBell(rfb): RFB Bell message received - 'onFBUReceive': function () { }, // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed - 'onFBUComplete': function () { }, // onFBUComplete(rfb, fbu): RFB FBU received and processed - 'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized - 'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received - 'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection - }); - - // main setup - Util.Debug(">> RFB.constructor"); - - // populate encHandlers with bound versions - Object.keys(RFB.encodingHandlers).forEach(function (encName) { - this._encHandlers[encName] = RFB.encodingHandlers[encName].bind(this); - }.bind(this)); - - // Create lookup tables based on encoding number - for (var i = 0; i < this._encodings.length; i++) { - this._encHandlers[this._encodings[i][1]] = this._encHandlers[this._encodings[i][0]]; - this._encNames[this._encodings[i][1]] = this._encodings[i][0]; - this._encStats[this._encodings[i][1]] = [0, 0]; - } - - // NB: nothing that needs explicit teardown should be done - // before this point, since this can throw an exception - try { - this._display = new Display({target: this._target}); - } catch (exc) { - Util.Error("Display exception: " + exc); - throw exc; - } - - this._keyboard = new Keyboard({target: this._focusContainer, - onKeyPress: this._handleKeyPress.bind(this)}); - - this._mouse = new Mouse({target: this._target, - onMouseButton: this._handleMouseButton.bind(this), - onMouseMove: this._handleMouseMove.bind(this), - notify: this._keyboard.sync.bind(this._keyboard)}); - - this._sock = new Websock(); - this._sock.on('message', this._handle_message.bind(this)); - this._sock.on('open', function () { - if (this._rfb_state === 'connect') { - this._updateState('ProtocolVersion', "Starting VNC handshake"); - } else { - this._fail("Got unexpected WebSocket connection"); - } - }.bind(this)); - this._sock.on('close', function (e) { - Util.Warn("WebSocket on-close event"); - var msg = ""; - if (e.code) { - msg = " (code: " + e.code; - if (e.reason) { - msg += ", reason: " + e.reason; - } - msg += ")"; - } - if (this._rfb_state === 'disconnect') { - this._updateState('disconnected', 'VNC disconnected' + msg); - } else if (this._rfb_state === 'ProtocolVersion') { - this._fail('Failed to connect to server' + msg); - } else if (this._rfb_state in {'failed': 1, 'disconnected': 1}) { - Util.Error("Received onclose while disconnected" + msg); - } else { - this._fail("Server disconnected" + msg); - } - this._sock.off('close'); - }.bind(this)); - this._sock.on('error', function (e) { - Util.Warn("WebSocket on-error event"); - }); - - this._init_vars(); - - var rmode = this._display.get_render_mode(); - if (Websock_native) { - Util.Info("Using native WebSockets"); - this._updateState('loaded', 'noVNC ready: native WebSockets, ' + rmode); - } else { - this._cleanupSocket('fatal'); - throw new Error("WebSocket support is required to use noVNC"); - } - - Util.Debug("<< RFB.constructor"); + // Frame buffer update state + this._FBU = { + rects: 0, + subrects: 0, // RRE + lines: 0, // RAW + tiles: 0, // HEXTILE + bytes: 0, + x: 0, + y: 0, + width: 0, + height: 0, + encoding: 0, + subencoding: -1, + background: null, + zlib: [] // TIGHT zlib streams }; + this._fb_Bpp = 4; + this._fb_depth = 3; + this._fb_width = 0; + this._fb_height = 0; + this._fb_name = ""; + + this._destBuff = null; + this._paletteBuff = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel) + + this._rre_chunk_sz = 100; + + this._timing = { + last_fbu: 0, + fbu_total: 0, + fbu_total_cnt: 0, + full_fbu_total: 0, + full_fbu_cnt: 0, + + fbu_rt_start: 0, + fbu_rt_total: 0, + fbu_rt_cnt: 0, + pixels: 0 + }; + + this._supportsSetDesktopSize = false; + this._screen_id = 0; + this._screen_flags = 0; + + // Mouse state + this._mouse_buttonMask = 0; + this._mouse_arr = []; + this._viewportDragging = false; + this._viewportDragPos = {}; + this._viewportHasMoved = false; + + // QEMU Extended Key Event support - default to false + this._qemuExtKeyEventSupported = false; + + // set the default value on user-facing properties + Util.set_defaults(this, defaults, { + '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 + 'xvp_password_sep': '@', // Separator for XVP password fields + 'disconnectTimeout': 3, // Time (s) to wait for disconnection + 'wsProtocols': ['binary'], // Protocols to use in the WebSocket connection + 'repeaterID': '', // [UltraVNC] RepeaterID to connect to + 'viewportDrag': false, // Move the viewport on mouse drags + + // Callback functions + 'onUpdateState': function () { }, // onUpdateState(rfb, state, oldstate, statusMsg): state update/change + 'onPasswordRequired': function () { }, // onPasswordRequired(rfb): VNC password is required + 'onClipboard': function () { }, // onClipboard(rfb, text): RFB clipboard contents received + 'onBell': function () { }, // onBell(rfb): RFB Bell message received + 'onFBUReceive': function () { }, // onFBUReceive(rfb, fbu): RFB FBU received but not yet processed + 'onFBUComplete': function () { }, // onFBUComplete(rfb, fbu): RFB FBU received and processed + 'onFBResize': function () { }, // onFBResize(rfb, width, height): frame buffer resized + 'onDesktopName': function () { }, // onDesktopName(rfb, name): desktop name received + 'onXvpInit': function () { } // onXvpInit(version): XVP extensions active for this connection + }); + + // main setup + Util.Debug(">> RFB.constructor"); + + // populate encHandlers with bound versions + Object.keys(RFB.encodingHandlers).forEach(function (encName) { + this._encHandlers[encName] = RFB.encodingHandlers[encName].bind(this); + }.bind(this)); + + // Create lookup tables based on encoding number + for (var i = 0; i < this._encodings.length; i++) { + this._encHandlers[this._encodings[i][1]] = this._encHandlers[this._encodings[i][0]]; + this._encNames[this._encodings[i][1]] = this._encodings[i][0]; + this._encStats[this._encodings[i][1]] = [0, 0]; + } + + // NB: nothing that needs explicit teardown should be done + // before this point, since this can throw an exception + try { + this._display = new Display({target: this._target}); + } catch (exc) { + Util.Error("Display exception: " + exc); + throw exc; + } + + this._keyboard = new Keyboard({target: this._focusContainer, + onKeyPress: this._handleKeyPress.bind(this)}); + + this._mouse = new Mouse({target: this._target, + onMouseButton: this._handleMouseButton.bind(this), + onMouseMove: this._handleMouseMove.bind(this), + notify: this._keyboard.sync.bind(this._keyboard)}); + + this._sock = new Websock(); + this._sock.on('message', this._handle_message.bind(this)); + this._sock.on('open', function () { + if (this._rfb_state === 'connect') { + this._updateState('ProtocolVersion', "Starting VNC handshake"); + } else { + this._fail("Got unexpected WebSocket connection"); + } + }.bind(this)); + this._sock.on('close', function (e) { + Util.Warn("WebSocket on-close event"); + var msg = ""; + if (e.code) { + msg = " (code: " + e.code; + if (e.reason) { + msg += ", reason: " + e.reason; + } + msg += ")"; + } + if (this._rfb_state === 'disconnect') { + this._updateState('disconnected', 'VNC disconnected' + msg); + } else if (this._rfb_state === 'ProtocolVersion') { + this._fail('Failed to connect to server' + msg); + } else if (this._rfb_state in {'failed': 1, 'disconnected': 1}) { + Util.Error("Received onclose while disconnected" + msg); + } else { + this._fail("Server disconnected" + msg); + } + this._sock.off('close'); + }.bind(this)); + this._sock.on('error', function (e) { + Util.Warn("WebSocket on-error event"); + }); + + this._init_vars(); + + var rmode = this._display.get_render_mode(); + Util.Info("Using native WebSockets"); + this._updateState('loaded', 'noVNC ready: native WebSockets, ' + rmode); + + Util.Debug("<< RFB.constructor"); +}; + +(function() { RFB.prototype = { // Public methods connect: function (host, port, password, path) { @@ -273,12 +277,12 @@ var RFB; if (this._rfb_state !== 'normal' || this._view_only) { return false; } Util.Info("Sending Ctrl-Alt-Del"); - RFB.messages.keyEvent(this._sock, XK_Control_L, 1); - RFB.messages.keyEvent(this._sock, XK_Alt_L, 1); - RFB.messages.keyEvent(this._sock, XK_Delete, 1); - RFB.messages.keyEvent(this._sock, XK_Delete, 0); - RFB.messages.keyEvent(this._sock, XK_Alt_L, 0); - RFB.messages.keyEvent(this._sock, XK_Control_L, 0); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 1); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Delete, 0); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_L, 0); + RFB.messages.keyEvent(this._sock, KeyTable.XK_Control_L, 0); return true; }, @@ -372,7 +376,7 @@ var RFB; } for (i = 0; i < 4; i++) { - this._FBU.zlibs[i] = new inflator.Inflate(); + this._FBU.zlibs[i] = new Inflator.Inflate(); } }, diff --git a/include/util.js b/core/util.js similarity index 53% rename from include/util.js rename to core/util.js index ed0e3cde..d6a01932 100644 --- a/include/util.js +++ b/core/util.js @@ -9,170 +9,8 @@ /* jshint white: false, nonstandard: true */ /*global window, console, document, navigator, ActiveXObject, INCLUDE_URI */ -// Globals defined here var Util = {}; - -/* - * Make arrays quack - */ - -var addFunc = function (cl, name, func) { - if (!cl.prototype[name]) { - Object.defineProperty(cl.prototype, name, { enumerable: false, value: func }); - } -}; - -addFunc(Array, 'push8', function (num) { - "use strict"; - this.push(num & 0xFF); -}); - -addFunc(Array, 'push16', function (num) { - "use strict"; - this.push((num >> 8) & 0xFF, - num & 0xFF); -}); - -addFunc(Array, 'push32', function (num) { - "use strict"; - this.push((num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - num & 0xFF); -}); - -// IE does not support map (even in IE9) -//This prototype is provided by the Mozilla foundation and -//is distributed under the MIT license. -//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license -addFunc(Array, 'map', function (fun /*, thisp*/) { - "use strict"; - var len = this.length; - if (typeof fun != "function") { - throw new TypeError(); - } - - var res = new Array(len); - var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } - } - - return res; -}); - -// IE <9 does not support indexOf -//This prototype is provided by the Mozilla foundation and -//is distributed under the MIT license. -//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license -addFunc(Array, 'indexOf', function (elt /*, from*/) { - "use strict"; - var len = this.length >>> 0; - - var from = Number(arguments[1]) || 0; - from = (from < 0) ? Math.ceil(from) : Math.floor(from); - if (from < 0) { - from += len; - } - - for (; from < len; from++) { - if (from in this && - this[from] === elt) { - return from; - } - } - return -1; -}); - -// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys -if (!Object.keys) { - Object.keys = (function () { - 'use strict'; - var hasOwnProperty = Object.prototype.hasOwnProperty, - hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), - dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ], - dontEnumsLength = dontEnums.length; - - return function (obj) { - if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { - throw new TypeError('Object.keys called on non-object'); - } - - var result = [], prop, i; - - for (prop in obj) { - if (hasOwnProperty.call(obj, prop)) { - result.push(prop); - } - } - - if (hasDontEnumBug) { - for (i = 0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) { - result.push(dontEnums[i]); - } - } - } - return result; - }; - })(); -} - -// PhantomJS 1.x doesn't support bind, -// so leave this in until PhantomJS 2.0 is released -//This prototype is provided by the Mozilla foundation and -//is distributed under the MIT license. -//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license -addFunc(Function, 'bind', function (oThis) { - if (typeof this !== "function") { - // closest thing possible to the ECMAScript 5 - // internal IsCallable function - throw new TypeError("Function.prototype.bind - " + - "what is trying to be bound is not callable"); - } - - var aArgs = Array.prototype.slice.call(arguments, 1), - fToBind = this, - fNOP = function () {}, - fBound = function () { - return fToBind.apply(this instanceof fNOP && oThis ? this - : oThis, - aArgs.concat(Array.prototype.slice.call(arguments))); - }; - - fNOP.prototype = this.prototype; - fBound.prototype = new fNOP(); - - return fBound; -}); - -// -// requestAnimationFrame shim with setTimeout fallback -// - -window.requestAnimFrame = (function () { - "use strict"; - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function (callback) { - window.setTimeout(callback, 1000 / 60); - }; -})(); - /* * ------------------------------------------------------ * Namespaced in Util @@ -191,39 +29,26 @@ Util.init_logging = function (level) { } else { Util._log_level = level; } - if (typeof window.console === "undefined") { - if (typeof window.opera !== "undefined") { - window.console = { - 'log' : window.opera.postError, - 'warn' : window.opera.postError, - 'error': window.opera.postError - }; - } else { - window.console = { - 'log' : function (m) {}, - 'warn' : function (m) {}, - 'error': function (m) {} - }; - } - } Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {}; - /* jshint -W086 */ - switch (level) { - case 'debug': - Util.Debug = function (msg) { console.log(msg); }; - case 'info': - Util.Info = function (msg) { console.log(msg); }; - case 'warn': - Util.Warn = function (msg) { console.warn(msg); }; - case 'error': - Util.Error = function (msg) { console.error(msg); }; - case 'none': - break; - default: - throw new Error("invalid logging type '" + level + "'"); + if (typeof window.console !== "undefined") { + /* jshint -W086 */ + switch (level) { + case 'debug': + Util.Debug = function (msg) { console.log(msg); }; + case 'info': + Util.Info = function (msg) { console.info(msg); }; + case 'warn': + Util.Warn = function (msg) { console.warn(msg); }; + case 'error': + Util.Error = function (msg) { console.error(msg); }; + case 'none': + break; + default: + throw new Error("invalid logging type '" + level + "'"); + } + /* jshint +W086 */ } - /* jshint +W086 */ }; Util.get_logging = function () { return Util._log_level; @@ -369,70 +194,6 @@ Util.decodeUTF8 = function (utf8string) { * Cross-browser routines */ - -// Dynamically load scripts without using document.write() -// Reference: http://unixpapa.com/js/dyna.html -// -// Handles the case where load_scripts is invoked from a script that -// itself is loaded via load_scripts. Once all scripts are loaded the -// window.onscriptsloaded handler is called (if set). -Util.get_include_uri = function () { - return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/"; -}; -Util._loading_scripts = []; -Util._pending_scripts = []; -Util.load_scripts = function (files) { - "use strict"; - var head = document.getElementsByTagName('head')[0], script, - ls = Util._loading_scripts, ps = Util._pending_scripts; - - var loadFunc = function (e) { - while (ls.length > 0 && (ls[0].readyState === 'loaded' || - ls[0].readyState === 'complete')) { - // For IE, append the script to trigger execution - var s = ls.shift(); - //console.log("loaded script: " + s.src); - head.appendChild(s); - } - if (!this.readyState || - (Util.Engine.presto && this.readyState === 'loaded') || - this.readyState === 'complete') { - if (ps.indexOf(this) >= 0) { - this.onload = this.onreadystatechange = null; - //console.log("completed script: " + this.src); - ps.splice(ps.indexOf(this), 1); - - // Call window.onscriptsload after last script loads - if (ps.length === 0 && window.onscriptsload) { - window.onscriptsload(); - } - } - } - }; - - for (var f = 0; f < files.length; f++) { - script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = Util.get_include_uri() + files[f]; - //console.log("loading script: " + script.src); - script.onload = script.onreadystatechange = loadFunc; - // In-order script execution tricks - if (Util.Engine.trident) { - // For IE wait until readyState is 'loaded' before - // appending it which will trigger execution - // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order - ls.push(script); - } else { - // For webkit and firefox set async=false and append now - // https://developer.mozilla.org/en-US/docs/HTML/Element/script - script.async = false; - head.appendChild(script); - } - ps.push(script); - } -}; - - Util.getPosition = function(obj) { "use strict"; // NB(sross): the Mozilla developer reference seems to indicate that @@ -471,41 +232,9 @@ Util.getEventPosition = function (e, obj, scale) { return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale}; }; - -// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events -Util.addEvent = function (obj, evType, fn) { - "use strict"; - if (obj.attachEvent) { - var r = obj.attachEvent("on" + evType, fn); - return r; - } else if (obj.addEventListener) { - obj.addEventListener(evType, fn, false); - return true; - } else { - throw new Error("Handler could not be attached"); - } -}; - -Util.removeEvent = function (obj, evType, fn) { - "use strict"; - if (obj.detachEvent) { - var r = obj.detachEvent("on" + evType, fn); - return r; - } else if (obj.removeEventListener) { - obj.removeEventListener(evType, fn, false); - return true; - } else { - throw new Error("Handler could not be removed"); - } -}; - Util.stopEvent = function (e) { - "use strict"; - if (e.stopPropagation) { e.stopPropagation(); } - else { e.cancelBubble = true; } - - if (e.preventDefault) { e.preventDefault(); } - else { e.returnValue = false; } + e.stopPropagation(); + e.preventDefault(); }; Util._cursor_uris_supported = null; @@ -620,3 +349,5 @@ Util.Flash = (function () { version = v.match(/\d+/g); return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; }()); + +/* [module] export default Util; */ diff --git a/include/websock.js b/core/websock.js similarity index 96% rename from include/websock.js rename to core/websock.js index 4d7a4f9a..1271d2f5 100644 --- a/include/websock.js +++ b/core/websock.js @@ -14,29 +14,15 @@ * read binary data off of the receive queue. */ +/* [module] + * import Util from "./util"; + * import Base64 from "./base64"; + */ + /*jslint browser: true, bitwise: true */ /*global Util*/ - -// Load Flash WebSocket emulator if needed - -// To force WebSocket emulator even when native WebSocket available -//window.WEB_SOCKET_FORCE_FLASH = true; -// To enable WebSocket emulator debug: -//window.WEB_SOCKET_DEBUG=1; - -if (window.WebSocket && !window.WEB_SOCKET_FORCE_FLASH) { - Websock_native = true; -} else if (window.MozWebSocket && !window.WEB_SOCKET_FORCE_FLASH) { - Websock_native = true; - window.WebSocket = window.MozWebSocket; -} else { - /* no builtin WebSocket so load web_socket.js */ - - Websock_native = false; -} - -function Websock() { +/* [module] export default */ function Websock() { "use strict"; this._websocket = null; // WebSocket object @@ -62,7 +48,7 @@ function Websock() { 'close': function () {}, 'error': function () {} }; -} +}; (function () { "use strict"; diff --git a/docs/notes b/docs/notes index 036cd510..dfef0bd6 100644 --- a/docs/notes +++ b/docs/notes @@ -2,4 +2,4 @@ Rebuilding inflator.js - Download pako from npm - Install browserify using npm -- browserify utils/inflator.partial.js -o include/inflator.js -s inflator +- browserify core/inflator.mod.js -o core/inflator.js -s Inflator diff --git a/favicon.ico b/favicon.ico index 45399c8c..af26b7b3 120000 --- a/favicon.ico +++ b/favicon.ico @@ -1 +1 @@ -images/favicon.ico \ No newline at end of file +app/images/favicon.ico \ No newline at end of file diff --git a/include/chrome-app/tcp-client.js b/include/chrome-app/tcp-client.js deleted file mode 100644 index b8c125f5..00000000 --- a/include/chrome-app/tcp-client.js +++ /dev/null @@ -1,321 +0,0 @@ -/* -Copyright 2012 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -Author: Boris Smus (smus@chromium.org) -*/ - -(function(exports) { - - // Define some local variables here. - var socket = chrome.socket || chrome.experimental.socket; - var dns = chrome.experimental.dns; - - /** - * Creates an instance of the client - * - * @param {String} host The remote host to connect to - * @param {Number} port The port to connect to at the remote host - */ - function TcpClient(host, port, pollInterval) { - this.host = host; - this.port = port; - this.pollInterval = pollInterval || 15; - - // Callback functions. - this.callbacks = { - connect: null, // Called when socket is connected. - disconnect: null, // Called when socket is disconnected. - recvBuffer: null, // Called (as ArrayBuffer) when client receives data from server. - recvString: null, // Called (as string) when client receives data from server. - sent: null // Called when client sends data to server. - }; - - // Socket. - this.socketId = null; - this.isConnected = false; - - log('initialized tcp client'); - } - - /** - * Connects to the TCP socket, and creates an open socket. - * - * @see http://developer.chrome.com/trunk/apps/socket.html#method-create - * @param {Function} callback The function to call on connection - */ - TcpClient.prototype.connect = function(callback) { - // First resolve the hostname to an IP. - dns.resolve(this.host, function(result) { - this.addr = result.address; - socket.create('tcp', {}, this._onCreate.bind(this)); - - // Register connect callback. - this.callbacks.connect = callback; - }.bind(this)); - }; - - /** - * Sends an arraybuffer/view down the wire to the remote side - * - * @see http://developer.chrome.com/trunk/apps/socket.html#method-write - * @param {String} msg The arraybuffer/view to send - * @param {Function} callback The function to call when the message has sent - */ - TcpClient.prototype.sendBuffer = function(buf, callback) { - if (buf.buffer) { - buf = buf.buffer; - } - - /* - // Debug - var bytes = [], u8 = new Uint8Array(buf); - for (var i = 0; i < u8.length; i++) { - bytes.push(u8[i]); - } - log("sending bytes: " + (bytes.join(','))); - */ - - socket.write(this.socketId, buf, this._onWriteComplete.bind(this)); - - // Register sent callback. - this.callbacks.sent = callback; - }; - - /** - * Sends a string down the wire to the remote side - * - * @see http://developer.chrome.com/trunk/apps/socket.html#method-write - * @param {String} msg The string to send - * @param {Function} callback The function to call when the message has sent - */ - TcpClient.prototype.sendString = function(msg, callback) { - /* - // Debug - log("sending string: " + msg); - */ - - this._stringToArrayBuffer(msg, function(arrayBuffer) { - socket.write(this.socketId, arrayBuffer, this._onWriteComplete.bind(this)); - }.bind(this)); - - // Register sent callback. - this.callbacks.sent = callback; - }; - - /** - * Sets the callback for when a message is received - * - * @param {Function} callback The function to call when a message has arrived - * @param {String} type The callback argument type: "arraybuffer" or "string" - */ - TcpClient.prototype.addResponseListener = function(callback, type) { - if (typeof type === "undefined") { - type = "arraybuffer"; - } - // Register received callback. - if (type === "string") { - this.callbacks.recvString = callback; - } else { - this.callbacks.recvBuffer = callback; - } - }; - - /** - * Sets the callback for when the socket disconnects - * - * @param {Function} callback The function to call when the socket disconnects - * @param {String} type The callback argument type: "arraybuffer" or "string" - */ - TcpClient.prototype.addDisconnectListener = function(callback) { - // Register disconnect callback. - this.callbacks.disconnect = callback; - }; - - /** - * Disconnects from the remote side - * - * @see http://developer.chrome.com/trunk/apps/socket.html#method-disconnect - */ - TcpClient.prototype.disconnect = function() { - if (this.isConnected) { - this.isConnected = false; - socket.disconnect(this.socketId); - if (this.callbacks.disconnect) { - this.callbacks.disconnect(); - } - log('socket disconnected'); - } - }; - - /** - * The callback function used for when we attempt to have Chrome - * create a socket. If the socket is successfully created - * we go ahead and connect to the remote side. - * - * @private - * @see http://developer.chrome.com/trunk/apps/socket.html#method-connect - * @param {Object} createInfo The socket details - */ - TcpClient.prototype._onCreate = function(createInfo) { - this.socketId = createInfo.socketId; - if (this.socketId > 0) { - socket.connect(this.socketId, this.addr, this.port, this._onConnectComplete.bind(this)); - } else { - error('Unable to create socket'); - } - }; - - /** - * The callback function used for when we attempt to have Chrome - * connect to the remote side. If a successful connection is - * made then polling starts to check for data to read - * - * @private - * @param {Number} resultCode Indicates whether the connection was successful - */ - TcpClient.prototype._onConnectComplete = function(resultCode) { - // Start polling for reads. - this.isConnected = true; - setTimeout(this._periodicallyRead.bind(this), this.pollInterval); - - if (this.callbacks.connect) { - log('connect complete'); - this.callbacks.connect(); - } - log('onConnectComplete'); - }; - - /** - * Checks for new data to read from the socket - * - * @see http://developer.chrome.com/trunk/apps/socket.html#method-read - */ - TcpClient.prototype._periodicallyRead = function() { - var that = this; - socket.getInfo(this.socketId, function (info) { - if (info.connected) { - setTimeout(that._periodicallyRead.bind(that), that.pollInterval); - socket.read(that.socketId, null, that._onDataRead.bind(that)); - } else if (that.isConnected) { - log('socket disconnect detected'); - that.disconnect(); - } - }); - }; - - /** - * Callback function for when data has been read from the socket. - * Converts the array buffer that is read in to a string - * and sends it on for further processing by passing it to - * the previously assigned callback function. - * - * @private - * @see TcpClient.prototype.addResponseListener - * @param {Object} readInfo The incoming message - */ - TcpClient.prototype._onDataRead = function(readInfo) { - // Call received callback if there's data in the response. - if (readInfo.resultCode > 0) { - log('onDataRead'); - - /* - // Debug - var bytes = [], u8 = new Uint8Array(readInfo.data); - for (var i = 0; i < u8.length; i++) { - bytes.push(u8[i]); - } - log("received bytes: " + (bytes.join(','))); - */ - - if (this.callbacks.recvBuffer) { - // Return raw ArrayBuffer directly. - this.callbacks.recvBuffer(readInfo.data); - } - if (this.callbacks.recvString) { - // Convert ArrayBuffer to string. - this._arrayBufferToString(readInfo.data, function(str) { - this.callbacks.recvString(str); - }.bind(this)); - } - - // Trigger another read right away - setTimeout(this._periodicallyRead.bind(this), 0); - } - }; - - /** - * Callback for when data has been successfully - * written to the socket. - * - * @private - * @param {Object} writeInfo The outgoing message - */ - TcpClient.prototype._onWriteComplete = function(writeInfo) { - log('onWriteComplete'); - // Call sent callback. - if (this.callbacks.sent) { - this.callbacks.sent(writeInfo); - } - }; - - /** - * Converts an array buffer to a string - * - * @private - * @param {ArrayBuffer} buf The buffer to convert - * @param {Function} callback The function to call when conversion is complete - */ - TcpClient.prototype._arrayBufferToString = function(buf, callback) { - var bb = new Blob([new Uint8Array(buf)]); - var f = new FileReader(); - f.onload = function(e) { - callback(e.target.result); - }; - f.readAsText(bb); - }; - - /** - * Converts a string to an array buffer - * - * @private - * @param {String} str The string to convert - * @param {Function} callback The function to call when conversion is complete - */ - TcpClient.prototype._stringToArrayBuffer = function(str, callback) { - var bb = new Blob([str]); - var f = new FileReader(); - f.onload = function(e) { - callback(e.target.result); - }; - f.readAsArrayBuffer(bb); - }; - - /** - * Wrapper function for logging - */ - function log(msg) { - console.log(msg); - } - - /** - * Wrapper function for error logging - */ - function error(msg) { - console.error(msg); - } - - exports.TcpClient = TcpClient; - -})(window); diff --git a/include/keysym.js b/include/keysym.js deleted file mode 100644 index 58b107c0..00000000 --- a/include/keysym.js +++ /dev/null @@ -1,378 +0,0 @@ -var XK_VoidSymbol = 0xffffff, /* Void symbol */ - -XK_BackSpace = 0xff08, /* Back space, back char */ -XK_Tab = 0xff09, -XK_Linefeed = 0xff0a, /* Linefeed, LF */ -XK_Clear = 0xff0b, -XK_Return = 0xff0d, /* Return, enter */ -XK_Pause = 0xff13, /* Pause, hold */ -XK_Scroll_Lock = 0xff14, -XK_Sys_Req = 0xff15, -XK_Escape = 0xff1b, -XK_Delete = 0xffff, /* Delete, rubout */ - -/* Cursor control & motion */ - -XK_Home = 0xff50, -XK_Left = 0xff51, /* Move left, left arrow */ -XK_Up = 0xff52, /* Move up, up arrow */ -XK_Right = 0xff53, /* Move right, right arrow */ -XK_Down = 0xff54, /* Move down, down arrow */ -XK_Prior = 0xff55, /* Prior, previous */ -XK_Page_Up = 0xff55, -XK_Next = 0xff56, /* Next */ -XK_Page_Down = 0xff56, -XK_End = 0xff57, /* EOL */ -XK_Begin = 0xff58, /* BOL */ - - -/* Misc functions */ - -XK_Select = 0xff60, /* Select, mark */ -XK_Print = 0xff61, -XK_Execute = 0xff62, /* Execute, run, do */ -XK_Insert = 0xff63, /* Insert, insert here */ -XK_Undo = 0xff65, -XK_Redo = 0xff66, /* Redo, again */ -XK_Menu = 0xff67, -XK_Find = 0xff68, /* Find, search */ -XK_Cancel = 0xff69, /* Cancel, stop, abort, exit */ -XK_Help = 0xff6a, /* Help */ -XK_Break = 0xff6b, -XK_Mode_switch = 0xff7e, /* Character set switch */ -XK_script_switch = 0xff7e, /* Alias for mode_switch */ -XK_Num_Lock = 0xff7f, - -/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ - -XK_KP_Space = 0xff80, /* Space */ -XK_KP_Tab = 0xff89, -XK_KP_Enter = 0xff8d, /* Enter */ -XK_KP_F1 = 0xff91, /* PF1, KP_A, ... */ -XK_KP_F2 = 0xff92, -XK_KP_F3 = 0xff93, -XK_KP_F4 = 0xff94, -XK_KP_Home = 0xff95, -XK_KP_Left = 0xff96, -XK_KP_Up = 0xff97, -XK_KP_Right = 0xff98, -XK_KP_Down = 0xff99, -XK_KP_Prior = 0xff9a, -XK_KP_Page_Up = 0xff9a, -XK_KP_Next = 0xff9b, -XK_KP_Page_Down = 0xff9b, -XK_KP_End = 0xff9c, -XK_KP_Begin = 0xff9d, -XK_KP_Insert = 0xff9e, -XK_KP_Delete = 0xff9f, -XK_KP_Equal = 0xffbd, /* Equals */ -XK_KP_Multiply = 0xffaa, -XK_KP_Add = 0xffab, -XK_KP_Separator = 0xffac, /* Separator, often comma */ -XK_KP_Subtract = 0xffad, -XK_KP_Decimal = 0xffae, -XK_KP_Divide = 0xffaf, - -XK_KP_0 = 0xffb0, -XK_KP_1 = 0xffb1, -XK_KP_2 = 0xffb2, -XK_KP_3 = 0xffb3, -XK_KP_4 = 0xffb4, -XK_KP_5 = 0xffb5, -XK_KP_6 = 0xffb6, -XK_KP_7 = 0xffb7, -XK_KP_8 = 0xffb8, -XK_KP_9 = 0xffb9, - -/* - * Auxiliary functions; note the duplicate definitions for left and right - * function keys; Sun keyboards and a few other manufacturers have such - * function key groups on the left and/or right sides of the keyboard. - * We've not found a keyboard with more than 35 function keys total. - */ - -XK_F1 = 0xffbe, -XK_F2 = 0xffbf, -XK_F3 = 0xffc0, -XK_F4 = 0xffc1, -XK_F5 = 0xffc2, -XK_F6 = 0xffc3, -XK_F7 = 0xffc4, -XK_F8 = 0xffc5, -XK_F9 = 0xffc6, -XK_F10 = 0xffc7, -XK_F11 = 0xffc8, -XK_L1 = 0xffc8, -XK_F12 = 0xffc9, -XK_L2 = 0xffc9, -XK_F13 = 0xffca, -XK_L3 = 0xffca, -XK_F14 = 0xffcb, -XK_L4 = 0xffcb, -XK_F15 = 0xffcc, -XK_L5 = 0xffcc, -XK_F16 = 0xffcd, -XK_L6 = 0xffcd, -XK_F17 = 0xffce, -XK_L7 = 0xffce, -XK_F18 = 0xffcf, -XK_L8 = 0xffcf, -XK_F19 = 0xffd0, -XK_L9 = 0xffd0, -XK_F20 = 0xffd1, -XK_L10 = 0xffd1, -XK_F21 = 0xffd2, -XK_R1 = 0xffd2, -XK_F22 = 0xffd3, -XK_R2 = 0xffd3, -XK_F23 = 0xffd4, -XK_R3 = 0xffd4, -XK_F24 = 0xffd5, -XK_R4 = 0xffd5, -XK_F25 = 0xffd6, -XK_R5 = 0xffd6, -XK_F26 = 0xffd7, -XK_R6 = 0xffd7, -XK_F27 = 0xffd8, -XK_R7 = 0xffd8, -XK_F28 = 0xffd9, -XK_R8 = 0xffd9, -XK_F29 = 0xffda, -XK_R9 = 0xffda, -XK_F30 = 0xffdb, -XK_R10 = 0xffdb, -XK_F31 = 0xffdc, -XK_R11 = 0xffdc, -XK_F32 = 0xffdd, -XK_R12 = 0xffdd, -XK_F33 = 0xffde, -XK_R13 = 0xffde, -XK_F34 = 0xffdf, -XK_R14 = 0xffdf, -XK_F35 = 0xffe0, -XK_R15 = 0xffe0, - -/* Modifiers */ - -XK_Shift_L = 0xffe1, /* Left shift */ -XK_Shift_R = 0xffe2, /* Right shift */ -XK_Control_L = 0xffe3, /* Left control */ -XK_Control_R = 0xffe4, /* Right control */ -XK_Caps_Lock = 0xffe5, /* Caps lock */ -XK_Shift_Lock = 0xffe6, /* Shift lock */ - -XK_Meta_L = 0xffe7, /* Left meta */ -XK_Meta_R = 0xffe8, /* Right meta */ -XK_Alt_L = 0xffe9, /* Left alt */ -XK_Alt_R = 0xffea, /* Right alt */ -XK_Super_L = 0xffeb, /* Left super */ -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) - * Byte 3 = 0 - */ - -XK_space = 0x0020, /* U+0020 SPACE */ -XK_exclam = 0x0021, /* U+0021 EXCLAMATION MARK */ -XK_quotedbl = 0x0022, /* U+0022 QUOTATION MARK */ -XK_numbersign = 0x0023, /* U+0023 NUMBER SIGN */ -XK_dollar = 0x0024, /* U+0024 DOLLAR SIGN */ -XK_percent = 0x0025, /* U+0025 PERCENT SIGN */ -XK_ampersand = 0x0026, /* U+0026 AMPERSAND */ -XK_apostrophe = 0x0027, /* U+0027 APOSTROPHE */ -XK_quoteright = 0x0027, /* deprecated */ -XK_parenleft = 0x0028, /* U+0028 LEFT PARENTHESIS */ -XK_parenright = 0x0029, /* U+0029 RIGHT PARENTHESIS */ -XK_asterisk = 0x002a, /* U+002A ASTERISK */ -XK_plus = 0x002b, /* U+002B PLUS SIGN */ -XK_comma = 0x002c, /* U+002C COMMA */ -XK_minus = 0x002d, /* U+002D HYPHEN-MINUS */ -XK_period = 0x002e, /* U+002E FULL STOP */ -XK_slash = 0x002f, /* U+002F SOLIDUS */ -XK_0 = 0x0030, /* U+0030 DIGIT ZERO */ -XK_1 = 0x0031, /* U+0031 DIGIT ONE */ -XK_2 = 0x0032, /* U+0032 DIGIT TWO */ -XK_3 = 0x0033, /* U+0033 DIGIT THREE */ -XK_4 = 0x0034, /* U+0034 DIGIT FOUR */ -XK_5 = 0x0035, /* U+0035 DIGIT FIVE */ -XK_6 = 0x0036, /* U+0036 DIGIT SIX */ -XK_7 = 0x0037, /* U+0037 DIGIT SEVEN */ -XK_8 = 0x0038, /* U+0038 DIGIT EIGHT */ -XK_9 = 0x0039, /* U+0039 DIGIT NINE */ -XK_colon = 0x003a, /* U+003A COLON */ -XK_semicolon = 0x003b, /* U+003B SEMICOLON */ -XK_less = 0x003c, /* U+003C LESS-THAN SIGN */ -XK_equal = 0x003d, /* U+003D EQUALS SIGN */ -XK_greater = 0x003e, /* U+003E GREATER-THAN SIGN */ -XK_question = 0x003f, /* U+003F QUESTION MARK */ -XK_at = 0x0040, /* U+0040 COMMERCIAL AT */ -XK_A = 0x0041, /* U+0041 LATIN CAPITAL LETTER A */ -XK_B = 0x0042, /* U+0042 LATIN CAPITAL LETTER B */ -XK_C = 0x0043, /* U+0043 LATIN CAPITAL LETTER C */ -XK_D = 0x0044, /* U+0044 LATIN CAPITAL LETTER D */ -XK_E = 0x0045, /* U+0045 LATIN CAPITAL LETTER E */ -XK_F = 0x0046, /* U+0046 LATIN CAPITAL LETTER F */ -XK_G = 0x0047, /* U+0047 LATIN CAPITAL LETTER G */ -XK_H = 0x0048, /* U+0048 LATIN CAPITAL LETTER H */ -XK_I = 0x0049, /* U+0049 LATIN CAPITAL LETTER I */ -XK_J = 0x004a, /* U+004A LATIN CAPITAL LETTER J */ -XK_K = 0x004b, /* U+004B LATIN CAPITAL LETTER K */ -XK_L = 0x004c, /* U+004C LATIN CAPITAL LETTER L */ -XK_M = 0x004d, /* U+004D LATIN CAPITAL LETTER M */ -XK_N = 0x004e, /* U+004E LATIN CAPITAL LETTER N */ -XK_O = 0x004f, /* U+004F LATIN CAPITAL LETTER O */ -XK_P = 0x0050, /* U+0050 LATIN CAPITAL LETTER P */ -XK_Q = 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */ -XK_R = 0x0052, /* U+0052 LATIN CAPITAL LETTER R */ -XK_S = 0x0053, /* U+0053 LATIN CAPITAL LETTER S */ -XK_T = 0x0054, /* U+0054 LATIN CAPITAL LETTER T */ -XK_U = 0x0055, /* U+0055 LATIN CAPITAL LETTER U */ -XK_V = 0x0056, /* U+0056 LATIN CAPITAL LETTER V */ -XK_W = 0x0057, /* U+0057 LATIN CAPITAL LETTER W */ -XK_X = 0x0058, /* U+0058 LATIN CAPITAL LETTER X */ -XK_Y = 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */ -XK_Z = 0x005a, /* U+005A LATIN CAPITAL LETTER Z */ -XK_bracketleft = 0x005b, /* U+005B LEFT SQUARE BRACKET */ -XK_backslash = 0x005c, /* U+005C REVERSE SOLIDUS */ -XK_bracketright = 0x005d, /* U+005D RIGHT SQUARE BRACKET */ -XK_asciicircum = 0x005e, /* U+005E CIRCUMFLEX ACCENT */ -XK_underscore = 0x005f, /* U+005F LOW LINE */ -XK_grave = 0x0060, /* U+0060 GRAVE ACCENT */ -XK_quoteleft = 0x0060, /* deprecated */ -XK_a = 0x0061, /* U+0061 LATIN SMALL LETTER A */ -XK_b = 0x0062, /* U+0062 LATIN SMALL LETTER B */ -XK_c = 0x0063, /* U+0063 LATIN SMALL LETTER C */ -XK_d = 0x0064, /* U+0064 LATIN SMALL LETTER D */ -XK_e = 0x0065, /* U+0065 LATIN SMALL LETTER E */ -XK_f = 0x0066, /* U+0066 LATIN SMALL LETTER F */ -XK_g = 0x0067, /* U+0067 LATIN SMALL LETTER G */ -XK_h = 0x0068, /* U+0068 LATIN SMALL LETTER H */ -XK_i = 0x0069, /* U+0069 LATIN SMALL LETTER I */ -XK_j = 0x006a, /* U+006A LATIN SMALL LETTER J */ -XK_k = 0x006b, /* U+006B LATIN SMALL LETTER K */ -XK_l = 0x006c, /* U+006C LATIN SMALL LETTER L */ -XK_m = 0x006d, /* U+006D LATIN SMALL LETTER M */ -XK_n = 0x006e, /* U+006E LATIN SMALL LETTER N */ -XK_o = 0x006f, /* U+006F LATIN SMALL LETTER O */ -XK_p = 0x0070, /* U+0070 LATIN SMALL LETTER P */ -XK_q = 0x0071, /* U+0071 LATIN SMALL LETTER Q */ -XK_r = 0x0072, /* U+0072 LATIN SMALL LETTER R */ -XK_s = 0x0073, /* U+0073 LATIN SMALL LETTER S */ -XK_t = 0x0074, /* U+0074 LATIN SMALL LETTER T */ -XK_u = 0x0075, /* U+0075 LATIN SMALL LETTER U */ -XK_v = 0x0076, /* U+0076 LATIN SMALL LETTER V */ -XK_w = 0x0077, /* U+0077 LATIN SMALL LETTER W */ -XK_x = 0x0078, /* U+0078 LATIN SMALL LETTER X */ -XK_y = 0x0079, /* U+0079 LATIN SMALL LETTER Y */ -XK_z = 0x007a, /* U+007A LATIN SMALL LETTER Z */ -XK_braceleft = 0x007b, /* U+007B LEFT CURLY BRACKET */ -XK_bar = 0x007c, /* U+007C VERTICAL LINE */ -XK_braceright = 0x007d, /* U+007D RIGHT CURLY BRACKET */ -XK_asciitilde = 0x007e, /* U+007E TILDE */ - -XK_nobreakspace = 0x00a0, /* U+00A0 NO-BREAK SPACE */ -XK_exclamdown = 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */ -XK_cent = 0x00a2, /* U+00A2 CENT SIGN */ -XK_sterling = 0x00a3, /* U+00A3 POUND SIGN */ -XK_currency = 0x00a4, /* U+00A4 CURRENCY SIGN */ -XK_yen = 0x00a5, /* U+00A5 YEN SIGN */ -XK_brokenbar = 0x00a6, /* U+00A6 BROKEN BAR */ -XK_section = 0x00a7, /* U+00A7 SECTION SIGN */ -XK_diaeresis = 0x00a8, /* U+00A8 DIAERESIS */ -XK_copyright = 0x00a9, /* U+00A9 COPYRIGHT SIGN */ -XK_ordfeminine = 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */ -XK_guillemotleft = 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ -XK_notsign = 0x00ac, /* U+00AC NOT SIGN */ -XK_hyphen = 0x00ad, /* U+00AD SOFT HYPHEN */ -XK_registered = 0x00ae, /* U+00AE REGISTERED SIGN */ -XK_macron = 0x00af, /* U+00AF MACRON */ -XK_degree = 0x00b0, /* U+00B0 DEGREE SIGN */ -XK_plusminus = 0x00b1, /* U+00B1 PLUS-MINUS SIGN */ -XK_twosuperior = 0x00b2, /* U+00B2 SUPERSCRIPT TWO */ -XK_threesuperior = 0x00b3, /* U+00B3 SUPERSCRIPT THREE */ -XK_acute = 0x00b4, /* U+00B4 ACUTE ACCENT */ -XK_mu = 0x00b5, /* U+00B5 MICRO SIGN */ -XK_paragraph = 0x00b6, /* U+00B6 PILCROW SIGN */ -XK_periodcentered = 0x00b7, /* U+00B7 MIDDLE DOT */ -XK_cedilla = 0x00b8, /* U+00B8 CEDILLA */ -XK_onesuperior = 0x00b9, /* U+00B9 SUPERSCRIPT ONE */ -XK_masculine = 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */ -XK_guillemotright = 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ -XK_onequarter = 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */ -XK_onehalf = 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */ -XK_threequarters = 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */ -XK_questiondown = 0x00bf, /* U+00BF INVERTED QUESTION MARK */ -XK_Agrave = 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ -XK_Aacute = 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ -XK_Acircumflex = 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ -XK_Atilde = 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ -XK_Adiaeresis = 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ -XK_Aring = 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ -XK_AE = 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */ -XK_Ccedilla = 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ -XK_Egrave = 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ -XK_Eacute = 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ -XK_Ecircumflex = 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ -XK_Ediaeresis = 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ -XK_Igrave = 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ -XK_Iacute = 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ -XK_Icircumflex = 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ -XK_Idiaeresis = 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ -XK_ETH = 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */ -XK_Eth = 0x00d0, /* deprecated */ -XK_Ntilde = 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ -XK_Ograve = 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ -XK_Oacute = 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ -XK_Ocircumflex = 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ -XK_Otilde = 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ -XK_Odiaeresis = 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ -XK_multiply = 0x00d7, /* U+00D7 MULTIPLICATION SIGN */ -XK_Oslash = 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ -XK_Ooblique = 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ -XK_Ugrave = 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ -XK_Uacute = 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ -XK_Ucircumflex = 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ -XK_Udiaeresis = 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ -XK_Yacute = 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ -XK_THORN = 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */ -XK_Thorn = 0x00de, /* deprecated */ -XK_ssharp = 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */ -XK_agrave = 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ -XK_aacute = 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ -XK_acircumflex = 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ -XK_atilde = 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ -XK_adiaeresis = 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ -XK_aring = 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ -XK_ae = 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */ -XK_ccedilla = 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ -XK_egrave = 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ -XK_eacute = 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ -XK_ecircumflex = 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ -XK_ediaeresis = 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ -XK_igrave = 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ -XK_iacute = 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ -XK_icircumflex = 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ -XK_idiaeresis = 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ -XK_eth = 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */ -XK_ntilde = 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ -XK_ograve = 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ -XK_oacute = 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ -XK_ocircumflex = 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ -XK_otilde = 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ -XK_odiaeresis = 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ -XK_division = 0x00f7, /* U+00F7 DIVISION SIGN */ -XK_oslash = 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ -XK_ooblique = 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ -XK_ugrave = 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ -XK_uacute = 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ -XK_ucircumflex = 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ -XK_udiaeresis = 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ -XK_yacute = 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ -XK_thorn = 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */ -XK_ydiaeresis = 0x00ff; /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ diff --git a/include/logo.js b/include/logo.js deleted file mode 100644 index befa598c..00000000 --- a/include/logo.js +++ /dev/null @@ -1 +0,0 @@ -noVNC_logo = {"width": 640, "height": 435, "data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAGzCAYAAAC/y6a9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAStAAAErQBBHTWggAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N13fBvlwQfw3522ZMm2vPdIGCFkA4GyoYyGsCmjk+7dQksHL2/H2/dtC4W2tLTlfelu2VA2lEILFCgQIHEGJCQkdjzkLdmWZGvfvX8oOkmJEy/pNO73/Xz44DtLzz2RT7qfnnXC8uXLZUxDlqfdnUYQhIP+bjbPn+5xhypzrmUf6rGzOc5cjzVduXN9/nTPyfRrMt/jzOcY05U5n3L2f95s/34LPW4m/p6FbLp/73xe+5nKnWuZs/07ZOOcnusx5nucbJU727LneuxslDmdTBxn/2NmusyEuZS7kHMxG/XP5Gf3TOVmQzY+u/PhPMnkMcSsH5WIiIiI8goDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHG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"}; diff --git a/include/xtscancodes.js b/include/xtscancodes.js deleted file mode 100644 index d19a0174..00000000 --- a/include/xtscancodes.js +++ /dev/null @@ -1,146 +0,0 @@ -var XtScancode = {}; -XtScancode["Escape"] = 0x0001; -XtScancode["Digit1"] = 0x0002; -XtScancode["Digit2"] = 0x0003; -XtScancode["Digit3"] = 0x0004; -XtScancode["Digit4"] = 0x0005; -XtScancode["Digit5"] = 0x0006; -XtScancode["Digit6"] = 0x0007; -XtScancode["Digit7"] = 0x0008; -XtScancode["Digit8"] = 0x0009; -XtScancode["Digit9"] = 0x000A; -XtScancode["Digit0"] = 0x000B; -XtScancode["Minus"] = 0x000C; -XtScancode["Equal"] = 0x000D; -XtScancode["Backspace"] = 0x000E; -XtScancode["Tab"] = 0x000F; -XtScancode["KeyQ"] = 0x0010; -XtScancode["KeyW"] = 0x0011; -XtScancode["KeyE"] = 0x0012; -XtScancode["KeyR"] = 0x0013; -XtScancode["KeyT"] = 0x0014; -XtScancode["KeyY"] = 0x0015; -XtScancode["KeyU"] = 0x0016; -XtScancode["KeyI"] = 0x0017; -XtScancode["KeyO"] = 0x0018; -XtScancode["KeyP"] = 0x0019; -XtScancode["BracketLeft"] = 0x001A; -XtScancode["BracketRight"] = 0x001B; -XtScancode["Enter"] = 0x001C; -XtScancode["ControlLeft"] = 0x001D; -XtScancode["KeyA"] = 0x001E; -XtScancode["KeyS"] = 0x001F; -XtScancode["KeyD"] = 0x0020; -XtScancode["KeyF"] = 0x0021; -XtScancode["KeyG"] = 0x0022; -XtScancode["KeyH"] = 0x0023; -XtScancode["KeyJ"] = 0x0024; -XtScancode["KeyK"] = 0x0025; -XtScancode["KeyL"] = 0x0026; -XtScancode["Semicolon"] = 0x0027; -XtScancode["Quote"] = 0x0028; -XtScancode["Backquote"] = 0x0029; -XtScancode["ShiftLeft"] = 0x002A; -XtScancode["Backslash"] = 0x002B; -XtScancode["KeyZ"] = 0x002C; -XtScancode["KeyX"] = 0x002D; -XtScancode["KeyC"] = 0x002E; -XtScancode["KeyV"] = 0x002F; -XtScancode["KeyB"] = 0x0030; -XtScancode["KeyN"] = 0x0031; -XtScancode["KeyM"] = 0x0032; -XtScancode["Comma"] = 0x0033; -XtScancode["Period"] = 0x0034; -XtScancode["Slash"] = 0x0035; -XtScancode["ShiftRight"] = 0x0036; -XtScancode["NumpadMultiply"] = 0x0037; -XtScancode["AltLeft"] = 0x0038; -XtScancode["Space"] = 0x0039; -XtScancode["CapsLock"] = 0x003A; -XtScancode["F1"] = 0x003B; -XtScancode["F2"] = 0x003C; -XtScancode["F3"] = 0x003D; -XtScancode["F4"] = 0x003E; -XtScancode["F5"] = 0x003F; -XtScancode["F6"] = 0x0040; -XtScancode["F7"] = 0x0041; -XtScancode["F8"] = 0x0042; -XtScancode["F9"] = 0x0043; -XtScancode["F10"] = 0x0044; -XtScancode["Pause"] = 0xE045; -XtScancode["ScrollLock"] = 0x0046; -XtScancode["Numpad7"] = 0x0047; -XtScancode["Numpad8"] = 0x0048; -XtScancode["Numpad9"] = 0x0049; -XtScancode["NumpadSubtract"] = 0x004A; -XtScancode["Numpad4"] = 0x004B; -XtScancode["Numpad5"] = 0x004C; -XtScancode["Numpad6"] = 0x004D; -XtScancode["NumpadAdd"] = 0x004E; -XtScancode["Numpad1"] = 0x004F; -XtScancode["Numpad2"] = 0x0050; -XtScancode["Numpad3"] = 0x0051; -XtScancode["Numpad0"] = 0x0052; -XtScancode["NumpadDecimal"] = 0x0053; -XtScancode["IntlBackslash"] = 0x0056; -XtScancode["F11"] = 0x0057; -XtScancode["F12"] = 0x0058; -XtScancode["IntlYen"] = 0x007D; -XtScancode["MediaTrackPrevious"] = 0xE010; -XtScancode["MediaTrackNext"] = 0xE019; -XtScancode["NumpadEnter"] = 0xE01C; -XtScancode["ControlRight"] = 0xE01D; -XtScancode["VolumeMute"] = 0xE020; -XtScancode["MediaPlayPause"] = 0xE022; -XtScancode["MediaStop"] = 0xE024; -XtScancode["VolumeDown"] = 0xE02E; -XtScancode["VolumeUp"] = 0xE030; -XtScancode["BrowserHome"] = 0xE032; -XtScancode["NumpadDivide"] = 0xE035; -XtScancode["PrintScreen"] = 0xE037; -XtScancode["AltRight"] = 0xE038; -XtScancode["NumLock"] = 0x0045; -XtScancode["Home"] = 0xE047; -XtScancode["ArrowUp"] = 0xE048; -XtScancode["PageUp"] = 0xE049; -XtScancode["ArrowLeft"] = 0xE04B; -XtScancode["ArrowRight"] = 0xE04D; -XtScancode["End"] = 0xE04F; -XtScancode["ArrowDown"] = 0xE050; -XtScancode["PageDown"] = 0xE051; -XtScancode["Insert"] = 0xE052; -XtScancode["Delete"] = 0xE053; -XtScancode["OSLeft"] = 0xE05B; -XtScancode["OSRight"] = 0xE05C; -XtScancode["ContextMenu"] = 0xE05D; -XtScancode["BrowserSearch"] = 0xE065; -XtScancode["BrowserFavorites"] = 0xE066; -XtScancode["BrowserRefresh"] = 0xE067; -XtScancode["BrowserStop"] = 0xE068; -XtScancode["BrowserForward"] = 0xE069; -XtScancode["BrowserBack"] = 0xE06A; -XtScancode["NumpadComma"] = 0x007E; -XtScancode["NumpadEqual"] = 0x0059; -XtScancode["F13"] = 0x0064; -XtScancode["F14"] = 0x0065; -XtScancode["F15"] = 0x0066; -XtScancode["F16"] = 0x0067; -XtScancode["F17"] = 0x0068; -XtScancode["F18"] = 0x0069; -XtScancode["F19"] = 0x006A; -XtScancode["F20"] = 0x006B; -XtScancode["F21"] = 0x006C; -XtScancode["F22"] = 0x006D; -XtScancode["F23"] = 0x006E; -XtScancode["F24"] = 0x0076; -XtScancode["KanaMode"] = 0x0070; -XtScancode["Lang2"] = 0x0071; -XtScancode["Lang1"] = 0x0072; -XtScancode["IntlRo"] = 0x0073; -XtScancode["Convert"] = 0x0079; -XtScancode["NonConvert"] = 0x007B; -XtScancode["LaunchApp2"] = 0xE021; -XtScancode["Power"] = 0xE05E; -XtScancode["LaunchApp1"] = 0xE06B; -XtScancode["LaunchMail"] = 0xE06C; -XtScancode["MediaSelect"] = 0xE06D; diff --git a/karma.conf.js b/karma.conf.js index 2c49ffc7..5f3c20b9 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -110,19 +110,19 @@ module.exports = function(config) { files: [ 'tests/fake.*.js', 'tests/assertions.js', - 'include/util.js', // load first to avoid issues, since methods are called immediately - //'../include/*.js', - 'include/base64.js', - 'include/keysym.js', - 'include/keysymdef.js', - 'include/xtscancodes.js', - 'include/keyboard.js', - 'include/input.js', - 'include/websock.js', - 'include/rfb.js', - 'include/des.js', - 'include/display.js', - 'include/inflator.js', + 'core/util.js', // load first to avoid issues, since methods are called immediately + //'../core/*.js', + 'core/base64.js', + 'core/input/keysym.js', + 'core/input/keysymdef.js', + 'core/input/xtscancodes.js', + 'core/input/util.js', + 'core/input/devices.js', + 'core/websock.js', + 'core/rfb.js', + 'core/des.js', + 'core/display.js', + 'core/inflator.js', 'tests/test.*.js' ], @@ -134,8 +134,8 @@ module.exports = function(config) { // list of files to exclude exclude: [ - '../include/playback.js', - '../include/ui.js' + '../tests/playback.js', + '../app/ui.js' ], customLaunchers: customLaunchers, diff --git a/package.json b/package.json index 3db93eb1..c169e922 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "test": "tests" }, "scripts": { - "test": "PATH=$PATH:node_modules/karma/bin karma start karma.conf.js" + "test": "PATH=$PATH:node_modules/karma/bin karma start karma.conf.js", + "prepublish": "node ./utils/use_require.js --as-require", + "build-es6": "node ./utils/use_require.js" }, "repository": { "type": "git", @@ -27,24 +29,32 @@ "homepage": "https://github.com/kanaka/noVNC", "devDependencies": { "ansi": "^0.3.0", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.14.0", + "babelify": "^7.3.0", + "browserify": "^13.1.0", "casperjs": "^1.1.0-beta3", "chai": "^2.1.0", - "commander": "^2.6.0", + "commander": "^2.8.1", + "fs-extra": "^0.30.0", "karma": "^0.12.31", "karma-chai": "^0.1.0", "karma-mocha": "^0.1.10", "karma-mocha-reporter": "^1.0.0", - "karma-phantomjs-launcher": "^0.1.4", + "karma-phantomjs-launcher": "^1.0.0", "karma-sauce-launcher": "^0.2.10", "karma-sinon": "^1.0.4", "karma-sinon-chai-latest": "^0.1.0", "mocha": "^2.1.0", "open": "^0.0.5", - "phantom": "^0.7.2", - "phantomjs": "^1.9.15", + "phantomjs-prebuilt": "^2.1.4", "sinon": "^1.12.2", "sinon-chai": "^2.7.0", "spooky": "^0.2.5", - "temp": "^0.8.1" + "temp": "^0.8.1", + "through2": "^2.0.1" + }, + "dependencies": { + "pako": "^1.0.3" } } diff --git a/tests/arrays.html b/tests/arrays.html deleted file mode 100644 index 257df261..00000000 --- a/tests/arrays.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - Javascript Arrays Performance Test - - - - - - - - -

Javascript Arrays Performance Test

- Iterations:   - Array Size: *1024  - -   - -

- Results:
- -
- - - - - - diff --git a/tests/arrays.js b/tests/arrays.js deleted file mode 100644 index 69da7fbb..00000000 --- a/tests/arrays.js +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Javascript binary array performance tests - * Copyright (C) 2012 Joel Martin - * Licensed under MPL 2.0 (see LICENSE.txt) - */ - -var ctx, i, j, randlist, - new_normal, new_imageData, new_arrayBuffer, - browser = Browser.browser + " " + - Browser.version + " on " + - Browser.OS, - do_imageData = false, - do_arrayBuffer = false, - conf = { - 'create_cnt' : 2000, - 'read_cnt' : 5000000, - 'write_cnt' : 5000000, - 'iterations' : 0, - 'order_l1' : [browser], - 'order_l2' : ['normal', - 'imageData', - 'arrayBuffer'], - 'order_l3' : ['create', - 'sequentialRead', - 'randomRead', - 'sequentialWrite'] - }, - stats = {}, - testFunc = {}, - iteration, arraySize; - -var newline = "\n"; -if (Util.Engine.trident) { - var newline = "
\n"; -} -function message(str) { - //console.log(str); - cell = $D('messages'); - cell.innerHTML += str + newline; - cell.scrollTop = cell.scrollHeight; -} - -function vmessage(str) { - if (verbose) { - message(str); - } else { - console.log(str); - } -} - -new_normal = function() { - var arr = [], i; - for (i = 0; i < arraySize; i++) { - arr[i] = 0; - } - return arr; -} - -/* Will be overridden with real function */ -new_imageData = function() { - throw("imageData not supported"); -}; - -new_imageData_createImageData = function() { - var imageData = ctx.createImageData(1024/4, arraySize / 1024); - return imageData.data; -}; - -new_imageData_getImageData = function() { - var imageData = ctx.getImageData(0, 0, 1024/4, arraySize / 1024), - arr = imageData.data; - for (i = 0; i < arraySize; i++) { - arr[i] = 0; - } - return arr; -}; - -new_arrayBuffer = function() { - var arr = new ArrayBuffer(arraySize); - return new Uint8Array(arr); -} - -function init_randlist() { - randlist = []; - for (var i=0; i < arraySize; i++) { - randlist[i] = parseInt(Math.random() * 256, 10); - } -} -function copy_randlist(arr) { - for (var i=0; i < arraySize; i++) { - arr[i] = randlist[i]; - } -} - -function begin() { - var i, j; - conf.iterations = parseInt($D('iterations').value, 10); - arraySize = parseInt($D('arraySize').value, 10) * 1024; - - init_randlist(); - - // TODO: randomize test_list - - stats = {}; - for (i = 0; i < conf.order_l2.length; i++) { - stats[conf.order_l2[i]] = {}; - for (j = 0; j < conf.order_l3.length; j++) { - stats[conf.order_l2[i]][conf.order_l3[j]] = []; - } - } - - $D('startButton').value = "Running"; - $D('startButton').disabled = true; - - message("running " + conf.iterations + " test iterations"); - iteration = 1; - setTimeout(run_next_iteration, 250); -} - -function finish() { - var totalTime, arrayType, testType, times; - message("tests finished"); - - for (j = 0; j < conf.order_l3.length; j++) { - testType = conf.order_l3[j]; - message("Test '" + testType + "'"); - for (i = 0; i < conf.order_l2.length; i++) { - arrayType = conf.order_l2[i]; - message(" Array Type '" + arrayType); - times = stats[arrayType][testType]; - message(" Average : " + times.mean() + "ms" + - " (Total: " + times.sum() + "ms)"); - message(" Min/Max : " + times.min() + "ms/" + - times.max() + "ms"); - message(" StdDev : " + times.stdDev() + "ms"); - } - } - - vmessage("array_chart.py JSON data:"); - chart_data = {'conf' : conf, 'stats' : { } }; - chart_data.stats[browser] = stats; - chart_data.stats['next_browser'] = {}; - vmessage(JSON.stringify(chart_data, null, 2)); - - $D('startButton').disabled = false; - $D('startButton').value = "Run Tests"; -} - -function run_next_iteration() { - var arrayType, testType, deltaTime; - - for (i = 0; i < conf.order_l2.length; i++) { - arrayType = conf.order_l2[i]; - if (arrayType === 'imageData' && (!do_imageData)) { - continue; - } - if (arrayType === 'arrayBuffer' && (!do_arrayBuffer)) { - continue; - } - for (j = 0; j < conf.order_l3.length; j++) { - testType = conf.order_l3[j]; - - deltaTime = testFunc[arrayType + "_" + testType](); - - stats[arrayType][testType].push(deltaTime); - vmessage("test " + (arrayType + "_" + testType) + - " time: " + (deltaTime) + "ms"); - } - } - - message("finished test iteration " + iteration); - if (iteration >= conf.iterations) { - setTimeout(finish, 1); - return; - } - iteration++; - setTimeout(run_next_iteration, 1); -} - -/* - * Test functions - */ - -testFunc["normal_create"] = function() { - var cnt, arrNormal, startTime, endTime; - vmessage("create normal array " + conf.create_cnt + "x, initialized to 0"); - - startTime = (new Date()).getTime(); - for (cnt = 0; cnt < conf.create_cnt; cnt++) { - arrNormal = new_normal(); - } - endTime = (new Date()).getTime(); - - return endTime - startTime; -}; - -testFunc["imageData_create"] = function() { - var cnt, arrImage, startTime, endTime; - vmessage("create imageData array " + conf.create_cnt + "x, initialized to 0"); - - startTime = (new Date()).getTime(); - for (cnt = 0; cnt < conf.create_cnt; cnt++) { - arrImage = new_imageData(); - } - endTime = (new Date()).getTime(); - - if (arrImage[103] !== 0) { - message("Initialization failed, arrImage[103] is: " + arrImage[103]); - throw("Initialization failed, arrImage[103] is: " + arrImage[103]); - } - return endTime - startTime; -}; - -testFunc["arrayBuffer_create"] = function() { - var cnt, arrBuffer, startTime, endTime; - vmessage("create arrayBuffer array " + conf.create_cnt + "x, initialized to 0"); - - startTime = (new Date()).getTime(); - for (cnt = 0; cnt < conf.create_cnt; cnt++) { - arrBuffer = new_arrayBuffer(); - } - endTime = (new Date()).getTime(); - - if (arrBuffer[103] !== 0) { - message("Initialization failed, arrBuffer[103] is: " + arrBuffer[103]); - throw("Initialization failed, arrBuffer[103] is: " + arrBuffer[103]); - } - return endTime - startTime; -}; - -function test_sequentialRead(arr) { - var i, j, cnt, startTime, endTime; - /* Initialize the array */ - copy_randlist(arr); - - startTime = (new Date()).getTime(); - i = 0; - j = 0; - for (cnt = 0; cnt < conf.read_cnt; cnt++) { - j = arr[i]; - i++; - if (i >= arraySize) { - i = 0; - } - } - endTime = (new Date()).getTime(); - - return endTime - startTime; -} - -function test_randomRead(arr) { - var i, cnt, startTime, endTime; - /* Initialize the array */ - copy_randlist(arr); // used as jumplist - - startTime = (new Date()).getTime(); - i = 0; - for (cnt = 0; cnt < conf.read_cnt; cnt++) { - i = (arr[i] + cnt) % arraySize; - } - endTime = (new Date()).getTime(); - - return endTime - startTime; -} - -function test_sequentialWrite(arr) { - var i, cnt, startTime, endTime; - /* Initialize the array */ - copy_randlist(arr); - - startTime = (new Date()).getTime(); - i = 0; - for (cnt = 0; cnt < conf.write_cnt; cnt++) { - arr[i] = (cnt % 256); - i++; - if (i >= arraySize) { - i = 0; - } - } - endTime = (new Date()).getTime(); - - return endTime - startTime; -} - -/* Sequential Read Tests */ -testFunc["normal_sequentialRead"] = function() { - vmessage("read normal array " + conf.read_cnt + "x"); - return test_sequentialRead(new_normal()); -}; - -testFunc["imageData_sequentialRead"] = function() { - vmessage("read imageData array " + conf.read_cnt + "x"); - return test_sequentialRead(new_imageData()); -}; - -testFunc["arrayBuffer_sequentialRead"] = function() { - vmessage("read arrayBuffer array " + conf.read_cnt + "x"); - return test_sequentialRead(new_arrayBuffer()); -}; - - -/* Random Read Tests */ -testFunc["normal_randomRead"] = function() { - vmessage("read normal array " + conf.read_cnt + "x"); - return test_randomRead(new_normal()); -}; - -testFunc["imageData_randomRead"] = function() { - vmessage("read imageData array " + conf.read_cnt + "x"); - return test_randomRead(new_imageData()); -}; - -testFunc["arrayBuffer_randomRead"] = function() { - vmessage("read arrayBuffer array " + conf.read_cnt + "x"); - return test_randomRead(new_arrayBuffer()); -}; - - -/* Sequential Write Tests */ -testFunc["normal_sequentialWrite"] = function() { - vmessage("write normal array " + conf.write_cnt + "x"); - return test_sequentialWrite(new_normal()); -}; - -testFunc["imageData_sequentialWrite"] = function() { - vmessage("write imageData array " + conf.write_cnt + "x"); - return test_sequentialWrite(new_imageData()); -}; - -testFunc["arrayBuffer_sequentialWrite"] = function() { - vmessage("write arrayBuffer array " + conf.write_cnt + "x"); - return test_sequentialWrite(new_arrayBuffer()); -}; - -init = function() { - vmessage(">> init"); - - $D('iterations').value = 10; - $D('arraySize').value = 10; - arraySize = parseInt($D('arraySize').value, 10) * 1024; - - message("Browser: " + browser); - - /* Determine browser binary array support */ - try { - ctx = $D('canvas').getContext('2d'); - new_imageData = new_imageData_createImageData; - new_imageData(); - do_imageData = true; - } catch (exc) { - vmessage("createImageData not supported: " + exc); - try { - ctx = $D('canvas').getContext('2d'); - new_imageData = new_imageData_getImageData; - blah = new_imageData(); - do_imageData = true; - } catch (exc) { - vmessage("getImageData not supported: " + exc); - } - } - if (! do_imageData) { - message("imageData arrays not supported"); - } - - try { - new_arrayBuffer(); - do_arrayBuffer = true; - } catch (exc) { - vmessage("Typed Arrays not supported: " + exc); - } - if (! do_arrayBuffer) { - message("Typed Arrays (ArrayBuffers) not suppoted"); - } - vmessage("<< init"); -} diff --git a/tests/base64.html b/tests/base64.html deleted file mode 100644 index dc45fdd5..00000000 --- a/tests/base64.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - Native Base64 Tests - - - - - -

Native Base64 Tests

- -
- Messages:
- - -
- - - diff --git a/tests/base64.js b/tests/base64.js deleted file mode 100644 index 6ade00a3..00000000 --- a/tests/base64.js +++ /dev/null @@ -1,12 +0,0 @@ -// The following results in 'hello [MANGLED]' -// -// Filed as https://github.com/ry/node/issues/issue/402 - -var sys = require("sys"), - buf = new Buffer(1024), len, - str1 = "aGVsbG8g", // 'hello ' - str2 = "d29ybGQ=", // 'world' - -len = buf.write(str1, 0, 'base64'); -len += buf.write(str2, len, 'base64'); -sys.log("decoded result: " + buf.toString('binary', 0, len)); diff --git a/tests/browser.js b/tests/browser.js deleted file mode 100644 index 7cf8279c..00000000 --- a/tests/browser.js +++ /dev/null @@ -1,134 +0,0 @@ -/* - * From: - * http://www.quirksmode.org/js/detect.html - */ - -var Browser = { - init: function () { - this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; - this.version = this.searchVersion(navigator.userAgent) - || this.searchVersion(navigator.appVersion) - || "an unknown version"; - this.majorVersion = this.searchMajorVersion(navigator.userAgent) - || this.searchMajorVersion(navigator.appVersion) - || "an unknown version"; - this.fullVersion = this.searchFullVersion(navigator.userAgent) - || this.searchFullVersion(navigator.appVersion) - || "an unknown version"; - this.OS = this.searchString(this.dataOS) || "an unknown OS"; - }, - searchString: function (data) { - for (var i=0;i - - - Canvas Performance Test - - - - - - - - - Iterations:   - - Width:   - Height:   - -   - -

- - Canvas (should see three squares and two happy faces):
- - Canvas not supported. - - -
- Results:
- - - - - diff --git a/tests/cursor.html b/tests/cursor.html deleted file mode 100644 index 91e621b3..00000000 --- a/tests/cursor.html +++ /dev/null @@ -1,135 +0,0 @@ - - - - Cursor Change test - - - - - - - - -

Roll over the buttons to test cursors

-
- - - -
-
-
- Debug:
- -
-
- - Canvas not supported. - - - - - diff --git a/tests/face.png b/tests/face.png deleted file mode 100644 index 74c30d82..00000000 Binary files a/tests/face.png and /dev/null differ diff --git a/tests/face.png.js b/tests/face.png.js deleted file mode 100644 index e0b5d6ce..00000000 --- a/tests/face.png.js +++ /dev/null @@ -1 +0,0 @@ -var face64 = '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'; diff --git a/tests/input.html b/tests/input.html index 301a7f8e..a261924b 100644 --- a/tests/input.html +++ b/tests/input.html @@ -23,15 +23,15 @@ --> - - - - - - - - - + + + + + + + + + - - - - - - - - - diff --git a/include/playback.js b/tests/playback.js similarity index 97% rename from include/playback.js rename to tests/playback.js index 203576f6..23bddf28 100644 --- a/include/playback.js +++ b/tests/playback.js @@ -36,7 +36,7 @@ enable_test_mode = function () { }; next_iteration = function () { - rfb = new RFB({'target': $D('VNC_canvas'), + rfb = new RFB({'target': document.getElementById('VNC_canvas'), 'onUpdateState': updateState}); enable_test_mode(); diff --git a/tests/run_from_console.casper.js b/tests/run_from_console.casper.js index 6a738a3e..ba8546b9 100644 --- a/tests/run_from_console.casper.js +++ b/tests/run_from_console.casper.js @@ -1,7 +1,7 @@ var Spooky = require('spooky'); var path = require('path'); -var phantom_path = require('phantomjs').path; +var phantom_path = require('phantomjs-prebuilt').path; var casper_path = path.resolve(__dirname, '../node_modules/casperjs/bin/casperjs'); process.env.PHANTOMJS_EXECUTABLE = phantom_path; var casper_opts = { diff --git a/tests/run_from_console.js b/tests/run_from_console.js index 371e861a..1a2b800a 100755 --- a/tests/run_from_console.js +++ b/tests/run_from_console.js @@ -67,7 +67,7 @@ if (all_js && !program.autoInject) { var eol = content.indexOf('\n', ind); var modules = content.slice(ind, eol).split(/,\s*/); modules.forEach(function (mod) { - all_modules[get_path('include/', mod) + '.js'] = 1; + all_modules[get_path('core/', mod) + '.js'] = 1; }); } @@ -92,7 +92,7 @@ if (program.autoInject) { var template = { header: "\n\n\n\n\n
", script_tag: function(p) { return ""; }, - footer: "\n\n" + footer: "\n\n" }; template.header += "\n" + template.script_tag(get_path('node_modules/chai/chai.js')); diff --git a/tests/stats.js b/tests/stats.js deleted file mode 100644 index cd3011cb..00000000 --- a/tests/stats.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Define some useful statistical functions on arrays of numbers - */ - -Array.prototype.sum = function() { - var i, sum = 0; - for (i = 0; i < this.length; i++) { - sum += this[i]; - } - return sum; -} - -Array.prototype.max = function() { - return Math.max.apply(null, this); -} - -Array.prototype.min = function() { - return Math.min.apply(null, this); -} - -Array.prototype.mean = function() { - return this.sum() / this.length; -} -Array.prototype.average = Array.prototype.mean; - -Array.prototype.median = function() { - var sorted = this.sort( function(a,b) { return a-b; }), - len = sorted.length; - if (len % 2) { - return sorted[Math.floor(len / 2)]; // Odd - } else { - return (sorted[len/2 - 1] + sorted[len/2]) / 2; // Even - } -} - -Array.prototype.stdDev = function(sample) { - var i, sumSqr = 0, mean = this.mean(), N; - - if (sample) { - // Population correction if this is a sample - N = this.length - 1; - } else { - // Standard deviation of just the array - N = this.length; - } - - for (i = 0; i < this.length; i++) { - sumSqr += Math.pow(this[i] - mean, 2); - } - - return Math.sqrt(sumSqr / N); -} - diff --git a/tests/test.display.js b/tests/test.display.js index 32a92e22..7c7c693b 100644 --- a/tests/test.display.js +++ b/tests/test.display.js @@ -384,15 +384,15 @@ describe('Display/Canvas Helper', function () { display = new Display({ target: document.createElement('canvas'), prefer_js: false }); display.resize(4, 4); sinon.spy(display, '_scan_renderQ'); - this.old_requestAnimFrame = window.requestAnimFrame; - window.requestAnimFrame = function (cb) { + this.old_requestAnimationFrame = window.requestAnimationFrame; + window.requestAnimationFrame = function (cb) { this.next_frame_cb = cb; }.bind(this); this.next_frame = function () { this.next_frame_cb(); }; }); afterEach(function () { - window.requestAnimFrame = this.old_requestAnimFrame; + window.requestAnimationFrame = this.old_requestAnimationFrame; }); it('should try to process an item when it is pushed on, if nothing else is on the queue', function () { diff --git a/tests/test.helper.js b/tests/test.helper.js index 98009d2a..4982535c 100644 --- a/tests/test.helper.js +++ b/tests/test.helper.js @@ -1,4 +1,4 @@ -// requires local modules: keysym, keysymdef, keyboard +// requires local modules: input/keysym, input/keysymdef, input/util var assert = chai.assert; var expect = chai.expect; @@ -7,18 +7,18 @@ describe('Helpers', function() { "use strict"; describe('keysymFromKeyCode', function() { it('should map known keycodes to keysyms', function() { - expect(kbdUtil.keysymFromKeyCode(0x41, false), 'a').to.be.equal(0x61); - expect(kbdUtil.keysymFromKeyCode(0x41, true), 'A').to.be.equal(0x41); - expect(kbdUtil.keysymFromKeyCode(0xd, false), 'enter').to.be.equal(0xFF0D); - expect(kbdUtil.keysymFromKeyCode(0x11, false), 'ctrl').to.be.equal(0xFFE3); - expect(kbdUtil.keysymFromKeyCode(0x12, false), 'alt').to.be.equal(0xFFE9); - expect(kbdUtil.keysymFromKeyCode(0xe1, false), 'altgr').to.be.equal(0xFE03); - expect(kbdUtil.keysymFromKeyCode(0x1b, false), 'esc').to.be.equal(0xFF1B); - expect(kbdUtil.keysymFromKeyCode(0x26, false), 'up').to.be.equal(0xFF52); + expect(KeyboardUtil.keysymFromKeyCode(0x41, false), 'a').to.be.equal(0x61); + expect(KeyboardUtil.keysymFromKeyCode(0x41, true), 'A').to.be.equal(0x41); + expect(KeyboardUtil.keysymFromKeyCode(0xd, false), 'enter').to.be.equal(0xFF0D); + expect(KeyboardUtil.keysymFromKeyCode(0x11, false), 'ctrl').to.be.equal(0xFFE3); + expect(KeyboardUtil.keysymFromKeyCode(0x12, false), 'alt').to.be.equal(0xFFE9); + expect(KeyboardUtil.keysymFromKeyCode(0xe1, false), 'altgr').to.be.equal(0xFE03); + expect(KeyboardUtil.keysymFromKeyCode(0x1b, false), 'esc').to.be.equal(0xFF1B); + expect(KeyboardUtil.keysymFromKeyCode(0x26, false), 'up').to.be.equal(0xFF52); }); it('should return null for unknown keycodes', function() { - expect(kbdUtil.keysymFromKeyCode(0xc0, false), 'DK æ').to.be.null; - expect(kbdUtil.keysymFromKeyCode(0xde, false), 'DK ø').to.be.null; + expect(KeyboardUtil.keysymFromKeyCode(0xc0, false), 'DK æ').to.be.null; + expect(KeyboardUtil.keysymFromKeyCode(0xde, false), 'DK ø').to.be.null; }); }); @@ -46,59 +46,59 @@ describe('Helpers', function() { describe('substituteCodepoint', function() { it('should replace characters which don\'t have a keysym', function() { - expect(kbdUtil.substituteCodepoint('Ș'.charCodeAt())).to.equal('Ş'.charCodeAt()); - expect(kbdUtil.substituteCodepoint('ș'.charCodeAt())).to.equal('ş'.charCodeAt()); - expect(kbdUtil.substituteCodepoint('Ț'.charCodeAt())).to.equal('Ţ'.charCodeAt()); - expect(kbdUtil.substituteCodepoint('ț'.charCodeAt())).to.equal('ţ'.charCodeAt()); + expect(KeyboardUtil.substituteCodepoint('Ș'.charCodeAt())).to.equal('Ş'.charCodeAt()); + expect(KeyboardUtil.substituteCodepoint('ș'.charCodeAt())).to.equal('ş'.charCodeAt()); + expect(KeyboardUtil.substituteCodepoint('Ț'.charCodeAt())).to.equal('Ţ'.charCodeAt()); + expect(KeyboardUtil.substituteCodepoint('ț'.charCodeAt())).to.equal('ţ'.charCodeAt()); }); it('should pass other characters through unchanged', function() { - expect(kbdUtil.substituteCodepoint('T'.charCodeAt())).to.equal('T'.charCodeAt()); + expect(KeyboardUtil.substituteCodepoint('T'.charCodeAt())).to.equal('T'.charCodeAt()); }); }); describe('nonCharacterKey', function() { it('should recognize the right keys', function() { - expect(kbdUtil.nonCharacterKey({keyCode: 0xd}), 'enter').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0x08}), 'backspace').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0x09}), 'tab').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0x10}), 'shift').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0x11}), 'ctrl').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0x12}), 'alt').to.be.defined; - expect(kbdUtil.nonCharacterKey({keyCode: 0xe0}), 'meta').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0xd}), 'enter').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0x08}), 'backspace').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0x09}), 'tab').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0x10}), 'shift').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0x11}), 'ctrl').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0x12}), 'alt').to.be.defined; + expect(KeyboardUtil.nonCharacterKey({keyCode: 0xe0}), 'meta').to.be.defined; }); it('should not recognize character keys', function() { - expect(kbdUtil.nonCharacterKey({keyCode: 'A'}), 'A').to.be.null; - expect(kbdUtil.nonCharacterKey({keyCode: '1'}), '1').to.be.null; - expect(kbdUtil.nonCharacterKey({keyCode: '.'}), '.').to.be.null; - expect(kbdUtil.nonCharacterKey({keyCode: ' '}), 'space').to.be.null; + expect(KeyboardUtil.nonCharacterKey({keyCode: 'A'}), 'A').to.be.null; + expect(KeyboardUtil.nonCharacterKey({keyCode: '1'}), '1').to.be.null; + expect(KeyboardUtil.nonCharacterKey({keyCode: '.'}), '.').to.be.null; + expect(KeyboardUtil.nonCharacterKey({keyCode: ' '}), 'space').to.be.null; }); }); describe('getKeysym', function() { it('should prefer char', function() { - expect(kbdUtil.getKeysym({char : 'a', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x61); + expect(KeyboardUtil.getKeysym({char : 'a', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x61); }); it('should use charCode if no char', function() { - expect(kbdUtil.getKeysym({char : '', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); - expect(kbdUtil.getKeysym({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); - expect(kbdUtil.getKeysym({char : 'hello', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); + expect(KeyboardUtil.getKeysym({char : '', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); + expect(KeyboardUtil.getKeysym({charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); + expect(KeyboardUtil.getKeysym({char : 'hello', charCode: 'Š'.charCodeAt(), keyCode: 0x42, which: 0x43})).to.have.property('keysym', 0x01a9); }); it('should use keyCode if no charCode', function() { - expect(kbdUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: false})).to.have.property('keysym', 0x62); - expect(kbdUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: true})).to.have.property('keysym', 0x42); + expect(KeyboardUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: false})).to.have.property('keysym', 0x62); + expect(KeyboardUtil.getKeysym({keyCode: 0x42, which: 0x43, shiftKey: true})).to.have.property('keysym', 0x42); }); it('should use which if no keyCode', function() { - expect(kbdUtil.getKeysym({which: 0x43, shiftKey: false})).to.have.property('keysym', 0x63); - expect(kbdUtil.getKeysym({which: 0x43, shiftKey: true})).to.have.property('keysym', 0x43); + expect(KeyboardUtil.getKeysym({which: 0x43, shiftKey: false})).to.have.property('keysym', 0x63); + expect(KeyboardUtil.getKeysym({which: 0x43, shiftKey: true})).to.have.property('keysym', 0x43); }); it('should substitute where applicable', function() { - expect(kbdUtil.getKeysym({char : 'Ș'})).to.have.property('keysym', 0x1aa); + expect(KeyboardUtil.getKeysym({char : 'Ș'})).to.have.property('keysym', 0x1aa); }); }); describe('Modifier Sync', function() { // return a list of fake events necessary to fix modifier state describe('Toggle all modifiers', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it ('should do nothing if all modifiers are up as expected', function() { expect(sync.keydown({ keyCode: 0x41, @@ -141,7 +141,7 @@ describe('Helpers', function() { }); }); describe('Toggle Ctrl', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it('should sync if modifier is suddenly down', function() { expect(sync.keydown({ keyCode: 0x41, @@ -156,7 +156,7 @@ describe('Helpers', function() { }); }); describe('Toggle Alt', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it('should sync if modifier is suddenly down', function() { expect(sync.keydown({ keyCode: 0x41, @@ -171,7 +171,7 @@ describe('Helpers', function() { }); }); describe('Toggle AltGr', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it('should sync if modifier is suddenly down', function() { expect(sync.keydown({ keyCode: 0x41, @@ -186,7 +186,7 @@ describe('Helpers', function() { }); }); describe('Toggle Shift', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it('should sync if modifier is suddenly down', function() { expect(sync.keydown({ keyCode: 0x41, @@ -201,7 +201,7 @@ describe('Helpers', function() { }); }); describe('Toggle Meta', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); it('should sync if modifier is suddenly down', function() { expect(sync.keydown({ keyCode: 0x41, @@ -217,17 +217,17 @@ describe('Helpers', function() { }); describe('Modifier keyevents', function() { it('should not sync a modifier on its own events', function() { - expect(kbdUtil.ModifierSync().keydown({ + expect(KeyboardUtil.ModifierSync().keydown({ keyCode: 0x11, ctrlKey: false })).to.be.deep.equal([]); - expect(kbdUtil.ModifierSync().keydown({ + expect(KeyboardUtil.ModifierSync().keydown({ keyCode: 0x11, ctrlKey: true }), 'B').to.be.deep.equal([]); }) it('should update state on modifier keyevents', function() { - var sync = kbdUtil.ModifierSync(); + var sync = KeyboardUtil.ModifierSync(); sync.keydown({ keyCode: 0x11, }); @@ -237,7 +237,7 @@ describe('Helpers', function() { })).to.be.deep.equal([]); }); it('should sync other modifiers on ctrl events', function() { - expect(kbdUtil.ModifierSync().keydown({ + expect(KeyboardUtil.ModifierSync().keydown({ keyCode: 0x11, altKey: true })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keydown'}]); @@ -245,17 +245,17 @@ describe('Helpers', function() { }); describe('sync modifiers on non-key events', function() { it('should generate sync events when receiving non-keyboard events', function() { - expect(kbdUtil.ModifierSync().syncAny({ + expect(KeyboardUtil.ModifierSync().syncAny({ altKey: true })).to.be.deep.equal([{keysym: keysyms.lookup(0xffe9), type: 'keydown'}]); }); }); describe('do not treat shift as a modifier key', function() { it('should not treat shift as a shortcut modifier', function() { - expect(kbdUtil.hasShortcutModifier([], {0xffe1 : true})).to.be.false; + expect(KeyboardUtil.hasShortcutModifier([], {0xffe1 : true})).to.be.false; }); it('should not treat shift as a char modifier', function() { - expect(kbdUtil.hasCharModifier([], {0xffe1 : true})).to.be.false; + expect(KeyboardUtil.hasCharModifier([], {0xffe1 : true})).to.be.false; }); }); }); diff --git a/tests/test.keyboard.js b/tests/test.keyboard.js index 2ac65af3..0019be9a 100644 --- a/tests/test.keyboard.js +++ b/tests/test.keyboard.js @@ -1,4 +1,4 @@ -// requires local modules: input, keyboard, keysymdef +// requires local modules: input/devices, input/util, input/keysymdef, input/keysym var assert = chai.assert; var expect = chai.expect; @@ -7,19 +7,19 @@ describe('Key Event Pipeline Stages', function() { "use strict"; describe('Decode Keyboard Events', function() { it('should pass events to the next stage', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.an.object; done(); }).keydown({keyCode: 0x41}); }); it('should pass the right keysym through', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt.keysym).to.be.deep.equal(keysyms.lookup(0x61)); done(); }).keypress({keyCode: 0x41}); }); it('should pass the right keyid through', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.have.property('keyId', 0x41); done(); }).keydown({keyCode: 0x41}); @@ -27,14 +27,14 @@ describe('Key Event Pipeline Stages', function() { it('should not sync modifiers on a keypress', function() { // Firefox provides unreliable modifier state on keypress events var count = 0; - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { ++count; }).keypress({keyCode: 0x41, ctrlKey: true}); expect(count).to.be.equal(1); }); it('should sync modifiers if necessary', function(done) { var count = 0; - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { switch (count) { case 0: // fake a ctrl keydown expect(evt).to.be.deep.equal({keysym: keysyms.lookup(0xffe3), type: 'keydown'}); @@ -48,26 +48,26 @@ describe('Key Event Pipeline Stages', function() { }).keydown({keyCode: 0x41, ctrlKey: true}); }); it('should forward keydown events with the right type', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, type: 'keydown'}); done(); }).keydown({keyCode: 0x41}); }); it('should forward keyup events with the right type', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keyup'}); done(); }).keyup({keyCode: 0x41}); }); it('should forward keypress events with the right type', function(done) { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keypress'}); done(); }).keypress({keyCode: 0x41}); }); it('should generate stalls if a char modifier is down while a key is pressed', function(done) { var count = 0; - KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) { switch (count) { case 0: // fake altgr expect(evt).to.be.deep.equal({keysym: keysyms.lookup(0xfe03), type: 'keydown'}); @@ -92,7 +92,7 @@ describe('Key Event Pipeline Stages', function() { }); describe('suppress the right events at the right time', function() { it('should suppress anything while a shortcut modifier is down', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {}); obj.keydown({keyCode: 0x11}); // press ctrl expect(obj.keydown({keyCode: 'A'.charCodeAt()})).to.be.true; @@ -102,7 +102,7 @@ describe('Key Event Pipeline Stages', function() { expect(obj.keydown({keyCode: 0xde})).to.be.true; // Ø key on DK }); it('should suppress non-character keys', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {}); expect(obj.keydown({keyCode: 0x08}), 'a').to.be.true; expect(obj.keydown({keyCode: 0x09}), 'b').to.be.true; @@ -110,20 +110,20 @@ describe('Key Event Pipeline Stages', function() { expect(obj.keydown({keyCode: 0x12}), 'e').to.be.true; }); it('should not suppress shift', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {}); expect(obj.keydown({keyCode: 0x10}), 'd').to.be.false; }); it('should generate event for shift keydown', function() { var called = false; - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.have.property('keysym'); called = true; }).keydown({keyCode: 0x10}); expect(called).to.be.true; }); it('should not suppress character keys', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {}); expect(obj.keydown({keyCode: 'A'.charCodeAt()})).to.be.false; expect(obj.keydown({keyCode: ' '.charCodeAt()})).to.be.false; @@ -132,7 +132,7 @@ describe('Key Event Pipeline Stages', function() { expect(obj.keydown({keyCode: 0xde})).to.be.false; // Ø key on DK }); it('should not suppress if a char modifier is down', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) {}); obj.keydown({keyCode: 0xe1}); // press altgr expect(obj.keydown({keyCode: 'A'.charCodeAt()})).to.be.false; @@ -144,7 +144,7 @@ describe('Key Event Pipeline Stages', function() { }); describe('Keypress and keyup events', function() { it('should always suppress event propagation', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) {}); + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) {}); expect(obj.keypress({keyCode: 'A'.charCodeAt()})).to.be.true; expect(obj.keypress({keyCode: 0x3c})).to.be.true; // < key on DK Windows @@ -155,7 +155,7 @@ describe('Key Event Pipeline Stages', function() { expect(obj.keyup({keyCode: 0x11})).to.be.true; }); it('should never generate stalls', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt.type).to.not.be.equal('stall'); }); @@ -171,7 +171,7 @@ describe('Key Event Pipeline Stages', function() { describe('mark events if a char modifier is down', function() { it('should not mark modifiers on a keydown event', function() { var times_called = 0; - var obj = KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) { switch (times_called++) { case 0: //altgr break; @@ -187,7 +187,7 @@ describe('Key Event Pipeline Stages', function() { it('should indicate on events if a single-key char modifier is down', function(done) { var times_called = 0; - var obj = KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) { switch (times_called++) { case 0: //altgr break; @@ -208,7 +208,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should indicate on events if a multi-key char modifier is down', function(done) { var times_called = 0; - var obj = KeyEventDecoder(kbdUtil.ModifierSync([0xffe9, 0xffe3]), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xffe9, 0xffe3]), function(evt) { switch (times_called++) { case 0: //ctrl break; @@ -231,7 +231,7 @@ describe('Key Event Pipeline Stages', function() { obj.keypress({keyCode: 'A'.charCodeAt()}); }); it('should not consider a char modifier to be down on the modifier key itself', function() { - var obj = KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) { + var obj = KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) { expect(evt).to.not.have.property('escape'); }); @@ -241,13 +241,13 @@ describe('Key Event Pipeline Stages', function() { }); describe('add/remove keysym', function() { it('should remove keysym from keydown if a char key and no modifier', function() { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, type: 'keydown'}); }).keydown({keyCode: 0x41}); }); it('should not remove keysym from keydown if a shortcut modifier is down', function() { var times_called = 0; - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { switch (times_called++) { case 1: expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keydown'}); @@ -258,7 +258,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should not remove keysym from keydown if a char modifier is down', function() { var times_called = 0; - KeyEventDecoder(kbdUtil.ModifierSync([0xfe03]), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync([0xfe03]), function(evt) { switch (times_called++) { case 2: expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keydown'}); @@ -268,21 +268,21 @@ describe('Key Event Pipeline Stages', function() { expect(times_called).to.be.equal(3); }); it('should not remove keysym from keydown if key is noncharacter', function() { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt, 'bacobjpace').to.be.deep.equal({keyId: 0x09, keysym: keysyms.lookup(0xff09), type: 'keydown'}); }).keydown({keyCode: 0x09}); - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt, 'ctrl').to.be.deep.equal({keyId: 0x11, keysym: keysyms.lookup(0xffe3), type: 'keydown'}); }).keydown({keyCode: 0x11}); }); it('should never remove keysym from keypress', function() { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keypress'}); }).keypress({keyCode: 0x41}); }); it('should never remove keysym from keyup', function() { - KeyEventDecoder(kbdUtil.ModifierSync(), function(evt) { + KeyboardUtil.KeyEventDecoder(KeyboardUtil.ModifierSync(), function(evt) { expect(evt).to.be.deep.equal({keyId: 0x41, keysym: keysyms.lookup(0x61), type: 'keyup'}); }).keyup({keyCode: 0x41}); }); @@ -293,25 +293,25 @@ describe('Key Event Pipeline Stages', function() { describe('Verify that char modifiers are active', function() { it('should pass keydown events through if there is no stall', function(done) { - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ expect(evt).to.deep.equal({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x41)}); done(); })({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x41)}); }); it('should pass keyup events through if there is no stall', function(done) { - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ expect(evt).to.deep.equal({type: 'keyup', keyId: 0x41, keysym: keysyms.lookup(0x41)}); done(); })({type: 'keyup', keyId: 0x41, keysym: keysyms.lookup(0x41)}); }); it('should pass keypress events through if there is no stall', function(done) { - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ expect(evt).to.deep.equal({type: 'keypress', keyId: 0x41, keysym: keysyms.lookup(0x41)}); done(); })({type: 'keypress', keyId: 0x41, keysym: keysyms.lookup(0x41)}); }); it('should not pass stall events through', function(done){ - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ // should only be called once, for the keydown expect(evt).to.deep.equal({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x41)}); done(); @@ -322,7 +322,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should merge keydown and keypress events if they come after a stall', function(done) { var next_called = false; - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ // should only be called once, for the keydown expect(next_called).to.be.false; next_called = true; @@ -337,7 +337,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should preserve modifier attribute when merging if keysyms differ', function(done) { var next_called = false; - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ // should only be called once, for the keydown expect(next_called).to.be.false; next_called = true; @@ -351,7 +351,7 @@ describe('Key Event Pipeline Stages', function() { expect(next_called).to.be.false; }); it('should not preserve modifier attribute when merging if keysyms are the same', function() { - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ expect(evt).to.not.have.property('escape'); }); @@ -361,7 +361,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should not merge keydown and keypress events if there is no stall', function(done) { var times_called = 0; - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ switch(times_called) { case 0: expect(evt).to.deep.equal({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x42)}); @@ -380,7 +380,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should not merge keydown and keypress events if separated by another event', function(done) { var times_called = 0; - var obj = VerifyCharModifier(function(evt){ + var obj = KeyboardUtil.VerifyCharModifier(function(evt){ switch(times_called) { case 0: expect(evt,1).to.deep.equal({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x42)}); @@ -406,7 +406,7 @@ describe('Key Event Pipeline Stages', function() { describe('Track Key State', function() { it('should do nothing on keyup events if no keys are down', function() { - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { expect(true).to.be.false; }); obj({type: 'keyup', keyId: 0x41}); @@ -415,7 +415,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -443,7 +443,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -472,7 +472,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -504,7 +504,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -540,7 +540,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -573,7 +573,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -608,7 +608,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -644,7 +644,7 @@ describe('Key Event Pipeline Stages', function() { var times_called = 0; var elem = null; var keysymsdown = {}; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; if (elem.type == 'keyup') { expect(evt).to.have.property('keysym'); @@ -676,7 +676,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should pop matching key event on keyup', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { switch (times_called++) { case 0: case 1: @@ -697,7 +697,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should pop the first zero keyevent on keyup with zero keyId', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { switch (times_called++) { case 0: case 1: @@ -718,7 +718,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should pop the last keyevents keysym if no match is found for keyId', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { switch (times_called++) { case 0: case 1: @@ -740,7 +740,7 @@ describe('Key Event Pipeline Stages', function() { describe('Firefox sends keypress even when keydown is suppressed', function() { it('should discard the keypress', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { expect(times_called).to.be.equal(0); ++times_called; }); @@ -753,7 +753,7 @@ describe('Key Event Pipeline Stages', function() { describe('releaseAll', function() { it('should do nothing if no keys have been pressed', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { ++times_called; }); obj({type: 'releaseall'}); @@ -761,7 +761,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should release the keys that have been pressed', function() { var times_called = 0; - var obj = TrackKeyState(function(evt) { + var obj = KeyboardUtil.TrackKeyState(function(evt) { switch (times_called++) { case 2: expect(evt).to.be.deep.equal({type: 'keyup', keyId: 0, keysym: keysyms.lookup(0x41)}); @@ -787,7 +787,7 @@ describe('Key Event Pipeline Stages', function() { describe('Keydown', function() { it('should pass through when a char modifier is not down', function() { var times_called = 0; - EscapeModifiers(function(evt) { + KeyboardUtil.EscapeModifiers(function(evt) { expect(times_called).to.be.equal(0); ++times_called; expect(evt).to.be.deep.equal({type: 'keydown', keyId: 0x41, keysym: keysyms.lookup(0x42)}); @@ -796,7 +796,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should generate fake undo/redo events when a char modifier is down', function() { var times_called = 0; - EscapeModifiers(function(evt) { + KeyboardUtil.EscapeModifiers(function(evt) { switch(times_called++) { case 0: expect(evt).to.be.deep.equal({type: 'keyup', keyId: 0, keysym: keysyms.lookup(0xffe9)}); @@ -821,7 +821,7 @@ describe('Key Event Pipeline Stages', function() { describe('Keyup', function() { it('should pass through when a char modifier is down', function() { var times_called = 0; - EscapeModifiers(function(evt) { + KeyboardUtil.EscapeModifiers(function(evt) { expect(times_called).to.be.equal(0); ++times_called; expect(evt).to.be.deep.equal({type: 'keyup', keyId: 0x41, keysym: keysyms.lookup(0x42), escape: [0xfe03]}); @@ -830,7 +830,7 @@ describe('Key Event Pipeline Stages', function() { }); it('should pass through when a char modifier is not down', function() { var times_called = 0; - EscapeModifiers(function(evt) { + KeyboardUtil.EscapeModifiers(function(evt) { expect(times_called).to.be.equal(0); ++times_called; expect(evt).to.be.deep.equal({type: 'keyup', keyId: 0x41, keysym: keysyms.lookup(0x42)}); diff --git a/tests/test.rfb.js b/tests/test.rfb.js index 06eeebe3..3d856faf 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -1,4 +1,4 @@ -// requires local modules: util, websock, rfb, keyboard, keysym, keysymdef, input, inflator, des, display +// requires local modules: util, websock, rfb, input/util, input/keysym, input/keysymdef, input/devices, inflator, des, display // requires test modules: fake.websocket, assertions /* jshint expr: true */ var assert = chai.assert; @@ -13,6 +13,25 @@ function make_rfb (extra_opts) { return new RFB(extra_opts); } +var push8 = function (arr, num) { + "use strict"; + arr.push(num & 0xFF); +}; + +var push16 = function (arr, num) { + "use strict"; + arr.push((num >> 8) & 0xFF, + num & 0xFF); +}; + +var push32 = function (arr, num) { + "use strict"; + arr.push((num >> 24) & 0xFF, + (num >> 16) & 0xFF, + (num >> 8) & 0xFF, + num & 0xFF); +}; + describe('Remote Frame Buffer Protocol Client', function() { "use strict"; before(FakeWebSocket.replace); @@ -232,17 +251,17 @@ describe('Remote Frame Buffer Protocol Client', function() { it('should send the request with the given width and height', function () { var expected = [251]; - expected.push8(0); // padding - expected.push16(1); // width - expected.push16(2); // height - expected.push8(1); // number-of-screens - expected.push8(0); // padding before screen array - expected.push32(0); // id - expected.push16(0); // x-position - expected.push16(0); // y-position - expected.push16(1); // width - expected.push16(2); // height - expected.push32(0); // flags + push8(expected, 0); // padding + push16(expected, 1); // width + push16(expected, 2); // height + push8(expected, 1); // number-of-screens + push8(expected, 0); // padding before screen array + push32(expected, 0); // id + push16(expected, 0); // x-position + push16(expected, 0); // y-position + push16(expected, 1); // width + push16(expected, 2); // height + push32(expected, 0); // flags client.requestDesktopSize(1, 2); expect(client._sock).to.have.sent(new Uint8Array(expected)); @@ -662,7 +681,7 @@ describe('Remote Frame Buffer Protocol Client', function() { var err_msg = "Whoopsies"; var data = [0, 0, 0, 0]; var err_len = err_msg.length; - data.push32(err_len); + push32(data, err_len); for (var i = 0; i < err_len; i++) { data.push(err_msg.charCodeAt(i)); } @@ -796,10 +815,10 @@ describe('Remote Frame Buffer Protocol Client', function() { function send_num_str_pairs(pairs, client) { var pairs_len = pairs.length; var data = []; - data.push32(pairs_len); + push32(data, pairs_len); for (var i = 0; i < pairs_len; i++) { - data.push32(pairs[i][0]); + push32(data, pairs[i][0]); var j; for (j = 0; j < 4; j++) { data.push(pairs[i][1].charCodeAt(j)); @@ -948,30 +967,30 @@ describe('Remote Frame Buffer Protocol Client', function() { } var data = []; - data.push16(full_opts.width); - data.push16(full_opts.height); + push16(data, full_opts.width); + push16(data, full_opts.height); data.push(full_opts.bpp); data.push(full_opts.depth); data.push(full_opts.big_endian); data.push(full_opts.true_color); - data.push16(full_opts.red_max); - data.push16(full_opts.green_max); - data.push16(full_opts.blue_max); - data.push8(full_opts.red_shift); - data.push8(full_opts.green_shift); - data.push8(full_opts.blue_shift); + push16(data, full_opts.red_max); + push16(data, full_opts.green_max); + push16(data, full_opts.blue_max); + push8(data, full_opts.red_shift); + push8(data, full_opts.green_shift); + push8(data, full_opts.blue_shift); // padding - data.push8(0); - data.push8(0); - data.push8(0); + push8(data, 0); + push8(data, 0); + push8(data, 0); client._sock._websocket._receive_data(new Uint8Array(data)); var name_data = []; - name_data.push32(full_opts.name.length); + push32(name_data, full_opts.name.length); for (var i = 0; i < full_opts.name.length; i++) { name_data.push(full_opts.name.charCodeAt(i)); } @@ -1003,10 +1022,10 @@ describe('Remote Frame Buffer Protocol Client', function() { send_server_init({}, client); var tight_data = []; - tight_data.push16(1); - tight_data.push16(2); - tight_data.push16(3); - tight_data.push16(0); + push16(tight_data, 1); + push16(tight_data, 2); + push16(tight_data, 3); + push16(tight_data, 0); for (var i = 0; i < 16 + 32 + 48; i++) { tight_data.push(i); } @@ -1136,16 +1155,16 @@ describe('Remote Frame Buffer Protocol Client', function() { // header data.push(0); // msg type data.push(0); // padding - data.push16(rect_cnt || rect_data.length); + push16(data, rect_cnt || rect_data.length); } for (var i = 0; i < rect_data.length; i++) { if (rect_info[i]) { - data.push16(rect_info[i].x); - data.push16(rect_info[i].y); - data.push16(rect_info[i].width); - data.push16(rect_info[i].height); - data.push32(rect_info[i].encoding); + push16(data, rect_info[i].x); + push16(data, rect_info[i].y); + push16(data, rect_info[i].width); + push16(data, rect_info[i].height); + push32(data, rect_info[i].encoding); } data = data.concat(rect_data[i]); } @@ -1339,24 +1358,24 @@ describe('Remote Frame Buffer Protocol Client', function() { it('should handle the RRE encoding', function () { var info = [{ x: 0, y: 0, width: 4, height: 4, encoding: 0x02 }]; var rect = []; - rect.push32(2); // 2 subrects - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 2); // 2 subrects + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color rect.push(0xff); // becomes ff0000ff --> #0000FF color rect.push(0x00); rect.push(0x00); rect.push(0xff); - rect.push16(0); // x: 0 - rect.push16(0); // y: 0 - rect.push16(2); // width: 2 - rect.push16(2); // height: 2 + push16(rect, 0); // x: 0 + push16(rect, 0); // y: 0 + push16(rect, 2); // width: 2 + push16(rect, 2); // height: 2 rect.push(0xff); // becomes ff0000ff --> #0000FF color rect.push(0x00); rect.push(0x00); rect.push(0xff); - rect.push16(2); // x: 2 - rect.push16(2); // y: 2 - rect.push16(2); // width: 2 - rect.push16(2); // height: 2 + push16(rect, 2); // x: 2 + push16(rect, 2); // y: 2 + push16(rect, 2); // width: 2 + push16(rect, 2); // height: 2 send_fbu_msg(info, [rect], client); expect(client._display).to.have.displayed(target_data_check); @@ -1384,7 +1403,7 @@ describe('Remote Frame Buffer Protocol Client', function() { var info = [{ x: 0, y: 0, width: 4, height: 4, encoding: 0x05 }]; var rect = []; rect.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color rect.push(0xff); // becomes ff0000ff --> #0000FF fg color rect.push(0x00); rect.push(0x00); @@ -1416,11 +1435,11 @@ describe('Remote Frame Buffer Protocol Client', function() { var info = [{ x: 0, y: 0, width: 4, height: 4, encoding: 0x05 }]; var rect = []; rect.push(0x02); - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color send_fbu_msg(info, [rect], client); var expected = []; - for (var i = 0; i < 16; i++) { expected.push32(0xff00ff); } + for (var i = 0; i < 16; i++) { push32(expected, 0xff00ff); } expect(client._display).to.have.displayed(new Uint8Array(expected)); }); @@ -1436,7 +1455,7 @@ describe('Remote Frame Buffer Protocol Client', function() { // send a bg frame rect.push(0x02); - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color // send an empty frame rect.push(0x00); @@ -1445,8 +1464,8 @@ describe('Remote Frame Buffer Protocol Client', function() { 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 + for (i = 0; i < 16; i++) { push32(expected, 0xff00ff); } // rect 1: solid + for (i = 0; i < 16; i++) { push32(expected, 0xff00ff); } // rect 2: same bkground color expect(client._display).to.have.displayed(new Uint8Array(expected)); }); @@ -1454,7 +1473,7 @@ describe('Remote Frame Buffer Protocol Client', function() { var info = [{ x: 0, y: 0, width: 4, height: 4, encoding: 0x05 }]; var rect = []; rect.push(0x02 | 0x08 | 0x10); // bg spec, anysubrects, colouredsubrects - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color rect.push(2); // 2 subrects rect.push(0xff); // becomes ff0000ff --> #0000FF fg color rect.push(0x00); @@ -1480,7 +1499,7 @@ describe('Remote Frame Buffer Protocol Client', function() { var info = [{ x: 0, y: 0, width: 4, height: 17, encoding: 0x05}]; var rect = []; rect.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects - rect.push32(0xff00ff); // becomes 00ff00ff --> #00FF00 bg color + push32(rect, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color rect.push(0xff); // becomes ff0000ff --> #0000FF fg color rect.push(0x00); rect.push(0x00); @@ -1561,16 +1580,16 @@ describe('Remote Frame Buffer Protocol Client', function() { function make_screen_data (nr_of_screens) { var data = []; - data.push8(nr_of_screens); // number-of-screens - data.push8(0); // padding - data.push16(0); // padding + push8(data, nr_of_screens); // number-of-screens + push8(data, 0); // padding + push16(data, 0); // padding for (var i=0; i - - Viewport Test - - - - - -
-
- Canvas: - -
-
-
- - Canvas not supported. - -
-
-
-
- Results:
- -
-
- - - - - - - - - - - - diff --git a/tests/vnc_perf.html b/tests/vnc_perf.html index 62f749c1..098575be 100644 --- a/tests/vnc_perf.html +++ b/tests/vnc_perf.html @@ -31,17 +31,17 @@ - - + + diff --git a/tests/vnc_playback.html b/tests/vnc_playback.html index c4d2108e..b8f9eb19 100644 --- a/tests/vnc_playback.html +++ b/tests/vnc_playback.html @@ -33,24 +33,24 @@ - - + + diff --git a/utils/make-module-transform.js b/utils/make-module-transform.js new file mode 100644 index 00000000..bb48ae50 --- /dev/null +++ b/utils/make-module-transform.js @@ -0,0 +1,25 @@ +var through = require('through2'); + +var singleLineRe = /\/\* \[module\] ((.(?!\*\/))+) \*\//g; +var multiLineRe = /\/\* \[module\]\n(( * .+\n)+) \*\//g; + +var skipAsModule = /\/\* \[begin skip-as-module\] \*\/(.|\n)+\/\* \[end skip-as-module\] \*\//g; + +module.exports = function (file) { + var stream = through(function (buf, enc, next) { + var bufStr = buf.toString('utf8'); + bufStr = bufStr.replace(singleLineRe, "$1"); + bufStr = bufStr.replace(multiLineRe, function (match, mainLines) { + return mainLines.split(" * ").join(""); + }); + + bufStr = bufStr.replace(skipAsModule, ""); + + this.push(bufStr); + next(); + }); + + stream._is_make_module = true; + + return stream; +}; diff --git a/utils/use_require.js b/utils/use_require.js new file mode 100755 index 00000000..e48c9e7b --- /dev/null +++ b/utils/use_require.js @@ -0,0 +1,121 @@ +#!/usr/bin/env node + +var path = require('path'); +var program = require('commander'); +var fs = require('fs'); +var fse = require('fs-extra'); +var browserify = require('browserify'); + +var make_modules_transform = require('./make-module-transform'); +var babelify = require("babelify"); + + +program + .option('-b, --browserify', 'create a browserify bundled app') + .option('--as-require', 'output files using "require" instead of ES6 import and export') + .parse(process.argv); + +// the various important paths +var core_path = path.resolve(__dirname, '..', 'core'); +var app_path = path.resolve(__dirname, '..', 'app'); +var out_dir_base = path.resolve(__dirname, '..', 'build'); +var lib_dir_base = path.resolve(__dirname, '..', 'lib'); + +var make_browserify = function (src_files, opts) { + // change to the root noVNC directory + process.chdir(path.resolve(__dirname, '..')); + + var b = browserify(src_files, opts); + + // register the transforms + b.transform(make_modules_transform); + b.transform(babelify, + { plugins: ["add-module-exports", "transform-es2015-modules-commonjs"] }); + + return b; +}; + +var make_full_app = function () { + // make sure the output directory exists + fse.ensureDir(out_dir_base); + + // actually bundle the files into a browserified bundled + var ui_file = path.join(app_path, 'ui.js'); + var b = make_browserify(ui_file, {}); + var app_file = path.join(out_dir_base, 'app.js'); + b.bundle().pipe(fs.createWriteStream(app_file)); + + // copy over app-related resources (images, styles, etc) + var src_dir_app = path.join(__dirname, '..', 'app'); + fs.readdir(src_dir_app, function (err, files) { + if (err) { throw err; } + + files.forEach(function (src_file) { + var src_file_path = path.resolve(src_dir_app, src_file); + var out_file_path = path.resolve(out_dir_base, src_file); + var ext = path.extname(src_file); + if (ext === '.js' || ext === '.html') return; + fse.copy(src_file_path, out_file_path, function (err) { + if (err) { throw err; } + console.log("Copied file(s) from " + src_file_path + " to " + out_file_path); + }); + }); + }); + + // write out the modified vnc.html file that works with the bundle + var src_html_path = path.resolve(__dirname, '..', 'vnc.html'); + var out_html_path = path.resolve(out_dir_base, 'vnc.html'); + fs.readFile(src_html_path, function (err, contents_raw) { + if (err) { throw err; } + + var contents = contents_raw.toString(); + contents = contents.replace(/="app\//g, '="'); + + var start_marker = '\n'; + var end_marker = ''; + var start_ind = contents.indexOf(start_marker) + start_marker.length; + var end_ind = contents.indexOf(end_marker, start_ind); + + contents = contents.slice(0, start_ind) + '\n' + contents.slice(end_ind); + + fs.writeFile(out_html_path, contents, function (err) { + if (err) { throw err; } + console.log("Wrote " + out_html_path); + }); + }); +}; + +var make_lib_files = function (use_require) { + // make sure the output directory exists + fse.ensureDir(lib_dir_base); + + var through = require('through2'); + + var deps = {}; + var rfb_file = path.join(core_path, 'rfb.js'); + var b = make_browserify(rfb_file, {}); + b.on('transform', function (tr, file) { + if (tr._is_make_module) { + var new_path = path.join(lib_dir_base, path.relative(core_path, file)); + fse.ensureDir(path.dirname(new_path)); + console.log("Writing " + new_path) + var fileStream = fs.createWriteStream(new_path); + + if (use_require) { + var babelificate = babelify(file, + { plugins: ["add-module-exports", "transform-es2015-modules-commonjs"] }); + tr.pipe(babelificate); + tr = babelificate; + } + tr.pipe(fileStream); + } + }); + + b.bundle(); +}; + +if (program.browserify) { + make_full_app(); +} else { + make_lib_files(program.asRequire); +} diff --git a/vnc.html b/vnc.html index 0b653065..b33b704e 100644 --- a/vnc.html +++ b/vnc.html @@ -27,18 +27,18 @@ - + - + - - - + + +
-
- - - - -
- - - - - - -
@@ -218,8 +218,11 @@
- - + + + + + diff --git a/vnc_auto.html b/vnc_auto.html index 597028e7..a3c5dc9c 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -27,22 +27,23 @@ - + - + - + - + + @@ -77,10 +78,11 @@ "use strict"; // Load supporting scripts - Util.load_scripts(["webutil.js", "base64.js", "websock.js", "des.js", - "keysymdef.js", "xtscancodes.js", "keyboard.js", - "input.js", "display.js", "inflator.js", "rfb.js", - "keysym.js"]); + WebUtil.load_scripts({ + 'core': ["base64.js", "websock.js", "des.js", "input/keysymdef.js", + "input/xtscancodes.js", "input/util.js", "input/devices.js", + "display.js", "inflator.js", "rfb.js", "input/keysym.js"], + 'app': ["webutil.js"]}); var rfb; var resizeTimeout; @@ -90,7 +92,7 @@ if (WebUtil.getConfigVar('resize', false)) { var innerW = window.innerWidth; var innerH = window.innerHeight; - var controlbarH = $D('noVNC_status_bar').offsetHeight; + var controlbarH = document.getElementById('noVNC_status_bar').offsetHeight; var padding = 5; if (innerW !== undefined && innerH !== undefined) rfb.requestDesktopSize(innerW, innerH - controlbarH - padding); @@ -107,11 +109,11 @@ msg += 'Password Required: '; msg += ''; msg += '<\/form>'; - $D('noVNC_status_bar').setAttribute("class", "noVNC_status_warn"); - $D('noVNC_status').innerHTML = msg; + document.getElementById('noVNC_status_bar').setAttribute("class", "noVNC_status_warn"); + document.getElementById('noVNC_status').innerHTML = msg; } function setPassword() { - rfb.sendPassword($D('password_input').value); + rfb.sendPassword(document.getElementById('password_input').value); return false; } function sendCtrlAltDel() { @@ -132,9 +134,9 @@ } function updateState(rfb, state, oldstate, msg) { var s, sb, cad, level; - s = $D('noVNC_status'); - sb = $D('noVNC_status_bar'); - cad = $D('sendCtrlAltDelButton'); + s = document.getElementById('noVNC_status'); + sb = document.getElementById('noVNC_status_bar'); + cad = document.getElementById('sendCtrlAltDelButton'); switch (state) { case 'failed': level = "error"; break; case 'fatal': level = "error"; break; @@ -169,7 +171,7 @@ function xvpInit(ver) { var xvpbuttons; - xvpbuttons = $D('noVNC_xvp_buttons'); + xvpbuttons = document.getElementById('noVNC_xvp_buttons'); if (ver >= 1) { xvpbuttons.style.display = 'inline'; } else { @@ -180,11 +182,11 @@ window.onscriptsload = function () { var host, port, password, path, token; - $D('sendCtrlAltDelButton').style.display = "inline"; - $D('sendCtrlAltDelButton').onclick = sendCtrlAltDel; - $D('xvpShutdownButton').onclick = xvpShutdown; - $D('xvpRebootButton').onclick = xvpReboot; - $D('xvpResetButton').onclick = xvpReset; + document.getElementById('sendCtrlAltDelButton').style.display = "inline"; + document.getElementById('sendCtrlAltDelButton').onclick = sendCtrlAltDel; + document.getElementById('xvpShutdownButton').onclick = xvpShutdown; + document.getElementById('xvpRebootButton').onclick = xvpReboot; + document.getElementById('xvpResetButton').onclick = xvpReset; WebUtil.init_logging(WebUtil.getConfigVar('logging', 'warn')); document.title = unescape(WebUtil.getConfigVar('title', 'noVNC')); @@ -223,7 +225,7 @@ } try { - rfb = new RFB({'target': $D('noVNC_canvas'), + rfb = new RFB({'target': document.getElementById('noVNC_canvas'), 'encrypt': WebUtil.getConfigVar('encrypt', (window.location.protocol === "https:")), 'repeaterID': WebUtil.getConfigVar('repeaterID', ''),