UI = {
- rfb_state: 'loaded',
+ connected: false,
+ desktopName: "",
resizeTimeout: null,
statusTimeout: null,
hideKeyboardTimeout: null,
- controlbarTimeout: null,
+ idleControlbarTimeout: null,
+ closeControlbarTimeout: null,
controlbarGrabbed: false,
controlbarDrag: false,
document.getElementById("noVNC_control_bar")
.addEventListener('keypress', UI.activateControlbar);
+ document.getElementById("noVNC_control_bar")
+ .addEventListener('mousedown', UI.keepControlbar);
+ document.getElementById("noVNC_control_bar")
+ .addEventListener('keypress', UI.keepControlbar);
+
document.getElementById("noVNC_view_drag_button")
.addEventListener('click', UI.toggleViewDrag);
- document.getElementById("noVNC_send_ctrl_alt_del_button")
- .addEventListener('click', UI.sendCtrlAltDel);
document.getElementById("noVNC_control_bar_handle")
.addEventListener('mousedown', UI.controlbarHandleMouseDown);
document.getElementById("noVNC_mouse_button4")
.addEventListener('click', function () { UI.setMouseButton(0); });
document.getElementById("noVNC_keyboard_button")
- .addEventListener('click', UI.showKeyboard);
+ .addEventListener('click', UI.toggleVirtualKeyboard);
document.getElementById("noVNC_keyboardinput")
.addEventListener('input', UI.keyInput);
document.getElementById("noVNC_keyboardinput")
- .addEventListener('blur', UI.hideKeyboard);
+ .addEventListener('blur', UI.onblurVirtualKeyboard);
document.getElementById("noVNC_keyboardinput")
.addEventListener('submit', function () { return false; });
document.getElementById("noVNC_control_bar")
.addEventListener('input', UI.activateControlbar);
+ document.getElementById("noVNC_control_bar")
+ .addEventListener('touchstart', UI.keepControlbar);
+ document.getElementById("noVNC_control_bar")
+ .addEventListener('input', UI.keepControlbar);
+
document.getElementById("noVNC_control_bar_handle")
.addEventListener('touchstart', UI.controlbarHandleMouseDown);
document.getElementById("noVNC_control_bar_handle")
.addEventListener('click', UI.sendTab);
document.getElementById("noVNC_send_esc_button")
.addEventListener('click', UI.sendEsc);
+ document.getElementById("noVNC_send_ctrl_alt_del_button")
+ .addEventListener('click', UI.sendCtrlAltDel);
},
addXvpHandlers: function() {
initRFB: function() {
try {
UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'),
+ 'onNotification': UI.notification,
'onUpdateState': UI.updateState,
+ 'onDisconnected': UI.disconnectFinished,
+ 'onPasswordRequired': UI.passwordRequired,
'onXvpInit': UI.updateXvpButton,
'onClipboard': UI.clipboardReceive,
'onFBUComplete': UI.initialResize,
'onFBResize': UI.updateViewDrag,
- 'onDesktopName': UI.updateDocumentTitle});
+ 'onDesktopName': UI.updateDesktopName});
return true;
} catch (exc) {
- UI.updateState(null, 'fatal', null, 'Unable to create RFB client -- ' + exc);
+ UI.showStatus('Unable to create RFB client -- ' + exc, 'error');
return false;
}
},
* VISUAL
* ------v------*/
- updateState: function(rfb, state, oldstate, msg) {
- UI.rfb_state = state;
-
- if (typeof(msg) !== 'undefined') {
- switch (state) {
- case 'failed':
- case 'fatal':
- // zero means no timeout
- UI.showStatus(msg, 'error', 0);
- break;
- case 'normal':
- /* falls through */
- case 'disconnected':
- case 'loaded':
- UI.showStatus(msg, 'normal');
- break;
- case 'password':
- document.getElementById('noVNC_password_dlg')
- .classList.add('noVNC_open');
- setTimeout(function () {
- document.getElementById(('noVNC_password_input').focus());
- }, 100);
-
- UI.showStatus(msg, 'warn');
- break;
- default:
- UI.showStatus(msg, 'warn');
- break;
- }
+ updateState: function(rfb, state, oldstate) {
+ switch (state) {
+ case 'connecting':
+ UI.showStatus("Connecting");
+ break;
+ case 'connected':
+ UI.connected = true;
+ if (rfb && rfb.get_encrypt()) {
+ UI.showStatus("Connected (encrypted) to " +
+ UI.desktopName);
+ } else {
+ UI.showStatus("Connected (unencrypted) to " +
+ UI.desktopName);
+ }
+ break;
+ case 'disconnecting':
+ UI.showStatus("Disconnecting");
+ break;
+ case 'disconnected':
+ UI.connected = false;
+ UI.showStatus("Disconnected");
+ break;
+ default:
+ UI.showStatus("Invalid state", 'error');
+ break;
}
UI.updateVisualState();
// Disable/enable controls depending on connection state
updateVisualState: function() {
- var connected = UI.rfb && UI.rfb_state === 'normal';
-
//Util.Debug(">> updateVisualState");
- document.getElementById('noVNC_setting_encrypt').disabled = connected;
- document.getElementById('noVNC_setting_true_color').disabled = connected;
+ document.getElementById('noVNC_setting_encrypt').disabled = UI.connected;
+ document.getElementById('noVNC_setting_true_color').disabled = UI.connected;
if (Util.browserSupportsCursorURIs()) {
- document.getElementById('noVNC_setting_cursor').disabled = connected;
+ document.getElementById('noVNC_setting_cursor').disabled = UI.connected;
} else {
UI.updateSetting('cursor', !UI.isTouchDevice);
document.getElementById('noVNC_setting_cursor').disabled = true;
}
UI.enableDisableViewClip();
- document.getElementById('noVNC_setting_resize').disabled = connected;
- document.getElementById('noVNC_setting_shared').disabled = connected;
- document.getElementById('noVNC_setting_view_only').disabled = connected;
- document.getElementById('noVNC_setting_path').disabled = connected;
- document.getElementById('noVNC_setting_repeaterID').disabled = connected;
+ document.getElementById('noVNC_setting_resize').disabled = UI.connected;
+ document.getElementById('noVNC_setting_shared').disabled = UI.connected;
+ document.getElementById('noVNC_setting_view_only').disabled = UI.connected;
+ document.getElementById('noVNC_setting_path').disabled = UI.connected;
+ document.getElementById('noVNC_setting_repeaterID').disabled = UI.connected;
- if (connected) {
+ if (UI.connected) {
document.documentElement.classList.add("noVNC_connected");
UI.updateViewClip();
UI.setMouseButton(1);
+
+ // Hide the controlbar after 2 seconds
+ UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
} else {
document.documentElement.classList.remove("noVNC_connected");
UI.updateXvpButton(0);
+ UI.keepControlbar();
}
// State change disables viewport dragging.
document.getElementById('noVNC_password_dlg')
.classList.remove('noVNC_open');
- switch (UI.rfb_state) {
- case 'fatal':
- case 'failed':
- case 'disconnected':
- UI.openConnectPanel();
- break;
- case 'loaded':
- break;
- default:
- break;
- }
-
//Util.Debug("<< updateVisualState");
},
time = 1500;
}
- // A specified time of zero means no timeout
- if (time != 0) {
+ // Error messages do not timeout
+ if (status_type !== 'error') {
UI.statusTimeout = window.setTimeout(UI.hideStatus, time);
}
},
document.getElementById('noVNC_status').classList.remove("noVNC_open");
},
- activateControlbar: function() {
- clearTimeout(UI.controlbarTimeout);
+ notification: function (rfb, msg, level, options) {
+ UI.showStatus(msg, level);
+ },
+
+ activateControlbar: function(event) {
+ clearTimeout(UI.idleControlbarTimeout);
// We manipulate the anchor instead of the actual control
// bar in order to avoid creating new a stacking group
document.getElementById('noVNC_control_bar_anchor')
.classList.remove("noVNC_idle");
- UI.controlbarTimeout = window.setTimeout(UI.idleControlbar, 2000);
+ UI.idleControlbarTimeout = window.setTimeout(UI.idleControlbar, 2000);
},
idleControlbar: function() {
.classList.add("noVNC_idle");
},
+ keepControlbar: function() {
+ clearTimeout(UI.closeControlbarTimeout);
+ },
+
openControlbar: function() {
document.getElementById('noVNC_control_bar')
.classList.add("noVNC_open");
},
controlbarHandleMouseUp: function(e) {
- if ((e.type == "mouseup") && (e.button != 0))
- return;
+ if ((e.type == "mouseup") && (e.button != 0)) return;
// mouseup and mousedown on the same place toggles the controlbar
if (UI.controlbarGrabbed && !UI.controlbarDrag) {
},
controlbarHandleMouseDown: function(e) {
- if ((e.type == "mousedown") && (e.button != 0))
- return;
+ if ((e.type == "mousedown") && (e.button != 0)) return;
var ptr = Util.getPointerEvent(e);
},
connect: function() {
- UI.closeAllPanels();
- UI.closeControlbar();
-
var host = document.getElementById('noVNC_setting_host').value;
var port = document.getElementById('noVNC_setting_port').value;
var password = document.getElementById('noVNC_setting_password').value;
}
if ((!host) || (!port)) {
- throw new Error("Must set host and port");
+ UI.showStatus("Must set host and port", 'error');
+ return;
}
if (!UI.initRFB()) return;
+ UI.closeAllPanels();
+
UI.rfb.set_encrypt(UI.getSetting('encrypt'));
UI.rfb.set_true_color(UI.getSetting('true_color'));
UI.rfb.set_local_cursor(UI.getSetting('cursor'));
// Don't display the connection settings until we're actually disconnected
},
+ disconnectFinished: function (rfb, reason) {
+ if (typeof reason !== 'undefined') {
+ UI.showStatus(reason, 'error');
+ }
+ UI.openConnectPanel();
+ },
+
+/* ------^-------
+ * /CONNECTION
+ * ==============
+ * PASSWORD
+ * ------v------*/
+
+ passwordRequired: function(rfb, msg) {
+
+ document.getElementById('noVNC_password_dlg')
+ .classList.add('noVNC_open');
+
+ setTimeout(function () {
+ document.getElementById('noVNC_password_input').focus();
+ }, 100);
+
+ if (typeof msg === 'undefined') {
+ msg = "Password is required";
+ }
+ UI.showStatus(msg, "warning");
+ },
+
setPassword: function() {
UI.rfb.sendPassword(document.getElementById('noVNC_password_input').value);
document.getElementById('noVNC_password_dlg')
},
/* ------^-------
- * /CONNECTION
+ * /PASSWORD
* ==============
* FULLSCREEN
* ------v------*/
var screen = UI.screenSize();
- if (screen && UI.rfb_state === 'normal' && UI.rfb.get_display()) {
+ if (screen && UI.connected && UI.rfb.get_display()) {
var display = UI.rfb.get_display();
var resizeMode = UI.getSetting('resize');
// Update parameters that depend on the clip setting
updateViewClip: function() {
var display;
- if (!UI.rfb) {
- return;
- }
+ if (!UI.rfb) return;
var display = UI.rfb.get_display();
var cur_clip = display.get_viewport();
// Handle special cases where clipping is forced on/off or locked
enableDisableViewClip: function() {
var resizeSetting = document.getElementById('noVNC_setting_resize');
- var connected = UI.rfb && UI.rfb_state === 'normal';
if (UI.isSafari) {
// Safari auto-hides the scrollbars which makes them
} else if (document.body.msRequestFullscreen && UI.rememberedClip !== null) {
// Restore view clip to what it was before fullscreen on IE
UI.setViewClip(UI.rememberedClipSetting);
- document.getElementById('noVNC_setting_clip').disabled = connected || UI.isTouchDevice;
+ document.getElementById('noVNC_setting_clip').disabled =
+ UI.connected || UI.isTouchDevice;
} else {
- document.getElementById('noVNC_setting_clip').disabled = connected || UI.isTouchDevice;
+ document.getElementById('noVNC_setting_clip').disabled =
+ UI.connected || UI.isTouchDevice;
if (UI.isTouchDevice) {
UI.setViewClip(true);
}
updateViewDrag: function() {
var clipping = false;
- if (UI.rfb_state !== 'normal') return;
+ if (!UI.connected) return;
// Check if viewport drag is possible. It is only possible
// if the remote display is clipping the client display.
* KEYBOARD
* ------v------*/
- // On touch devices, show the OS keyboard
- showKeyboard: function() {
- var kbi = document.getElementById('noVNC_keyboardinput');
- var skb = document.getElementById('noVNC_keyboard_button');
- var l = kbi.value.length;
- if(UI.keyboardVisible === false) {
- kbi.focus();
- try { kbi.setSelectionRange(l, l); } // Move the caret to the end
- catch (err) {} // setSelectionRange is undefined in Google Chrome
- UI.keyboardVisible = true;
- skb.classList.add("noVNC_selected");
- } else if(UI.keyboardVisible === true) {
- kbi.blur();
- skb.classList.remove("noVNC_selected");
- UI.keyboardVisible = false;
+ showVirtualKeyboard: function() {
+ if (!UI.isTouchDevice) return;
+
+ var input = document.getElementById('noVNC_keyboardinput');
+
+ if (document.activeElement == input) return;
+
+ UI.keyboardVisible = true;
+ document.getElementById('noVNC_keyboard_button')
+ .classList.add("noVNC_selected");
+ input.focus();
+
+ try {
+ var l = input.value.length;
+ // Move the caret to the end
+ input.setSelectionRange(l, l);
+ } catch (err) {} // setSelectionRange is undefined in Google Chrome
+ },
+
+ hideVirtualKeyboard: function() {
+ if (!UI.isTouchDevice) return;
+
+ var input = document.getElementById('noVNC_keyboardinput');
+
+ if (document.activeElement != input) return;
+
+ input.blur();
+ },
+
+ toggleVirtualKeyboard: function () {
+ if (UI.keyboardVisible) {
+ UI.hideVirtualKeyboard();
+ } else {
+ UI.showVirtualKeyboard();
}
},
- hideKeyboard: function() {
- document.getElementById('noVNC_keyboard_button')
- .classList.remove("noVNC_selected");
+ onblurVirtualKeyboard: function() {
//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;
+ document.getElementById('noVNC_keyboard_button')
+ .classList.remove("noVNC_selected");
},100);
},
keepKeyboard: function() {
clearTimeout(UI.hideKeyboardTimeout);
if(UI.keyboardVisible === true) {
- document.getElementById('noVNC_keyboardinput').focus();
- document.getElementById('noVNC_keyboard_button')
- .classList.add("noVNC_selected");
+ UI.showVirtualKeyboard();
} else if(UI.keyboardVisible === false) {
- document.getElementById('noVNC_keyboardinput').blur();
- document.getElementById('noVNC_keyboard_button')
- .classList.remove("noVNC_selected");
+ UI.hideVirtualKeyboard();
}
},
}
},
+/* ------^-------
+ * /KEYBOARD
+ * ==============
+ * EXTRA KEYS
+ * ------v------*/
+
openExtraKeys: function() {
UI.closeAllPanels();
UI.openControlbar();
},
sendCtrlAltDel: function() {
+ UI.keepKeyboard();
UI.rfb.sendCtrlAltDel();
},
/* ------^-------
- * /KEYBOARD
+ * /EXTRA KEYS
* ==============
* MISC
* ------v------*/
UI.rfb.get_mouse().set_focused(true);
},
- // Display the desktop name in the document title
- updateDocumentTitle: function(rfb, name) {
+ updateDesktopName: function(rfb, name) {
+ UI.desktopName = name;
+ // Display the desktop name in the document title
document.title = name + " - noVNC";
},