diff --git a/images/showextrakeys.png b/images/toggleextrakeys.png similarity index 100% rename from images/showextrakeys.png rename to images/toggleextrakeys.png diff --git a/include/base.css b/include/base.css index 2769357e..8d88c0f5 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 7d940c5a..5c4558dc 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 b2a0adcc..4ab53bde 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 7340fad2..c022969b 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 95bc1356..4fc6f09d 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("noVNC_keyboard_button").onclick = UI.showKeyboard; - $D("keyboardinput").oninput = UI.keyInput; - $D("keyboardinput").onblur = UI.keyInputBlur; - $D("keyboardinput").onsubmit = function () { return false; }; + $D("noVNC_keyboardinput").oninput = UI.keyInput; + $D("noVNC_keyboardinput").onblur = UI.hideKeyboard; + $D("noVNC_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("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("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_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 - - 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()); - } + 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(); }, - 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"; - - var pos = Util.getPosition(container); - var w = pos.width; - var h = pos.height; - - container.style.overflow = "visible"; - - if (isNaN(w) || isNaN(h)) { - return false; + //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 { - return {w: w, h: h}; + UI.updateSetting('cursor', !UI.isTouchDevice); + $D('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; + + 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); + } + + // 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"); }, - // 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; - } + popupStatus: function(text) { + var psp = $D('noVNC_popup_status'); + + clearTimeout(UI.popupStatusTimeout); + + if (typeof text === 'string') { + psp.innerHTML = text; + } else { + 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); + }, + + 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); - } - UI.updateSetting(name, val); - return val; - }, - // Force a setting to be a certain value forceSetting: function(name, val) { UI.updateSetting(name, val); return val; }, - - // Show the popup status - togglePopupStatus: function(text) { - var psp = $D('noVNC_popup_status'); - - var closePopup = function() { psp.style.display = "none"; }; - - if (window.getComputedStyle(psp).display === 'none') { - if (typeof text === 'string') { - psp.innerHTML = text; + // 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 { - psp.innerHTML = $D('noVNC_status').innerHTML; + val = true; } - psp.style.display = "block"; - psp.style.left = window.innerWidth/2 - - parseInt(window.getComputedStyle(psp).width)/2 -30 + "px"; + } + return val; + }, - // Show the popup for a maximum of 1.5 seconds - UI.popupStatusTimeout = setTimeout(function() { closePopup(); }, 1500); + // 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'); + + 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'); + + // 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"); + }, + + // 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 { - clearTimeout(UI.popupStatusTimeout); - closePopup(); + UI.updateSetting('encrypt'); + UI.updateSetting('true_color'); + if (Util.browserSupportsCursorURIs()) { + UI.updateSetting('cursor'); + } else { + UI.updateSetting('cursor', !UI.isTouchDevice); + $D('noVNC_setting_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'); + + 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,16 +628,140 @@ 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 + clipboardReceive: function(rfb, text) { + Util.Debug(">> UI.clipboardReceive: " + text.substr(0,40) + "..."); + $D('noVNC_clipboard_text').value = text; + Util.Debug("<< UI.clipboardReceive"); + }, + + 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 + $D('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"; + } + // Close clipboard panel if open + if (UI.clipboardOpen === true) { + UI.toggleClipboardPanel(); + } + // Close XVP panel if open + if (UI.xvpOpen === true) { + UI.toggleXvpPanel(); + } + + // Toggle Connection Panel + if (UI.connSettingsOpen === true) { + $D('noVNC_controls').style.display = "none"; + $D('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"; + UI.connSettingsOpen = true; + $D('noVNC_setting_host').focus(); + } + }, + + connect: function() { + 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; + + //if token is in path then ignore the new token variable + if (token) { + path = WebUtil.injectParamIfMissing(path, "token", token); + } + + if ((!host) || (!port)) { + throw new Error("Must set host and port"); + } + + if (!UI.initRFB()) return; + + 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.rfb.connect(host, port, password, path); + + //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_setting_password').value); + //Reset connect button. + $D('noVNC_connect_button').value = "Connect"; + $D('noVNC_connect_button').onclick = UI.connect; + //Hide connection panel. + UI.toggleConnectPanel(); + return false; + }, + +/* ------^------- + * /CONNECTION + * ============== + * FULLSCREEN + * ------v------*/ + toggleFullscreen: function() { if (document.fullscreenElement || // alternative standard method document.mozFullScreenElement || // currently working methods @@ -494,397 +796,97 @@ var UI; document.mozFullScreenElement || // currently working methods document.webkitFullscreenElement || document.msFullscreenElement ) { - $D('fullscreenButton').className = "noVNC_status_button_selected"; + $D('noVNC_fullscreen_button').className = "noVNC_status_button_selected"; } else { - $D('fullscreenButton').className = "noVNC_status_button"; + $D('noVNC_fullscreen_button').className = "noVNC_status_button"; } }, - // Show the connection settings panel/menu - toggleConnectPanel: function() { - // Close the description panel - $D('noVNC_description').style.display = "none"; - // Close connection settings if open - if (UI.settingsOpen === true) { - UI.settingsApply(); - UI.closeSettingsMenu(); - $D('connectButton').className = "noVNC_status_button"; - } - // Close clipboard panel if open - if (UI.clipboardOpen === true) { - UI.toggleClipboardPanel(); - } - // Close XVP panel if open - if (UI.xvpOpen === true) { - UI.toggleXvpPanel(); - } +/* ------^------- + * /FULLSCREEN + * ============== + * RESIZE + * ------v------*/ - // Toggle Connection Panel - if (UI.connSettingsOpen === true) { - $D('noVNC_controls').style.display = "none"; - $D('connectButton').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('connectButton').className = "noVNC_status_button_selected"; - UI.connSettingsOpen = true; - $D('noVNC_host').focus(); - } - }, + // Apply remote resizing or local scaling + applyResizeMode: function() { + if (!UI.rfb) return; - // 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'); + var screen = UI.screenSize(); - UI.openSettingsMenu(); - } - }, + if (screen && UI.rfb_state === 'normal' && UI.rfb.get_display()) { - // 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('settingsButton').className = "noVNC_status_button_selected"; - UI.settingsOpen = true; - }, + var display = UI.rfb.get_display(); + var resizeMode = UI.getSetting('resize'); - // Close menu (without applying settings) - closeSettingsMenu: function() { - $D('noVNC_settings').style.display = "none"; - $D('settingsButton').className = "noVNC_status_button"; - UI.settingsOpen = false; - }, + if (resizeMode === 'remote') { - // 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'); - } + // Request changing the resolution of the remote display to + // the size of the local browser viewport. - UI.saveSetting('resize'); + // 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(){ - if (UI.getSetting('resize') === 'downscale' || UI.getSetting('resize') === 'scale') { - UI.forceSetting('clip', false); - } + // Limit the viewport to the size of the browser window + display.set_maxWidth(screen.w); + display.set_maxHeight(screen.h); - UI.saveSetting('clip'); - UI.saveSetting('shared'); - UI.saveSetting('view_only'); - UI.saveSetting('path'); - UI.saveSetting('repeaterID'); - UI.saveSetting('stylesheet'); - UI.saveSetting('logging'); + Util.Debug('Attempting requestDesktopSize(' + + screen.w + ', ' + screen.h + ')'); - // 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"); - }, + // Request a remote size covering the viewport + UI.rfb.requestDesktopSize(screen.w, screen.h); + }, 500); - - - setPassword: function() { - UI.rfb.sendPassword($D('noVNC_password').value); - //Reset connect button. - $D('noVNC_connect_button').value = "Connect"; - $D('noVNC_connect_button').onclick = UI.connect; - //Hide connection panel. - UI.toggleConnectPanel(); - 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); - } - - 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"; + } 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()); } } }, - 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(); + // 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'); - $D('noVNC_connect_button').value = "Send Password"; - $D('noVNC_connect_button').onclick = UI.setPassword; - $D('noVNC_password').focus(); + // Hide the scrollbars until the size is calculated + screen.style.overflow = "hidden"; - klass = "noVNC_status_warn"; - break; - default: - klass = "noVNC_status_warn"; - break; - } + var pos = Util.getPosition(screen); + var w = pos.width; + var h = pos.height; - if (typeof(msg) !== 'undefined') { - $D('noVNC-control-bar').setAttribute("class", klass); - $D('noVNC_status').innerHTML = msg; - } + screen.style.overflow = "visible"; - 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; + if (isNaN(w) || isNaN(h)) { + return false; } else { - UI.updateSetting('cursor', !UI.isTouchDevice); - $D('noVNC_cursor').disabled = true; - } - - 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"); - }, - - // Disable/enable XVP button - updateXvpVisualState: function(ver) { - if (ver >= 1) { - $D('xvpButton').style.display = 'inline'; - } else { - $D('xvpButton').style.display = 'none'; - // Close XVP panel if open - if (UI.xvpOpen === true) { - UI.toggleXvpPanel(); - } + return {w: w, h: h}; } }, - // 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(); + // 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() { }); }, - // 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(); - - 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; - - //if token is in path then ignore the new token variable - if (token) { - path = WebUtil.injectParamIfMissing(path, "token", token); - } - - if ((!host) || (!port)) { - throw new Error("Must set host and port"); - } - - if (!UI.initRFB()) return; - - 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.rfb.connect(host, port, password, path); - - //Close dialog. - setTimeout(UI.setBarPosition, 100); - $D('noVNC_logo').style.display = "none"; - $D('noVNC_container').style.display = "inline"; - }, - - disconnect: function() { - UI.closeSettingsMenu(); - UI.rfb.disconnect(); - - // Restore the callback used for initial resize - UI.rfb.set_onFBUComplete(UI.FBUComplete); - - $D('noVNC_logo').style.display = "block"; - $D('noVNC_container').style.display = "none"; - - // Don't display the connection settings until we're actually disconnected - }, - - 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); - }, - - clipClear: function() { - $D('noVNC_clipboard_text').value = ""; - UI.rfb.clipboardPasteFrom(""); - }, - - 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"); - }, +/* ------^------- + * /RESIZE + * ============== + * CLIPPING + * ------v------*/ // Set and configure viewport clipping setViewClip: function(clip) { @@ -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"; + } + } }, - setKeyboard: function() { - UI.keyboardVisible = false; + 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); + }, + + // 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 + * ============== + */ }; })(); diff --git a/vnc.html b/vnc.html index f64c750c..0b653065 100644 --- a/vnc.html +++ b/vnc.html @@ -5,7 +5,7 @@