diff options
author | samhed <samuel@cendio.se> | 2016-06-03 10:46:05 +0200 |
---|---|---|
committer | samhed <samuel@cendio.se> | 2016-06-03 10:46:05 +0200 |
commit | 5fd3f88e50f8f18422b0692733a302bb6fb9b7e0 (patch) | |
tree | 4f187f42ba433b6c928e144a1a213d54509f02cc | |
parent | ae11605141f345d38bf1e5fcf8fb85c42c771145 (diff) | |
parent | a1dbbcc1a71ca88a7e3e2fd0e47362744b69c265 (diff) | |
download | novnc-5fd3f88e50f8f18422b0692733a302bb6fb9b7e0.tar.gz |
Merge branch 'ui-cleanup' of https://github.com/kanaka/noVNC
-rw-r--r-- | images/toggleextrakeys.png (renamed from images/showextrakeys.png) | bin | 735 -> 735 bytes | |||
-rw-r--r-- | include/base.css | 63 | ||||
-rw-r--r-- | include/black.css | 2 | ||||
-rw-r--r-- | include/blue.css | 2 | ||||
-rw-r--r-- | include/rfb.js | 2 | ||||
-rw-r--r-- | include/ui.js | 1123 | ||||
-rw-r--r-- | vnc.html | 108 |
7 files changed, 683 insertions, 617 deletions
diff --git a/images/showextrakeys.png b/images/toggleextrakeys.png Binary files differindex ad8e0a7..ad8e0a7 100644 --- a/images/showextrakeys.png +++ b/images/toggleextrakeys.png diff --git a/include/base.css b/include/base.css index 2769357..8d88c0f 100644 --- a/include/base.css +++ b/include/base.css @@ -1,7 +1,7 @@ /* * noVNC base CSS * Copyright (C) 2012 Joel Martin - * Copyright (C) 2013 Samuel Mannehed for Cendio AB + * Copyright (C) 2016 Samuel Mannehed for Cendio AB * noVNC is licensed under the MPL 2.0 (see LICENSE.txt) * This file is licensed under the 2-Clause BSD license (see LICENSE.txt). */ @@ -30,18 +30,18 @@ html { padding-bottom:8px; } -#noVNC_host { +#noVNC_setting_host { width:150px; } -#noVNC_port { +#noVNC_setting_port { width: 80px; } -#noVNC_password { +#noVNC_setting_password { width: 150px; } -#noVNC_encrypt { +#noVNC_setting_encrypt { } -#noVNC_path { +#noVNC_setting_path { width: 100px; } #noVNC_connect_button { @@ -56,10 +56,10 @@ html { #noVNC_view_drag_button { display: none; } -#sendCtrlAltDelButton { +#noVNC_sendCtrlAltDel_button { display: none; } -#fullscreenButton { +#noVNC_fullscreen_button { display: none; } #noVNC_xvp_buttons { @@ -77,13 +77,13 @@ html { position: relative; } -.noVNC-buttons-left { +.noVNC_buttons_left { float: left; z-index: 1; position: relative; } -.noVNC-buttons-right { +.noVNC_buttons_right { float:right; right: 0px; z-index: 2; @@ -109,13 +109,11 @@ html { padding: 0px; } -#noVNC_apply { +#noVNC_settings_apply { float:right; } -/* Do not set width/height for VNC_screen or VNC_canvas or incorrect - * scaling will occur. Canvas resizes to remote VNC settings */ -#noVNC_screen { +#noVNC_container { display: table; width:100%; height:100%; @@ -124,7 +122,7 @@ html { /*border-top-left-radius: 800px 600px;*/ } -#noVNC_container { +#noVNC_screen { display: none; position: absolute; margin: 0px; @@ -137,6 +135,9 @@ html { height: auto; } +/* Do not set width/height for VNC_canvas or incorrect + * scaling will occur. Canvas size depends on remote VNC + * settings and noVNC settings. */ #noVNC_canvas { position: absolute; left: 0; @@ -232,7 +233,7 @@ html { right:85px; } -#keyboardinput { +#noVNC_keyboardinput { width:1px; height:1px; background-color:#fff; @@ -277,7 +278,7 @@ html { } /* Control bar */ -#noVNC-control-bar { +#noVNC_control_bar { position:fixed; display:block; @@ -426,11 +427,11 @@ html { font-size: 180px; } -.noVNC-buttons-left { +.noVNC_buttons_left { padding-left: 10px; } -.noVNC-buttons-right { +.noVNC_buttons_right { padding-right: 10px; } @@ -441,11 +442,11 @@ html { margin-left: 0px; } -#showExtraKeysButton { display: none; } -#toggleCtrlButton { display: inline; } -#toggleAltButton { display: inline; } -#sendTabButton { display: inline; } -#sendEscButton { display: inline; } +#noVNC_toggleExtraKeys_button { display: none; } +#noVNC_toggleCtrl_button { display: inline; } +#noVNC_toggleAlt_button { display: inline; } +#noVNC_sendTab_button { display: inline; } +#noVNC_sendEsc_button { display: inline; } /* left-align the status text on lower resolutions */ @media screen and (max-width: 800px){ @@ -468,35 +469,35 @@ html { .noVNC_status_button { font-size: 10px; } - .noVNC-buttons-left { + .noVNC_buttons_left { padding-left: 0px; } - .noVNC-buttons-right { + .noVNC_buttons_right { padding-right: 0px; } /* collapse the extra keys on lower resolutions */ - #showExtraKeysButton { + #noVNC_toggleExtraKeys_button { display: inline; } - #toggleCtrlButton { + #noVNC_toggleCtrl_button { display: none; position: absolute; top: 30px; left: 0px; } - #toggleAltButton { + #noVNC_toggleAlt_button { display: none; position: absolute; top: 65px; left: 0px; } - #sendTabButton { + #noVNC_sendTab_button { display: none; position: absolute; top: 100px; left: 0px; } - #sendEscButton { + #noVNC_sendEsc_button { display: none; position: absolute; top: 135px; diff --git a/include/black.css b/include/black.css index 7d940c5..5c4558d 100644 --- a/include/black.css +++ b/include/black.css @@ -6,7 +6,7 @@ * This file is licensed under the 2-Clause BSD license (see LICENSE.txt). */ -#keyboardinput { +#noVNC_keyboardinput { background-color:#000; } diff --git a/include/blue.css b/include/blue.css index b2a0adc..4ab53bd 100644 --- a/include/blue.css +++ b/include/blue.css @@ -58,7 +58,7 @@ color:#fff; } -#keyboardinput { +#noVNC_keyboardinput { background-color:#04073d; } diff --git a/include/rfb.js b/include/rfb.js index 7340fad..c022969 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -311,6 +311,8 @@ var RFB; this._sock.flush(); }, + // Requests a change of remote desktop size. This message is an extension + // and may only be sent if we have received an ExtendedDesktopSize message requestDesktopSize: function (width, height) { if (this._rfb_state !== "normal") { return; } diff --git a/include/ui.js b/include/ui.js index 95bc135..4fc6f09 100644 --- a/include/ui.js +++ b/include/ui.js @@ -1,7 +1,7 @@ /* * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin - * Copyright (C) 2015 Samuel Mannehed for Cendio AB + * Copyright (C) 2016 Samuel Mannehed for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. @@ -47,7 +47,7 @@ var UI; // Setup rfb object, load settings from browser storage, then call // UI.init to setup the UI/menus - load: function (callback) { + load: function(callback) { WebUtil.initSettings(UI.start, callback); }, @@ -60,13 +60,13 @@ var UI; var sheets = WebUtil.getStylesheets(); var i; for (i = 0; i < sheets.length; i += 1) { - UI.addOption($D('noVNC_stylesheet'),sheets[i].title, sheets[i].title); + UI.addOption($D('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_logging'),llevels[i], llevels[i]); + UI.addOption($D('noVNC_setting_logging'),llevels[i], llevels[i]); } // Settings with immediate effects @@ -114,7 +114,7 @@ var UI; UI.updateVisualState(); - $D('noVNC_host').focus(); + $D('noVNC_setting_host').focus(); // Show mouse selector buttons on touch screen devices if (UI.isTouchDevice) { @@ -132,7 +132,7 @@ var UI; UI.setBarPosition(); Util.addEvent(window, 'resize', function () { - UI.onresize(); + UI.applyResizeMode(); UI.setViewClip(); UI.updateViewDrag(); UI.setBarPosition(); @@ -148,7 +148,7 @@ var UI; document.documentElement.mozRequestFullScreen || document.documentElement.webkitRequestFullscreen || document.body.msRequestFullscreen)) { - $D('fullscreenButton').style.display = "inline"; + $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); @@ -182,13 +182,13 @@ var UI; } }, - initRFB: function () { + initRFB: function() { try { UI.rfb = new RFB({'target': $D('noVNC_canvas'), 'onUpdateState': UI.updateState, - 'onXvpInit': UI.updateXvpVisualState, - 'onClipboard': UI.clipReceive, - 'onFBUComplete': UI.FBUComplete, + 'onXvpInit': UI.updateXvpButton, + 'onClipboard': UI.clipboardReceive, + 'onFBUComplete': UI.initialResize, 'onFBResize': UI.updateViewDrag, 'onDesktopName': UI.updateDocumentTitle}); return true; @@ -205,109 +205,194 @@ var UI; $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("showKeyboard").onclick = UI.showKeyboard; - - $D("keyboardinput").oninput = UI.keyInput; - $D("keyboardinput").onblur = UI.keyInputBlur; - $D("keyboardinput").onsubmit = function () { return false; }; - - $D("showExtraKeysButton").onclick = UI.showExtraKeys; - $D("toggleCtrlButton").onclick = UI.toggleCtrl; - $D("toggleAltButton").onclick = UI.toggleAlt; - $D("sendTabButton").onclick = UI.sendTab; - $D("sendEscButton").onclick = UI.sendEsc; - - $D("sendCtrlAltDelButton").onclick = UI.sendCtrlAltDel; - $D("xvpShutdownButton").onclick = UI.xvpShutdown; - $D("xvpRebootButton").onclick = UI.xvpReboot; - $D("xvpResetButton").onclick = UI.xvpReset; - $D("noVNC_status").onclick = UI.togglePopupStatus; - $D("noVNC_popup_status").onclick = UI.togglePopupStatus; - $D("xvpButton").onclick = UI.toggleXvpPanel; - $D("clipboardButton").onclick = UI.toggleClipboardPanel; - $D("fullscreenButton").onclick = UI.toggleFullscreen; - $D("settingsButton").onclick = UI.toggleSettingsPanel; - $D("connectButton").onclick = UI.toggleConnectPanel; - $D("disconnectButton").onclick = UI.disconnect; - $D("descriptionButton").onclick = UI.toggleConnectPanel; + $D("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; }; + + $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; + + $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; $D("noVNC_clipboard_text").onfocus = UI.displayBlur; $D("noVNC_clipboard_text").onblur = UI.displayFocus; - $D("noVNC_clipboard_text").onchange = UI.clipSend; - $D("noVNC_clipboard_clear_button").onclick = UI.clipClear; + $D("noVNC_clipboard_text").onchange = UI.clipboardSend; + $D("noVNC_clipboard_clear_button").onclick = UI.clipboardClear; $D("noVNC_settings_menu").onmouseover = UI.displayBlur; $D("noVNC_settings_menu").onmouseover = UI.displayFocus; - $D("noVNC_apply").onclick = UI.settingsApply; + $D("noVNC_settings_apply").onclick = UI.settingsApply; $D("noVNC_connect_button").onclick = UI.connect; - $D("noVNC_resize").onchange = UI.enableDisableViewClip; + $D("noVNC_setting_resize").onchange = UI.enableDisableViewClip; }, - onresize: function (callback) { - if (!UI.rfb) return; +/* ------^------- + * /INIT + * ============== + * VISUAL + * ------v------*/ - var size = UI.getCanvasLimit(); + updateState: function(rfb, state, oldstate, msg) { + UI.rfb_state = state; + var klass; + switch (state) { + case 'failed': + case 'fatal': + klass = "noVNC_status_error"; + break; + case 'normal': + klass = "noVNC_status_normal"; + break; + case 'disconnected': + $D('noVNC_logo').style.display = "block"; + $D('noVNC_screen').style.display = "none"; + /* falls through */ + case 'loaded': + klass = "noVNC_status_normal"; + break; + case 'password': + UI.toggleConnectPanel(); - if (size && UI.rfb_state === 'normal' && UI.rfb.get_display()) { - var display = UI.rfb.get_display(); - var scaleType = UI.getSetting('resize'); - if (scaleType === 'remote') { - // use remote resizing + $D('noVNC_connect_button').value = "Send Password"; + $D('noVNC_connect_button').onclick = UI.setPassword; + $D('noVNC_setting_password').focus(); - // When the local window has been resized, wait until the size remains - // the same for 0.5 seconds before sending the request for changing - // the resolution of the session - clearTimeout(UI.resizeTimeout); - UI.resizeTimeout = setTimeout(function(){ - display.set_maxWidth(size.w); - display.set_maxHeight(size.h); - Util.Debug('Attempting requestDesktopSize(' + - size.w + ', ' + size.h + ')'); - UI.rfb.requestDesktopSize(size.w, size.h); - }, 500); - } else if (scaleType === 'scale' || scaleType === 'downscale') { - // use local scaling + klass = "noVNC_status_warn"; + break; + default: + klass = "noVNC_status_warn"; + break; + } - var downscaleOnly = scaleType === 'downscale'; - var scaleRatio = display.autoscale(size.w, size.h, downscaleOnly); - UI.rfb.get_mouse().set_scale(scaleRatio); - Util.Debug('Scaling by ' + UI.rfb.get_mouse().get_scale()); - } + if (typeof(msg) !== 'undefined') { + $D('noVNC_control_bar').setAttribute("class", klass); + $D('noVNC_status').innerHTML = msg; } + + UI.updateVisualState(); }, - getCanvasLimit: function () { - var container = $D('noVNC_container'); + // Disable/enable controls depending on connection state + updateVisualState: function() { + var connected = UI.rfb && UI.rfb_state === 'normal'; - // Hide the scrollbars until the size is calculated - container.style.overflow = "hidden"; + //Util.Debug(">> updateVisualState"); + $D('noVNC_setting_encrypt').disabled = connected; + $D('noVNC_setting_true_color').disabled = connected; + if (Util.browserSupportsCursorURIs()) { + $D('noVNC_setting_cursor').disabled = connected; + } else { + UI.updateSetting('cursor', !UI.isTouchDevice); + $D('noVNC_setting_cursor').disabled = true; + } - var pos = Util.getPosition(container); - var w = pos.width; - var h = pos.height; + 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; - container.style.overflow = "visible"; + 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"; + } 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"; + UI.updateXvpButton(0); + } - if (isNaN(w) || isNaN(h)) { - return false; + // State change disables viewport dragging. + // It is enabled (toggled) by direct click on the button + UI.updateViewDrag(false); + + switch (UI.rfb_state) { + case 'fatal': + case 'failed': + case 'disconnected': + $D('noVNC_connectPanel_button').style.display = ""; + $D('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"; + break; + default: + $D('noVNC_connectPanel_button').style.display = "none"; + $D('noVNC_disconnect_button').style.display = ""; + break; + } + + //Util.Debug("<< updateVisualState"); + }, + + popupStatus: function(text) { + var psp = $D('noVNC_popup_status'); + + clearTimeout(UI.popupStatusTimeout); + + if (typeof text === 'string') { + psp.innerHTML = text; } else { - return {w: w, h: h}; + psp.innerHTML = $D('noVNC_status').innerHTML; } + psp.style.display = "block"; + psp.style.left = window.innerWidth/2 - + parseInt(window.getComputedStyle(psp).width)/2 -30 + "px"; + + // Show the popup for a maximum of 1.5 seconds + UI.popupStatusTimeout = setTimeout(function() { + UI.closePopup(); + }, 1500); }, - // Read form control compatible setting from cookie - getSetting: function(name) { - var ctrl = $D('noVNC_' + 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}) { - val = false; - } else { - val = true; - } + closePopup: function() { + clearTimeout(UI.popupStatusTimeout); + $D('noVNC_popup_status').style.display = "none"; + }, + +/* ------^------- + * /VISUAL + * ============== + * SETTINGS + * ------v------*/ + + // Initial page load read/initialization of settings + initSetting: function(name, defVal) { + // Check Query string followed by cookie + var val = WebUtil.getConfigVar(name); + if (val === null) { + val = WebUtil.readSetting(name, defVal); } + UI.updateSetting(name, val); return val; }, @@ -323,7 +408,7 @@ var UI; // Update the settings control value = UI.getSetting(name); - var ctrl = $D('noVNC_' + name); + var ctrl = $D('noVNC_setting_' + name); if (ctrl.type === 'checkbox') { ctrl.checked = value; @@ -346,7 +431,7 @@ var UI; // Save control setting to cookie saveSetting: function(name) { - var val, ctrl = $D('noVNC_' + name); + var val, ctrl = $D('noVNC_setting_' + name); if (ctrl.type === 'checkbox') { val = ctrl.checked; } else if (typeof ctrl.options !== 'undefined') { @@ -359,48 +444,122 @@ var UI; return val; }, - // Initial page load read/initialization of settings - initSetting: function(name, defVal) { - // Check Query string followed by cookie - var val = WebUtil.getConfigVar(name); - if (val === null) { - val = WebUtil.readSetting(name, defVal); - } + // Force a setting to be a certain value + forceSetting: function(name, val) { UI.updateSetting(name, val); return val; }, - // Force a setting to be a certain value - forceSetting: function(name, val) { - UI.updateSetting(name, val); + // Read form control compatible setting from cookie + getSetting: function(name) { + var ctrl = $D('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}) { + val = false; + } else { + val = true; + } + } return val; }, + // Save/apply settings when 'Apply' button is pressed + settingsApply: function() { + //Util.Debug(">> settingsApply"); + UI.saveSetting('encrypt'); + UI.saveSetting('true_color'); + if (Util.browserSupportsCursorURIs()) { + UI.saveSetting('cursor'); + } + + UI.saveSetting('resize'); - // Show the popup status - togglePopupStatus: function(text) { - var psp = $D('noVNC_popup_status'); + if (UI.getSetting('resize') === 'downscale' || UI.getSetting('resize') === 'scale') { + UI.forceSetting('clip', false); + } + + UI.saveSetting('clip'); + UI.saveSetting('shared'); + UI.saveSetting('view_only'); + UI.saveSetting('path'); + UI.saveSetting('repeaterID'); + UI.saveSetting('stylesheet'); + UI.saveSetting('logging'); - var closePopup = function() { psp.style.display = "none"; }; + // Settings with immediate (non-connected related) effect + WebUtil.selectStylesheet(UI.getSetting('stylesheet')); + WebUtil.init_logging(UI.getSetting('logging')); + UI.setViewClip(); + UI.updateViewDrag(); + //Util.Debug("<< settingsApply"); + }, - if (window.getComputedStyle(psp).display === 'none') { - if (typeof text === 'string') { - psp.innerHTML = text; + // Open menu + openSettingsMenu: function() { + // Close the description panel + $D('noVNC_description').style.display = "none"; + // Close clipboard panel if open + if (UI.clipboardOpen === true) { + UI.toggleClipboardPanel(); + } + // Close connection settings if open + if (UI.connSettingsOpen === true) { + UI.toggleConnectPanel(); + } + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } + $D('noVNC_settings').style.display = "block"; + $D('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"; + UI.settingsOpen = false; + }, + + // Toggle the settings menu: + // On open, settings are refreshed from saved cookies. + // On close, settings are applied + toggleSettingsPanel: function() { + // Close the description panel + $D('noVNC_description').style.display = "none"; + if (UI.settingsOpen) { + UI.settingsApply(); + UI.closeSettingsMenu(); + } else { + UI.updateSetting('encrypt'); + UI.updateSetting('true_color'); + if (Util.browserSupportsCursorURIs()) { + UI.updateSetting('cursor'); } else { - psp.innerHTML = $D('noVNC_status').innerHTML; + UI.updateSetting('cursor', !UI.isTouchDevice); + $D('noVNC_setting_cursor').disabled = true; } - psp.style.display = "block"; - psp.style.left = window.innerWidth/2 - - parseInt(window.getComputedStyle(psp).width)/2 -30 + "px"; + UI.updateSetting('clip'); + UI.updateSetting('resize'); + UI.updateSetting('shared'); + UI.updateSetting('view_only'); + UI.updateSetting('path'); + UI.updateSetting('repeaterID'); + UI.updateSetting('stylesheet'); + UI.updateSetting('logging'); - // Show the popup for a maximum of 1.5 seconds - UI.popupStatusTimeout = setTimeout(function() { closePopup(); }, 1500); - } else { - clearTimeout(UI.popupStatusTimeout); - closePopup(); + UI.openSettingsMenu(); } }, +/* ------^------- + * /SETTINGS + * ============== + * XVP + * ------v------*/ + // Show the XVP panel toggleXvpPanel: function() { // Close the description panel @@ -421,15 +580,34 @@ var UI; // Toggle XVP panel if (UI.xvpOpen === true) { $D('noVNC_xvp').style.display = "none"; - $D('xvpButton').className = "noVNC_status_button"; + $D('noVNC_toggleXvp_button').className = "noVNC_status_button"; UI.xvpOpen = false; } else { $D('noVNC_xvp').style.display = "block"; - $D('xvpButton').className = "noVNC_status_button_selected"; + $D('noVNC_toggleXvp_button').className = "noVNC_status_button_selected"; UI.xvpOpen = true; } }, + // Disable/enable XVP button + updateXvpButton: function(ver) { + if (ver >= 1) { + $D('noVNC_toggleXvp_button').style.display = 'inline'; + } else { + $D('noVNC_toggleXvp_button').style.display = 'none'; + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } + } + }, + +/* ------^------- + * /XVP + * ============== + * CLIPBOARD + * ------v------*/ + // Show the clipboard panel toggleClipboardPanel: function() { // Close the description panel @@ -450,56 +628,39 @@ var UI; // Toggle Clipboard Panel if (UI.clipboardOpen === true) { $D('noVNC_clipboard').style.display = "none"; - $D('clipboardButton').className = "noVNC_status_button"; + $D('noVNC_clipboard_button').className = "noVNC_status_button"; UI.clipboardOpen = false; } else { $D('noVNC_clipboard').style.display = "block"; - $D('clipboardButton').className = "noVNC_status_button_selected"; + $D('noVNC_clipboard_button').className = "noVNC_status_button_selected"; UI.clipboardOpen = true; } }, - // Toggle fullscreen mode - toggleFullscreen: function() { - if (document.fullscreenElement || // alternative standard method - document.mozFullScreenElement || // currently working methods - document.webkitFullscreenElement || - document.msFullscreenElement) { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } else { - if (document.documentElement.requestFullscreen) { - document.documentElement.requestFullscreen(); - } else if (document.documentElement.mozRequestFullScreen) { - document.documentElement.mozRequestFullScreen(); - } else if (document.documentElement.webkitRequestFullscreen) { - document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } else if (document.body.msRequestFullscreen) { - document.body.msRequestFullscreen(); - } - } - UI.enableDisableViewClip(); - UI.updateFullscreenButton(); + clipboardReceive: function(rfb, text) { + Util.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "..."); + $D('noVNC_clipboard_text').value = text; + Util.Debug("<< UI.clipboardReceive"); }, - updateFullscreenButton: function() { - if (document.fullscreenElement || // alternative standard method - document.mozFullScreenElement || // currently working methods - document.webkitFullscreenElement || - document.msFullscreenElement ) { - $D('fullscreenButton').className = "noVNC_status_button_selected"; - } else { - $D('fullscreenButton').className = "noVNC_status_button"; - } + clipboardClear: function() { + $D('noVNC_clipboard_text').value = ""; + UI.rfb.clipboardPasteFrom(""); + }, + + clipboardSend: function() { + var text = $D('noVNC_clipboard_text').value; + Util.Debug(">> UI.clipboardSend: " + text.substr(0,40) + "..."); + UI.rfb.clipboardPasteFrom(text); + Util.Debug("<< UI.clipboardSend"); }, +/* ------^------- + * /CLIPBOARD + * ============== + * CONNECTION + * ------v------*/ + // Show the connection settings panel/menu toggleConnectPanel: function() { // Close the description panel @@ -508,7 +669,7 @@ var UI; if (UI.settingsOpen === true) { UI.settingsApply(); UI.closeSettingsMenu(); - $D('connectButton').className = "noVNC_status_button"; + $D('noVNC_connectPanel_button').className = "noVNC_status_button"; } // Close clipboard panel if open if (UI.clipboardOpen === true) { @@ -522,7 +683,7 @@ var UI; // Toggle Connection Panel if (UI.connSettingsOpen === true) { $D('noVNC_controls').style.display = "none"; - $D('connectButton').className = "noVNC_status_button"; + $D('noVNC_connectPanel_button').className = "noVNC_status_button"; UI.connSettingsOpen = false; UI.saveSetting('host'); UI.saveSetting('port'); @@ -530,106 +691,63 @@ var UI; //UI.saveSetting('password'); } else { $D('noVNC_controls').style.display = "block"; - $D('connectButton').className = "noVNC_status_button_selected"; + $D('noVNC_connectPanel_button').className = "noVNC_status_button_selected"; UI.connSettingsOpen = true; - $D('noVNC_host').focus(); + $D('noVNC_setting_host').focus(); } }, - // Toggle the settings menu: - // On open, settings are refreshed from saved cookies. - // On close, settings are applied - toggleSettingsPanel: function() { - // Close the description panel - $D('noVNC_description').style.display = "none"; - if (UI.settingsOpen) { - UI.settingsApply(); - UI.closeSettingsMenu(); - } else { - UI.updateSetting('encrypt'); - UI.updateSetting('true_color'); - if (Util.browserSupportsCursorURIs()) { - UI.updateSetting('cursor'); - } else { - UI.updateSetting('cursor', !UI.isTouchDevice); - $D('noVNC_cursor').disabled = true; - } - UI.updateSetting('clip'); - UI.updateSetting('resize'); - UI.updateSetting('shared'); - UI.updateSetting('view_only'); - UI.updateSetting('path'); - UI.updateSetting('repeaterID'); - UI.updateSetting('stylesheet'); - UI.updateSetting('logging'); + connect: function() { + UI.closeSettingsMenu(); + UI.toggleConnectPanel(); - UI.openSettingsMenu(); - } - }, + 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; - // Open menu - openSettingsMenu: function() { - // Close the description panel - $D('noVNC_description').style.display = "none"; - // Close clipboard panel if open - if (UI.clipboardOpen === true) { - UI.toggleClipboardPanel(); - } - // Close connection settings if open - if (UI.connSettingsOpen === true) { - UI.toggleConnectPanel(); - } - // Close XVP panel if open - if (UI.xvpOpen === true) { - UI.toggleXvpPanel(); + //if token is in path then ignore the new token variable + if (token) { + path = WebUtil.injectParamIfMissing(path, "token", token); } - $D('noVNC_settings').style.display = "block"; - $D('settingsButton').className = "noVNC_status_button_selected"; - UI.settingsOpen = true; - }, - - // Close menu (without applying settings) - closeSettingsMenu: function() { - $D('noVNC_settings').style.display = "none"; - $D('settingsButton').className = "noVNC_status_button"; - UI.settingsOpen = false; - }, - // Save/apply settings when 'Apply' button is pressed - settingsApply: function() { - //Util.Debug(">> settingsApply"); - UI.saveSetting('encrypt'); - UI.saveSetting('true_color'); - if (Util.browserSupportsCursorURIs()) { - UI.saveSetting('cursor'); + if ((!host) || (!port)) { + throw new Error("Must set host and port"); } - UI.saveSetting('resize'); + if (!UI.initRFB()) return; - if (UI.getSetting('resize') === 'downscale' || UI.getSetting('resize') === 'scale') { - UI.forceSetting('clip', false); - } + UI.rfb.set_encrypt(UI.getSetting('encrypt')); + UI.rfb.set_true_color(UI.getSetting('true_color')); + UI.rfb.set_local_cursor(UI.getSetting('cursor')); + UI.rfb.set_shared(UI.getSetting('shared')); + UI.rfb.set_view_only(UI.getSetting('view_only')); + UI.rfb.set_repeaterID(UI.getSetting('repeaterID')); - UI.saveSetting('clip'); - UI.saveSetting('shared'); - UI.saveSetting('view_only'); - UI.saveSetting('path'); - UI.saveSetting('repeaterID'); - UI.saveSetting('stylesheet'); - UI.saveSetting('logging'); + UI.rfb.connect(host, port, password, path); - // Settings with immediate (non-connected related) effect - WebUtil.selectStylesheet(UI.getSetting('stylesheet')); - WebUtil.init_logging(UI.getSetting('logging')); - UI.setViewClip(); - UI.updateViewDrag(); - //Util.Debug("<< settingsApply"); + //Close dialog. + setTimeout(function () { UI.setBarPosition; } ); + $D('noVNC_logo').style.display = "none"; + $D('noVNC_screen').style.display = "inline"; }, + disconnect: function() { + UI.closeSettingsMenu(); + UI.rfb.disconnect(); + + // 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"; + // Don't display the connection settings until we're actually disconnected + }, setPassword: function() { - UI.rfb.sendPassword($D('noVNC_password').value); + UI.rfb.sendPassword($D('noVNC_setting_password').value); //Reset connect button. $D('noVNC_connect_button').value = "Connect"; $D('noVNC_connect_button').onclick = UI.connect; @@ -638,254 +756,138 @@ var UI; return false; }, - sendCtrlAltDel: function() { - UI.rfb.sendCtrlAltDel(); - }, - - xvpShutdown: function() { - UI.rfb.xvpShutdown(); - }, - - xvpReboot: function() { - UI.rfb.xvpReboot(); - }, - - xvpReset: function() { - UI.rfb.xvpReset(); - }, - - setMouseButton: function(num) { - if (typeof num === 'undefined') { - // Disable mouse buttons - num = -1; - } - if (UI.rfb) { - UI.rfb.get_mouse().set_touchButton(num); - } +/* ------^------- + * /CONNECTION + * ============== + * FULLSCREEN + * ------v------*/ - var blist = [0, 1,2,4]; - for (var b = 0; b < blist.length; b++) { - var button = $D('noVNC_mouse_button' + blist[b]); - if (blist[b] === num) { - button.style.display = ""; - } else { - button.style.display = "none"; + toggleFullscreen: function() { + if (document.fullscreenElement || // alternative standard method + document.mozFullScreenElement || // currently working methods + document.webkitFullscreenElement || + document.msFullscreenElement) { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); } - } - }, - - updateState: function(rfb, state, oldstate, msg) { - UI.rfb_state = state; - var klass; - switch (state) { - case 'failed': - case 'fatal': - klass = "noVNC_status_error"; - break; - case 'normal': - klass = "noVNC_status_normal"; - break; - case 'disconnected': - $D('noVNC_logo').style.display = "block"; - $D('noVNC_container').style.display = "none"; - /* falls through */ - case 'loaded': - klass = "noVNC_status_normal"; - break; - case 'password': - UI.toggleConnectPanel(); - - $D('noVNC_connect_button').value = "Send Password"; - $D('noVNC_connect_button').onclick = UI.setPassword; - $D('noVNC_password').focus(); - - klass = "noVNC_status_warn"; - break; - default: - klass = "noVNC_status_warn"; - break; - } - - if (typeof(msg) !== 'undefined') { - $D('noVNC-control-bar').setAttribute("class", klass); - $D('noVNC_status').innerHTML = msg; - } - - UI.updateVisualState(); - }, - - // Disable/enable controls depending on connection state - updateVisualState: function() { - var connected = UI.rfb && UI.rfb_state === 'normal'; - - //Util.Debug(">> updateVisualState"); - $D('noVNC_encrypt').disabled = connected; - $D('noVNC_true_color').disabled = connected; - if (Util.browserSupportsCursorURIs()) { - $D('noVNC_cursor').disabled = connected; } else { - UI.updateSetting('cursor', !UI.isTouchDevice); - $D('noVNC_cursor').disabled = true; + if (document.documentElement.requestFullscreen) { + document.documentElement.requestFullscreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.documentElement.mozRequestFullScreen(); + } else if (document.documentElement.webkitRequestFullscreen) { + document.documentElement.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (document.body.msRequestFullscreen) { + document.body.msRequestFullscreen(); + } } - UI.enableDisableViewClip(); - $D('noVNC_resize').disabled = connected; - $D('noVNC_shared').disabled = connected; - $D('noVNC_view_only').disabled = connected; - $D('noVNC_path').disabled = connected; - $D('noVNC_repeaterID').disabled = connected; - - if (connected) { - UI.setViewClip(); - UI.setMouseButton(1); - $D('clipboardButton').style.display = "inline"; - $D('showKeyboard').style.display = "inline"; - $D('noVNC_extra_keys').style.display = ""; - $D('sendCtrlAltDelButton').style.display = "inline"; - } else { - UI.setMouseButton(); - $D('clipboardButton').style.display = "none"; - $D('showKeyboard').style.display = "none"; - $D('noVNC_extra_keys').style.display = "none"; - $D('sendCtrlAltDelButton').style.display = "none"; - UI.updateXvpVisualState(0); - } - - // State change disables viewport dragging. - // It is enabled (toggled) by direct click on the button - UI.updateViewDrag(false); - - switch (UI.rfb_state) { - case 'fatal': - case 'failed': - case 'disconnected': - $D('connectButton').style.display = ""; - $D('disconnectButton').style.display = "none"; - UI.connSettingsOpen = false; - UI.toggleConnectPanel(); - break; - case 'loaded': - $D('connectButton').style.display = ""; - $D('disconnectButton').style.display = "none"; - break; - default: - $D('connectButton').style.display = "none"; - $D('disconnectButton').style.display = ""; - break; - } - - //Util.Debug("<< updateVisualState"); + UI.updateFullscreenButton(); }, - // Disable/enable XVP button - updateXvpVisualState: function(ver) { - if (ver >= 1) { - $D('xvpButton').style.display = 'inline'; + updateFullscreenButton: function() { + if (document.fullscreenElement || // alternative standard method + document.mozFullScreenElement || // currently working methods + document.webkitFullscreenElement || + document.msFullscreenElement ) { + $D('noVNC_fullscreen_button').className = "noVNC_status_button_selected"; } else { - $D('xvpButton').style.display = 'none'; - // Close XVP panel if open - if (UI.xvpOpen === true) { - UI.toggleXvpPanel(); - } + $D('noVNC_fullscreen_button').className = "noVNC_status_button"; } }, - // This resize can not be done until we know from the first Frame Buffer Update - // if it is supported or not. - // The resize is needed to make sure the server desktop size is updated to the - // corresponding size of the current local window when reconnecting to an - // existing session. - FBUComplete: function(rfb, fbu) { - UI.onresize(); - UI.rfb.set_onFBUComplete(function() { }); - }, - - // Display the desktop name in the document title - updateDocumentTitle: function(rfb, name) { - document.title = name + " - noVNC"; - }, - - clipReceive: function(rfb, text) { - Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "..."); - $D('noVNC_clipboard_text').value = text; - Util.Debug("<< UI.clipReceive"); - }, - - connect: function() { - UI.closeSettingsMenu(); - UI.toggleConnectPanel(); +/* ------^------- + * /FULLSCREEN + * ============== + * RESIZE + * ------v------*/ - var host = $D('noVNC_host').value; - var port = $D('noVNC_port').value; - var password = $D('noVNC_password').value; - var token = $D('noVNC_token').value; - var path = $D('noVNC_path').value; + // Apply remote resizing or local scaling + applyResizeMode: function() { + if (!UI.rfb) return; - //if token is in path then ignore the new token variable - if (token) { - path = WebUtil.injectParamIfMissing(path, "token", token); - } + var screen = UI.screenSize(); - if ((!host) || (!port)) { - throw new Error("Must set host and port"); - } + if (screen && UI.rfb_state === 'normal' && UI.rfb.get_display()) { - if (!UI.initRFB()) return; + var display = UI.rfb.get_display(); + var resizeMode = UI.getSetting('resize'); - UI.rfb.set_encrypt(UI.getSetting('encrypt')); - UI.rfb.set_true_color(UI.getSetting('true_color')); - UI.rfb.set_local_cursor(UI.getSetting('cursor')); - UI.rfb.set_shared(UI.getSetting('shared')); - UI.rfb.set_view_only(UI.getSetting('view_only')); - UI.rfb.set_repeaterID(UI.getSetting('repeaterID')); + if (resizeMode === 'remote') { - UI.rfb.connect(host, port, password, path); + // Request changing the resolution of the remote display to + // the size of the local browser viewport. - //Close dialog. - setTimeout(UI.setBarPosition, 100); - $D('noVNC_logo').style.display = "none"; - $D('noVNC_container').style.display = "inline"; - }, + // In order to not send multiple requests before the browser-resize + // is finished we wait 0.5 seconds before sending the request. + clearTimeout(UI.resizeTimeout); + UI.resizeTimeout = setTimeout(function(){ - disconnect: function() { - UI.closeSettingsMenu(); - UI.rfb.disconnect(); + // Limit the viewport to the size of the browser window + display.set_maxWidth(screen.w); + display.set_maxHeight(screen.h); - // Restore the callback used for initial resize - UI.rfb.set_onFBUComplete(UI.FBUComplete); + Util.Debug('Attempting requestDesktopSize(' + + screen.w + ', ' + screen.h + ')'); - $D('noVNC_logo').style.display = "block"; - $D('noVNC_container').style.display = "none"; + // Request a remote size covering the viewport + UI.rfb.requestDesktopSize(screen.w, screen.h); + }, 500); - // Don't display the connection settings until we're actually disconnected + } else if (resizeMode === 'scale' || resizeMode === 'downscale') { + var downscaleOnly = resizeMode === 'downscale'; + var scaleRatio = display.autoscale(screen.w, screen.h, downscaleOnly); + UI.rfb.get_mouse().set_scale(scaleRatio); + Util.Debug('Scaling by ' + UI.rfb.get_mouse().get_scale()); + } + } }, - displayBlur: function() { - if (!UI.rfb) return; + // 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'); - UI.rfb.get_keyboard().set_focused(false); - UI.rfb.get_mouse().set_focused(false); - }, + // Hide the scrollbars until the size is calculated + screen.style.overflow = "hidden"; - displayFocus: function() { - if (!UI.rfb) return; + var pos = Util.getPosition(screen); + var w = pos.width; + var h = pos.height; - UI.rfb.get_keyboard().set_focused(true); - UI.rfb.get_mouse().set_focused(true); - }, + screen.style.overflow = "visible"; - clipClear: function() { - $D('noVNC_clipboard_text').value = ""; - UI.rfb.clipboardPasteFrom(""); + if (isNaN(w) || isNaN(h)) { + return false; + } else { + return {w: w, h: h}; + } }, - clipSend: function() { - var text = $D('noVNC_clipboard_text').value; - Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "..."); - UI.rfb.clipboardPasteFrom(text); - Util.Debug("<< UI.clipSend"); + // Normally we only apply the current resize mode after a window resize + // event. This means that when a new connection is opened, there is no + // resize mode active. + // We have to wait until the first FBU because this is where the client + // will find the supported encodings of the server. Some calls later in + // the chain is dependant on knowing the server-capabilities. + initialResize: function(rfb, fbu) { + UI.applyResizeMode(); + // After doing this once, we remove the callback. + UI.rfb.set_onFBUComplete(function() { }); }, +/* ------^------- + * /RESIZE + * ============== + * CLIPPING + * ------v------*/ + // Set and configure viewport clipping setViewClip: function(clip) { var display; @@ -919,19 +921,19 @@ var UI; // If clipping, update clipping settings display.set_viewport(true); - var size = UI.getCanvasLimit(); + var size = UI.screenSize(); if (size) { display.set_maxWidth(size.w); display.set_maxHeight(size.h); // Hide potential scrollbars that can skew the position - $D('noVNC_container').style.overflow = "hidden"; + $D('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); - $D('noVNC_container').style.overflow = "visible"; + $D('noVNC_screen').style.overflow = "visible"; display.viewportChangeSize(new_w, size.h); } @@ -939,71 +941,75 @@ var UI; }, // Handle special cases where clipping is forced on/off or locked - enableDisableViewClip: function () { - var resizeElem = $D('noVNC_resize'); + enableDisableViewClip: function() { + var resizeSetting = $D('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_clip').disabled = true; - } else if (resizeElem.value === 'downscale' || resizeElem.value === 'scale') { + $D('noVNC_setting_clip').disabled = true; + } else if (resizeSetting.value === 'downscale' || resizeSetting.value === 'scale') { // Disable clipping if we are scaling UI.setViewClip(false); - $D('noVNC_clip').disabled = true; + $D('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 // scrollbars doesn't work. - UI.togglePopupStatus("Forcing clipping mode since scrollbars aren't supported by IE in fullscreen"); + UI.popupStatus("Forcing clipping mode since scrollbars aren't supported by IE in fullscreen"); UI.rememberedClipSetting = UI.getSetting('clip'); UI.setViewClip(true); - $D('noVNC_clip').disabled = true; + $D('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_clip').disabled = connected || UI.isTouchDevice; + $D('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; } else { - $D('noVNC_clip').disabled = connected || UI.isTouchDevice; + $D('noVNC_setting_clip').disabled = connected || UI.isTouchDevice; if (UI.isTouchDevice) { UI.setViewClip(true); } } }, - // Update the viewport drag/move button +/* ------^------- + * /CLIPPING + * ============== + * VIEWDRAG + * ------v------*/ + + // Update the viewport drag state updateViewDrag: function(drag) { if (!UI.rfb) return; - var vmb = $D('noVNC_view_drag_button'); + var viewDragButton = $D('noVNC_view_drag_button'); - // Check if viewport drag is possible + // Check if viewport drag is possible. It is only possible + // if the remote display is clipping the client display. if (UI.rfb_state === 'normal' && UI.rfb.get_display().get_viewport() && UI.rfb.get_display().clippingDisplay()) { - // Show and enable the drag button - vmb.style.display = "inline"; - vmb.disabled = false; + viewDragButton.style.display = "inline"; + viewDragButton.disabled = false; } else { - // The VNC content is the same size as - // or smaller than the display - + // The size of the remote display is the same or smaller + // than the client display. Make sure viewport drag isn't + // active when it can't be used. if (UI.rfb.get_viewportDrag) { - // Turn off viewport drag when it's - // active since it can't be used here - vmb.className = "noVNC_status_button"; + viewDragButton.className = "noVNC_status_button"; UI.rfb.set_viewportDrag(false); } - // Disable or hide the drag button + // The button is disabled instead of hidden on touch devices if (UI.rfb_state === 'normal' && UI.isTouchDevice) { - vmb.style.display = "inline"; - vmb.disabled = true; + viewDragButton.style.display = "inline"; + viewDragButton.disabled = true; } else { - vmb.style.display = "none"; + viewDragButton.style.display = "none"; } return; } @@ -1011,10 +1017,10 @@ var UI; if (typeof(drag) !== "undefined" && typeof(drag) !== "object") { if (drag) { - vmb.className = "noVNC_status_button_selected"; + viewDragButton.className = "noVNC_status_button_selected"; UI.rfb.set_viewportDrag(true); } else { - vmb.className = "noVNC_status_button"; + viewDragButton.className = "noVNC_status_button"; UI.rfb.set_viewportDrag(false); } } @@ -1023,20 +1029,26 @@ var UI; toggleViewDrag: function() { if (!UI.rfb) return; - var vmb = $D('noVNC_view_drag_button'); + var viewDragButton = $D('noVNC_view_drag_button'); if (UI.rfb.get_viewportDrag()) { - vmb.className = "noVNC_status_button"; + viewDragButton.className = "noVNC_status_button"; UI.rfb.set_viewportDrag(false); } else { - vmb.className = "noVNC_status_button_selected"; + viewDragButton.className = "noVNC_status_button_selected"; UI.rfb.set_viewportDrag(true); } }, +/* ------^------- + * /VIEWDRAG + * ============== + * KEYBOARD + * ------v------*/ + // On touch devices, show the OS keyboard showKeyboard: function() { - var kbi = $D('keyboardinput'); - var skb = $D('showKeyboard'); + var kbi = $D('noVNC_keyboardinput'); + var skb = $D('noVNC_keyboard_button'); var l = kbi.value.length; if(UI.keyboardVisible === false) { kbi.focus(); @@ -1051,19 +1063,29 @@ var UI; } }, + hideKeyboard: function() { + $D('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. + UI.hideKeyboardTimeout = setTimeout(function() { + UI.keyboardVisible = false; + },100); + }, + keepKeyboard: function() { clearTimeout(UI.hideKeyboardTimeout); if(UI.keyboardVisible === true) { - $D('keyboardinput').focus(); - $D('showKeyboard').className = "noVNC_status_button_selected"; + $D('noVNC_keyboardinput').focus(); + $D('noVNC_keyboard_button').className = "noVNC_status_button_selected"; } else if(UI.keyboardVisible === false) { - $D('keyboardinput').blur(); - $D('showKeyboard').className = "noVNC_status_button"; + $D('noVNC_keyboardinput').blur(); + $D('noVNC_keyboard_button').className = "noVNC_status_button"; } }, keyboardinputReset: function() { - var kbi = $D('keyboardinput'); + var kbi = $D('noVNC_keyboardinput'); kbi.value = new Array(UI.defaultKeyboardinputLen).join("_"); UI.lastKeyboardinput = kbi.value; }, @@ -1139,42 +1161,44 @@ var UI; } }, - keyInputBlur: function() { - $D('showKeyboard').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. - UI.hideKeyboardTimeout = setTimeout(function() { UI.setKeyboard(); },100); - }, - - showExtraKeys: function() { + toggleExtraKeys: function() { UI.keepKeyboard(); if(UI.extraKeysVisible === false) { - $D('toggleCtrlButton').style.display = "inline"; - $D('toggleAltButton').style.display = "inline"; - $D('sendTabButton').style.display = "inline"; - $D('sendEscButton').style.display = "inline"; - $D('showExtraKeysButton').className = "noVNC_status_button_selected"; + $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"; UI.extraKeysVisible = true; } else if(UI.extraKeysVisible === true) { - $D('toggleCtrlButton').style.display = ""; - $D('toggleAltButton').style.display = ""; - $D('sendTabButton').style.display = ""; - $D('sendEscButton').style.display = ""; - $D('showExtraKeysButton').className = "noVNC_status_button"; + $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"; UI.extraKeysVisible = false; } }, + sendEsc: function() { + UI.keepKeyboard(); + UI.rfb.sendKey(XK_Escape); + }, + + sendTab: function() { + UI.keepKeyboard(); + UI.rfb.sendKey(XK_Tab); + }, + toggleCtrl: function() { UI.keepKeyboard(); if(UI.ctrlOn === false) { UI.rfb.sendKey(XK_Control_L, true); - $D('toggleCtrlButton').className = "noVNC_status_button_selected"; + $D('noVNC_toggleCtrl_button').className = "noVNC_status_button_selected"; UI.ctrlOn = true; } else if(UI.ctrlOn === true) { UI.rfb.sendKey(XK_Control_L, false); - $D('toggleCtrlButton').className = "noVNC_status_button"; + $D('noVNC_toggleCtrl_button').className = "noVNC_status_button"; UI.ctrlOn = false; } }, @@ -1183,27 +1207,62 @@ var UI; UI.keepKeyboard(); if(UI.altOn === false) { UI.rfb.sendKey(XK_Alt_L, true); - $D('toggleAltButton').className = "noVNC_status_button_selected"; + $D('noVNC_toggleAlt_button').className = "noVNC_status_button_selected"; UI.altOn = true; } else if(UI.altOn === true) { UI.rfb.sendKey(XK_Alt_L, false); - $D('toggleAltButton').className = "noVNC_status_button"; + $D('noVNC_toggleAlt_button').className = "noVNC_status_button"; UI.altOn = false; } }, - sendTab: function() { - UI.keepKeyboard(); - UI.rfb.sendKey(XK_Tab); + sendCtrlAltDel: function() { + UI.rfb.sendCtrlAltDel(); }, - sendEsc: function() { - UI.keepKeyboard(); - UI.rfb.sendKey(XK_Escape); +/* ------^------- + * /KEYBOARD + * ============== + * MISC + * ------v------*/ + + setMouseButton: function(num) { + if (typeof num === 'undefined') { + // Disable mouse buttons + num = -1; + } + if (UI.rfb) { + UI.rfb.get_mouse().set_touchButton(num); + } + + var blist = [0, 1,2,4]; + for (var b = 0; b < blist.length; b++) { + var button = $D('noVNC_mouse_button' + blist[b]); + if (blist[b] === num) { + button.style.display = ""; + } else { + button.style.display = "none"; + } + } + }, + + displayBlur: function() { + if (!UI.rfb) return; + + UI.rfb.get_keyboard().set_focused(false); + UI.rfb.get_mouse().set_focused(false); + }, + + displayFocus: function() { + if (!UI.rfb) return; + + UI.rfb.get_keyboard().set_focused(true); + UI.rfb.get_mouse().set_focused(true); }, - setKeyboard: function() { - UI.keyboardVisible = false; + // Display the desktop name in the document title + updateDocumentTitle: function(rfb, name) { + document.title = name + " - noVNC"; }, //Helper to add options to dropdown. @@ -1215,12 +1274,16 @@ var UI; }, setBarPosition: function() { - $D('noVNC-control-bar').style.top = (window.pageYOffset) + 'px'; + $D('noVNC_control_bar').style.top = (window.pageYOffset) + 'px'; $D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px'; - var vncwidth = $D('noVNC_screen').style.offsetWidth; - $D('noVNC-control-bar').style.width = vncwidth + 'px'; + var vncwidth = $D('noVNC_container').style.offsetWidth; + $D('noVNC_control_bar').style.width = vncwidth + 'px'; } +/* ------^------- + * /MISC + * ============== + */ }; })(); @@ -5,7 +5,7 @@ <!-- noVNC example: simple example using default UI Copyright (C) 2012 Joel Martin - Copyright (C) 2013 Samuel Mannehed for Cendio AB + Copyright (C) 2016 Samuel Mannehed for Cendio AB noVNC is licensed under the MPL 2.0 (see LICENSE.txt) This file is licensed under the 2-Clause BSD license (see LICENSE.txt). @@ -16,20 +16,20 @@ --> <title>noVNC</title> - <meta charset="utf-8"> + <meta charset="utf-8" /> <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame Remove this if you use the .htaccess --> - <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <!-- Apple iOS Safari settings --> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <!-- App Start Icon --> <link rel="apple-touch-startup-image" href="images/screen_320x460.png" /> <!-- For iOS devices set the icon to use if user bookmarks app on their homescreen --> - <link rel="apple-touch-icon" href="images/screen_57x57.png"> + <link rel="apple-touch-icon" href="images/screen_57x57.png" /> <!-- <link rel="apple-touch-icon-precomposed" href="images/screen_57x57.png" /> --> @@ -48,42 +48,42 @@ </head> <body> - <div id="noVNC-control-bar" class="noVNC_status_normal"> + <div id="noVNC_control_bar" class="noVNC_status_normal"> <!--noVNC Mobile Device only Buttons--> - <div class="noVNC-buttons-left"> + <div class="noVNC_buttons_left"> <input type="image" alt="viewport drag" src="images/drag.png" id="noVNC_view_drag_button" class="noVNC_status_button" - title="Move/Drag Viewport"> + title="Move/Drag Viewport" /> <div id="noVNC_mobile_buttons"> <input type="image" alt="No mousebutton" src="images/mouse_none.png" - id="noVNC_mouse_button0" class="noVNC_status_button"> + id="noVNC_mouse_button0" class="noVNC_status_button" /> <input type="image" alt="Left mousebutton" src="images/mouse_left.png" - id="noVNC_mouse_button1" class="noVNC_status_button"> + id="noVNC_mouse_button1" class="noVNC_status_button" /> <input type="image" alt="Middle mousebutton" src="images/mouse_middle.png" - id="noVNC_mouse_button2" class="noVNC_status_button"> + id="noVNC_mouse_button2" class="noVNC_status_button" /> <input type="image" alt="Right mousebutton" src="images/mouse_right.png" - id="noVNC_mouse_button4" class="noVNC_status_button"> + id="noVNC_mouse_button4" class="noVNC_status_button" /> <input type="image" alt="Keyboard" src="images/keyboard.png" - id="showKeyboard" class="noVNC_status_button" - value="Keyboard" title="Show Keyboard"/> + id="noVNC_keyboard_button" class="noVNC_status_button" + value="Keyboard" title="Show Keyboard" /> <!-- Note that Google Chrome on Android doesn't respect any of these, html attributes which attempt to disable text suggestions on the on-screen keyboard. Let's hope Chrome implements the ime-mode style for example --> - <textarea id="keyboardinput" autocapitalize="off" + <textarea id="noVNC_keyboardinput" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" mozactionhint="Enter"></textarea> <div id="noVNC_extra_keys"> - <input type="image" alt="Extra keys" src="images/showextrakeys.png" - id="showExtraKeysButton" class="noVNC_status_button"> + <input type="image" alt="Extra keys" src="images/toggleextrakeys.png" + id="noVNC_toggleExtraKeys_button" class="noVNC_status_button" /> <input type="image" alt="Ctrl" src="images/ctrl.png" - id="toggleCtrlButton" class="noVNC_status_button"> + id="noVNC_toggleCtrl_button" class="noVNC_status_button" /> <input type="image" alt="Alt" src="images/alt.png" - id="toggleAltButton" class="noVNC_status_button"> + id="noVNC_toggleAlt_button" class="noVNC_status_button" /> <input type="image" alt="Tab" src="images/tab.png" - id="sendTabButton" class="noVNC_status_button"> + id="noVNC_sendTab_button" class="noVNC_status_button" /> <input type="image" alt="Esc" src="images/esc.png" - id="sendEscButton" class="noVNC_status_button"> + id="noVNC_sendEsc_button" class="noVNC_status_button" /> </div> </div> </div> @@ -91,27 +91,27 @@ <div id="noVNC_status"></div> <!--noVNC Buttons--> - <div class="noVNC-buttons-right"> + <div class="noVNC_buttons_right"> <input type="image" alt="Ctrl+Alt+Del" src="images/ctrlaltdel.png" - id="sendCtrlAltDelButton" class="noVNC_status_button" + id="noVNC_sendCtrlAltDel_button" class="noVNC_status_button" title="Send Ctrl-Alt-Del" /> <input type="image" alt="Shutdown/Reboot" src="images/power.png" - id="xvpButton" class="noVNC_status_button" + id="noVNC_toggleXvp_button" class="noVNC_status_button" title="Shutdown/Reboot..." /> <input type="image" alt="Clipboard" src="images/clipboard.png" - id="clipboardButton" class="noVNC_status_button" + id="noVNC_clipboard_button" class="noVNC_status_button" title="Clipboard" /> <input type="image" alt="Fullscreen" src="images/fullscreen.png" - id="fullscreenButton" class="noVNC_status_button" + id="noVNC_fullscreen_button" class="noVNC_status_button" title="Fullscreen" /> <input type="image" alt="Settings" src="images/settings.png" - id="settingsButton" class="noVNC_status_button" + id="noVNC_settings_button" class="noVNC_status_button" title="Settings" /> <input type="image" alt="Connect" src="images/connect.png" - id="connectButton" class="noVNC_status_button" + id="noVNC_connectPanel_button" class="noVNC_status_button" title="Connect" /> <input type="image" alt="Disconnect" src="images/disconnect.png" - id="disconnectButton" class="noVNC_status_button" + id="noVNC_disconnect_button" class="noVNC_status_button" title="Disconnect" /> </div> @@ -128,7 +128,7 @@ and <a href="http://kanaka.github.com/noVNC">website</a> for more information. <br /> - <input id="descriptionButton" type="button" value="Close"> + <input id="noVNC_description_button" type="button" value="Close" /> </div> <!-- Popup Status --> @@ -141,15 +141,15 @@ </textarea> <br /> <input id="noVNC_clipboard_clear_button" type="button" - value="Clear"> + value="Clear" /> </div> <!-- XVP Shutdown/Reboot Panel --> <div id="noVNC_xvp" class="triangle-right top"> <span id="noVNC_xvp_menu"> - <input type="button" id="xvpShutdownButton" value="Shutdown" /> - <input type="button" id="xvpRebootButton" value="Reboot" /> - <input type="button" id="xvpResetButton" value="Reset" /> + <input type="button" id="noVNC_xvpShutdown_button" value="Shutdown" /> + <input type="button" id="noVNC_xvpReboot_button" value="Reboot" /> + <input type="button" id="noVNC_xvpReset_button" value="Reset" /> </span> </div> @@ -157,38 +157,38 @@ <div id="noVNC_settings" class="triangle-right top"> <span id="noVNC_settings_menu"> <ul> - <li><input id="noVNC_encrypt" type="checkbox"> Encrypt</li> - <li><input id="noVNC_true_color" type="checkbox" checked> True Color</li> - <li><input id="noVNC_cursor" type="checkbox"> Local Cursor</li> - <li><input id="noVNC_clip" type="checkbox"> Clip to Window</li> - <li><input id="noVNC_shared" type="checkbox"> Shared Mode</li> - <li><input id="noVNC_view_only" type="checkbox"> View Only</li> + <li><input id="noVNC_setting_encrypt" type="checkbox" /> Encrypt</li> + <li><input id="noVNC_setting_true_color" type="checkbox" checked /> True Color</li> + <li><input id="noVNC_setting_cursor" type="checkbox" /> Local Cursor</li> + <li><input id="noVNC_setting_clip" type="checkbox" /> Clip to Window</li> + <li><input id="noVNC_setting_shared" type="checkbox" /> Shared Mode</li> + <li><input id="noVNC_setting_view_only" type="checkbox" /> View Only</li> <hr> - <li><input id="noVNC_path" type="input" value="websockify"> Path</li> + <li><input id="noVNC_setting_path" type="input" value="websockify" /> Path</li> <li><label> - <select id="noVNC_resize" name="vncResize"> + <select id="noVNC_setting_resize" name="vncResize"> <option value="off">None</option> <option value="scale">Local Scaling</option> <option value="downscale">Local Downscaling</option> <option value="remote">Remote Resizing</option> </select> Scaling Mode</label> </li> - <li><input id="noVNC_repeaterID" type="input" value=""> Repeater ID</li> + <li><input id="noVNC_setting_repeaterID" type="input" value="" /> Repeater ID</li> <hr> <!-- Stylesheet selection dropdown --> <li><label><strong>Style: </strong> - <select id="noVNC_stylesheet" name="vncStyle"> + <select id="noVNC_setting_stylesheet" name="vncStyle"> <option value="default">default</option> </select></label> </li> <!-- Logging selection dropdown --> <li><label><strong>Logging: </strong> - <select id="noVNC_logging" name="vncLogging"> + <select id="noVNC_setting_logging" name="vncLogging"> </select></label> </li> <hr> - <li><input type="button" id="noVNC_apply" value="Apply"></li> + <li><input type="button" id="noVNC_settings_apply" value="Apply" /></li> </ul> </span> </div> @@ -196,22 +196,22 @@ <!-- Connection Panel --> <div id="noVNC_controls" class="triangle-right top"> <ul> - <li><label><strong>Host: </strong><input id="noVNC_host" /></label></li> - <li><label><strong>Port: </strong><input id="noVNC_port" /></label></li> - <li><label><strong>Password: </strong><input id="noVNC_password" type="password" /></label></li> - <li><label><strong>Token: </strong><input id="noVNC_token"/></label></li> - <li><input id="noVNC_connect_button" type="button" value="Connect"></li> + <li><label><strong>Host: </strong><input id="noVNC_setting_host" /></label></li> + <li><label><strong>Port: </strong><input id="noVNC_setting_port" /></label></li> + <li><label><strong>Password: </strong><input id="noVNC_setting_password" type="password" /></label></li> + <li><label><strong>Token: </strong><input id="noVNC_setting_token" /></label></li> + <li><input id="noVNC_connect_button" type="button" value="Connect" /></li> </ul> </div> - </div> <!-- End of noVNC-control-bar --> + </div> <!-- End of noVNC_control_bar --> - <div id="noVNC_screen"> + <div id="noVNC_container"> <h1 id="noVNC_logo"><span>no</span><br />VNC</h1> <!-- HTML5 Canvas --> - <div id="noVNC_container"> + <div id="noVNC_screen"> <canvas id="noVNC_canvas" width="0" height="0"> Canvas not supported. </canvas> |