--- /dev/null
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Dominik Csapak <d.csapak@proxmox.com>
+Date: Tue, 13 Dec 2016 16:11:35 +0100
+Subject: [PATCH] add PVE specific JS code
+
+Add a ES6 module named `PVEUI` which defines the Proxmox VE
+related helper methods, like for example, API2Request.
+
+Hook the `PVEUI` module into the upstream `ui.js`, so that handlers
+for `autoresizing`, `commandstoggle`, etc., get setup.
+
+Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
+---
+ app/pve.js | 418 +++++++++++++++++++++++++++++++++++++++++++++++++++++
+ app/ui.js | 66 +++++++--
+ vnc.html | 10 +-
+ 3 files changed, 480 insertions(+), 14 deletions(-)
+ create mode 100644 app/pve.js
+
+diff --git a/app/pve.js b/app/pve.js
+new file mode 100644
+index 0000000..e2c37fb
+--- /dev/null
++++ b/app/pve.js
+@@ -0,0 +1,418 @@
++/*
++ * PVE Utility functions for noVNC
++ * Copyright (C) 2017 Proxmox GmbH
++ */
++
++import * as WebUtil from "./webutil.js";
++
++export default function PVEUI(UI){
++ this.consoletype = WebUtil.getQueryVar('console');
++ this.vmid = WebUtil.getQueryVar('vmid');
++ this.vmname = WebUtil.getQueryVar('vmname');
++ this.nodename = WebUtil.getQueryVar('node');
++ this.resize = WebUtil.getQueryVar('resize');
++ this.lastFBWidth = undefined;
++ this.lastFBHeight = undefined;
++ this.sizeUpdateTimer = undefined;
++ this.UI = UI;
++
++ var baseUrl = '/nodes/' + this.nodename;
++ var url;
++ var params = { websocket: 1 };
++ var title;
++
++ switch (this.consoletype) {
++ case 'kvm':
++ baseUrl += '/qemu/' + this.vmid;
++ url = baseUrl + '/vncproxy';
++ title = "VM " + this.vmid;
++ if (this.vmname) {
++ title += " ('" + this.vmname + "')";
++ }
++ break;
++ case 'lxc':
++ baseUrl += '/lxc/' + this.vmid;
++ url = baseUrl + '/vncproxy';
++ title = "CT " + this.vmid;
++ if (this.vmname) {
++ title += " ('" + this.vmname + "')";
++ }
++ break;
++ case 'shell':
++ url = baseUrl + '/vncshell';
++ title = "node '" + this.nodename + "'";
++ break;
++ case 'upgrade':
++ url = baseUrl + '/vncshell';
++ params.upgrade = 1;
++ title = 'System upgrade on node ' + this.nodename;
++ break;
++ default:
++ throw 'implement me';
++ break;
++ }
++
++ if (this.resize == 'scale' &&
++ (this.consoletype === 'lxc' || this.consoletype === 'shell')) {
++ var size = this.getFBSize();
++ params.width = size.width;
++ params.height = size.height;
++ }
++
++ this.baseUrl = baseUrl;
++ this.url = url;
++ this.params = params;
++ document.title = title;
++};
++
++PVEUI.prototype = {
++ urlEncode: function(object) {
++ var i,value, params = [];
++
++ for (i in object) {
++ if (object.hasOwnProperty(i)) {
++ value = object[i];
++ if (value === undefined) value = '';
++ params.push(encodeURIComponent(i) + '=' + encodeURIComponent(String(value)));
++ }
++ }
++
++ return params.join('&');
++ },
++
++ API2Request: function(reqOpts) {
++ var me = this;
++
++ reqOpts.method = reqOpts.method || 'GET';
++
++ var xhr = new XMLHttpRequest();
++
++ xhr.onload = function() {
++ var scope = reqOpts.scope || this;
++ var result;
++ var errmsg;
++
++ if (xhr.readyState === 4) {
++ var ctype = xhr.getResponseHeader('Content-Type');
++ if (xhr.status === 200) {
++ if (ctype.match(/application\/json;/)) {
++ result = JSON.parse(xhr.responseText);
++ } else {
++ errmsg = 'got unexpected content type ' + ctype;
++ }
++ } else {
++ errmsg = 'Error ' + xhr.status + ': ' + xhr.statusText;
++ }
++ } else {
++ errmsg = 'Connection error - server offline?';
++ }
++
++ if (errmsg !== undefined) {
++ if (reqOpts.failure) {
++ reqOpts.failure.call(scope, errmsg);
++ }
++ } else {
++ if (reqOpts.success) {
++ reqOpts.success.call(scope, result);
++ }
++ }
++ if (reqOpts.callback) {
++ reqOpts.callback.call(scope, errmsg === undefined);
++ }
++ }
++
++ var data = me.urlEncode(reqOpts.params || {});
++
++ if (reqOpts.method === 'GET') {
++ xhr.open(reqOpts.method, "/api2/json" + reqOpts.url + '?' + data);
++ } else {
++ xhr.open(reqOpts.method, "/api2/json" + reqOpts.url);
++ }
++ xhr.setRequestHeader('Cache-Control', 'no-cache');
++ if (reqOpts.method === 'POST' || reqOpts.method === 'PUT') {
++ xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
++ xhr.setRequestHeader('CSRFPreventionToken', PVE.CSRFPreventionToken);
++ xhr.send(data);
++ } else if (reqOpts.method === 'GET') {
++ xhr.send();
++ } else {
++ throw "unknown method";
++ }
++ },
++
++ pve_detect_migrated_vm: function() {
++ var me = this;
++ if (me.consoletype === 'kvm') {
++ // try to detect migrated VM
++ me.API2Request({
++ url: '/cluster/resources',
++ method: 'GET',
++ success: function(result) {
++ var list = result.data;
++ list.every(function(item) {
++ if (item.type === 'qemu' && item.vmid == me.vmid) {
++ var url = "?" + me.urlEncode({
++ console: me.consoletype,
++ novnc: 1,
++ vmid: me.vmid,
++ vmname: me.vmname,
++ node: item.node,
++ resize: me.resize
++ });
++ location.href = url;
++ return false; // break
++ }
++ return true;
++ });
++ }
++ });
++ } else if(me.consoletype === 'lxc') {
++ // lxc restart migration can take a while,
++ // so we need to find out if we are really migrating
++ var migrating;
++ var check = setInterval(function() {
++ if (migrating === undefined ||
++ migrating === true) {
++ // check (again) if migrating
++ me.UI.showStatus('Waiting for connection...', 'warning', 5000);
++ me.API2Request({
++ url: me.baseUrl + '/config',
++ method: 'GET',
++ success: function(result) {
++ var lock = result.data.lock;
++ if (lock == 'migrate') {
++ migrating = true;
++ me.UI.showStatus('Migration detected, waiting...', 'warning', 5000);
++ } else {
++ migrating = false;
++ }
++ },
++ failure: function() {
++ migrating = false;
++ }
++ });
++ } else {
++ // not migrating any more
++ me.UI.showStatus('Connection resumed', 'warning');
++ clearInterval(check);
++ me.API2Request({
++ url: '/cluster/resources',
++ method: 'GET',
++ success: function(result) {
++ var list = result.data;
++ list.every(function(item) {
++ if (item.type === 'lxc' && item.vmid == me.vmid) {
++ var url = "?" + me.urlEncode({
++ console: me.consoletype,
++ novnc: 1,
++ vmid: me.vmid,
++ vmname: me.vmname,
++ node: item.node,
++ resize: me.resize
++ });
++ location.href = url;
++ return false; // break
++ }
++ return true;
++ });
++ }
++ });
++ }
++ }, 5000);
++ }
++
++ },
++
++ pve_vm_command: function(cmd, params, reload) {
++ var me = this;
++ var baseUrl;
++ var confirmMsg = "";
++
++ switch(cmd) {
++ case "start":
++ reload = 1;
++ case "shutdown":
++ case "stop":
++ case "reset":
++ case "suspend":
++ case "resume":
++ confirmMsg = "Do you really want to " + cmd + " VM/CT {0}?";
++ break;
++ case "reload":
++ location.reload();
++ break;
++ default:
++ throw "implement me " + cmd;
++ }
++
++ confirmMsg = confirmMsg.replace('{0}', me.vmid);
++
++ if (confirmMsg !== "" && confirm(confirmMsg) !== true) {
++ return;
++ }
++
++ me.UI.closePVECommandPanel();
++
++ if (me.consoletype === 'kvm') {
++ baseUrl = '/nodes/' + me.nodename + '/qemu/' + me.vmid;
++ } else if (me.consoletype === 'lxc') {
++ baseUrl = '/nodes/' + me.nodename + '/lxc/' + me.vmid;
++ } else {
++ throw "unknown VM type";
++ }
++
++ me.API2Request({
++ params: params,
++ url: baseUrl + "/status/" + cmd,
++ method: 'POST',
++ failure: function(msg) {
++ me.UI.showStatus(msg, 'warning');
++ },
++ success: function() {
++ me.UI.showStatus("VM command '" + cmd +"' successful", 'normal');
++ if (reload) {
++ setTimeout(function() {
++ location.reload();
++ }, 1000);
++ };
++ }
++ });
++ },
++
++ addPVEHandlers: function() {
++ var me = this;
++ document.getElementById('pve_commands_button')
++ .addEventListener('click', me.UI.togglePVECommandPanel);
++
++ // show/hide the buttons
++ document.getElementById('noVNC_disconnect_button')
++ .classList.add('noVNC_hidden');
++ if (me.consoletype === 'kvm') {
++ document.getElementById('noVNC_clipboard_button')
++ .classList.add('noVNC_hidden');
++ }
++
++ if (me.consoletype === 'shell' || me.consoletype === 'upgrade') {
++ document.getElementById('pve_commands_button')
++ .classList.add('noVNC_hidden');
++ }
++
++ // add command logic
++ var commandArray = [
++ { cmd: 'start', kvm: 1, lxc: 1},
++ { cmd: 'stop', kvm: 1, lxc: 1},
++ { cmd: 'shutdown', kvm: 1, lxc: 1},
++ { cmd: 'suspend', kvm: 1},
++ { cmd: 'resume', kvm: 1},
++ { cmd: 'reset', kvm: 1},
++ { cmd: 'reload', kvm: 1, lxc: 1, shell: 1},
++ ];
++
++ commandArray.forEach(function(item) {
++ var el = document.getElementById('pve_command_'+item.cmd);
++ if (!el) {
++ return;
++ }
++
++ if (item[me.consoletype] === 1) {
++ el.onclick = function() {
++ me.pve_vm_command(item.cmd);
++ };
++ } else {
++ el.classList.add('noVNC_hidden');
++ }
++ });
++ },
++
++ getFBSize: function() {
++ var oh;
++ var ow;
++
++ if (window.innerHeight) {
++ oh = window.innerHeight;
++ ow = window.innerWidth;
++ } else if (document.documentElement &&
++ document.documentElement.clientHeight) {
++ oh = document.documentElement.clientHeight;
++ ow = document.documentElement.clientWidth;
++ } else if (document.body) {
++ oh = document.body.clientHeight;
++ ow = document.body.clientWidth;
++ } else {
++ throw "can't get window size";
++ }
++
++ return { width: ow, height: oh };
++ },
++
++ pveStart: function(callback) {
++ var me = this;
++ me.API2Request({
++ url: me.url,
++ method: 'POST',
++ params: me.params,
++ success: function(result) {
++ var wsparams = me.urlEncode({
++ port: result.data.port,
++ vncticket: result.data.ticket
++ });
++
++ document.getElementById('noVNC_password_input').value = result.data.ticket;
++ me.UI.forceSetting('path', 'api2/json' + me.baseUrl + '/vncwebsocket' + "?" + wsparams);
++
++ callback();
++ },
++ failure: function(msg) {
++ me.UI.showStatus(msg, 'error');
++ }
++ });
++ },
++
++ updateFBSize: function(rfb, width, height) {
++ var me = this;
++ try {
++ // Note: window size must be even number for firefox
++ me.lastFBWidth = Math.floor((width + 1)/2)*2;
++ me.lastFBHeight = Math.floor((height + 1)/2)*2;
++
++ if (me.sizeUpdateTimer !== undefined) {
++ clearInterval(me.sizeUpdateTimer);
++ }
++
++ var update_size = function() {
++ var clip = me.UI.getSetting('view_clip');
++ var resize = me.UI.getSetting('resize');
++ var autoresize = me.UI.getSetting('autoresize');
++ if (clip || resize === 'scale' || !autoresize) {
++ return;
++ }
++
++ // we do not want to resize if we are in fullscreen
++ if (document.fullscreenElement || // alternative standard method
++ document.mozFullScreenElement || // currently working methods
++ document.webkitFullscreenElement ||
++ document.msFullscreenElement) {
++ return;
++ }
++
++ var oldsize = me.getFBSize();
++ var offsetw = me.lastFBWidth - oldsize.width;
++ var offseth = me.lastFBHeight - oldsize.height;
++ if (offsetw !== 0 || offseth !== 0) {
++ //console.log("try resize by " + offsetw + " " + offseth);
++ try {
++ window.resizeBy(offsetw, offseth);
++ } catch (e) {
++ console.log('resizing did not work', e);
++ }
++ }
++ };
++
++ update_size();
++ me.sizeUpdateTimer = setInterval(update_size, 1000);
++
++ } catch(e) {
++ console.log(e);
++ }
++ },
++};
+diff --git a/app/ui.js b/app/ui.js
+index c70743d..317f845 100644
+--- a/app/ui.js
++++ b/app/ui.js
+@@ -16,6 +16,7 @@ import keysyms from "../core/input/keysymdef.js";
+ import Keyboard from "../core/input/keyboard.js";
+ import RFB from "../core/rfb.js";
+ import * as WebUtil from "./webutil.js";
++import PVEUI from "./pve.js";
+
+ const PAGE_TITLE = "noVNC";
+
+@@ -56,6 +57,8 @@ const UI = {
+ // Render default UI and initialize settings menu
+ start() {
+
++ UI.PVE = new PVEUI(UI);
++
+ UI.initSettings();
+
+ // Translate the DOM
+@@ -94,6 +97,9 @@ const UI = {
+ UI.addConnectionControlHandlers();
+ UI.addClipboardHandlers();
+ UI.addSettingsHandlers();
++
++ // add pve specific event handlers
++ UI.PVE.addPVEHandlers();
+ document.getElementById("noVNC_status")
+ .addEventListener('click', UI.hideStatus);
+
+@@ -102,19 +108,15 @@ const UI = {
+
+ UI.openControlbar();
+
++ UI.updateViewClip();
++
+ UI.updateVisualState('init');
+
+ document.documentElement.classList.remove("noVNC_loading");
+
+- let autoconnect = WebUtil.getConfigVar('autoconnect', false);
+- if (autoconnect === 'true' || autoconnect == '1') {
+- autoconnect = true;
++ UI.PVE.pveStart(function() {
+ UI.connect();
+- } else {
+- autoconnect = false;
+- // Show the connect panel on first load unless autoconnecting
+- UI.openConnectPanel();
+- }
++ });
+
+ return Promise.resolve(UI.rfb);
+ },
+@@ -158,11 +160,12 @@ const UI = {
+ /* Populate the controls if defaults are provided in the URL */
+ UI.initSetting('host', window.location.hostname);
+ UI.initSetting('port', port);
+- UI.initSetting('encrypt', (window.location.protocol === "https:"));
++ UI.initSetting('encrypt', true);
+ UI.initSetting('view_clip', false);
+ UI.initSetting('resize', 'off');
+ UI.initSetting('quality', 6);
+ UI.initSetting('compression', 2);
++ UI.initSetting('autoresize', true);
+ UI.initSetting('shared', true);
+ UI.initSetting('view_only', false);
+ UI.initSetting('show_dot', false);
+@@ -341,6 +344,7 @@ const UI = {
+ UI.addSettingChangeHandler('resize');
+ UI.addSettingChangeHandler('resize', UI.applyResizeMode);
+ UI.addSettingChangeHandler('resize', UI.updateViewClip);
++ UI.addSettingChangeHandler('autoresize');
+ UI.addSettingChangeHandler('quality');
+ UI.addSettingChangeHandler('quality', UI.updateQuality);
+ UI.addSettingChangeHandler('compression');
+@@ -395,6 +399,9 @@ const UI = {
+ document.documentElement.classList.add("noVNC_connecting");
+ break;
+ case 'connected':
++ UI.connected = true;
++ UI.inhibit_reconnect = false;
++ UI.pveAllowMigratedTest = true;
+ document.documentElement.classList.add("noVNC_connected");
+ break;
+ case 'disconnecting':
+@@ -402,6 +409,11 @@ const UI = {
+ document.documentElement.classList.add("noVNC_disconnecting");
+ break;
+ case 'disconnected':
++ UI.showStatus(_("Disconnected"));
++ if (UI.pveAllowMigratedTest === true) {
++ UI.pveAllowMigratedTest = false;
++ UI.PVE.pve_detect_migrated_vm();
++ }
+ break;
+ case 'reconnecting':
+ transitionElem.textContent = _("Reconnecting...");
+@@ -820,6 +832,7 @@ const UI = {
+ UI.closePowerPanel();
+ UI.closeClipboardPanel();
+ UI.closeExtraKeys();
++ UI.closePVECommandPanel();
+ },
+
+ /* ------^-------
+@@ -997,6 +1010,12 @@ const UI = {
+ UI.reconnectPassword = password;
+ }
+
++ var password = document.getElementById('noVNC_password_input').value;
++
++ if (!password) {
++ password = WebUtil.getConfigVar('password');
++ }
++
+ if (password === null) {
+ password = undefined;
+ }
+@@ -1621,9 +1640,36 @@ const UI = {
+ /* ------^-------
+ * /EXTRA KEYS
+ * ==============
+- * MISC
++ * PVE
+ * ------v------*/
+
++ togglePVECommandPanel: function() {
++ if (document.getElementById('pve_commands').classList.contains("noVNC_open")) {
++ UI.closePVECommandPanel();
++ } else {
++ UI.openPVECommandPanel();
++ }
++ },
++
++ openPVECommandPanel: function() {
++ var me = this;
++ UI.closeAllPanels();
++ UI.openControlbar();
++
++ document.getElementById('pve_commands').classList.add("noVNC_open");
++ document.getElementById('pve_commands_button').classList.add("noVNC_selected");
++ },
++
++ closePVECommandPanel: function() {
++ document.getElementById('pve_commands').classList.remove("noVNC_open");
++ document.getElementById('pve_commands_button').classList.remove("noVNC_selected");
++ },
++
++/* ------^-------
++ * /PVE
++ * ==============
++ * MISC
++ * ------v------*/
+ updateViewOnly() {
+ if (!UI.rfb) return;
+ UI.rfb.viewOnly = UI.getSetting('view_only');
+diff --git a/vnc.html b/vnc.html
+index 32f356f..5ec354a 100644
+--- a/vnc.html
++++ b/vnc.html
+@@ -171,7 +171,7 @@
+ <li class="noVNC_heading">
+ <img alt="" src="app/images/settings.svg"> Settings
+ </li>
+- <li>
++ <li style="display:none;">
+ <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
+ </li>
+ <li>
+@@ -181,16 +181,18 @@
+ <li>
+ <label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
+ </li>
++ <li>
++ <label><input id="noVNC_setting_autoresize" type="checkbox" /> Autoresize Window</label>
++ </li>
+ <li>
+ <label for="noVNC_setting_resize">Scaling Mode:</label>
+ <select id="noVNC_setting_resize" name="vncResize">
+- <option value="off">None</option>
++ <option value="off">Off</option>
+ <option value="scale">Local Scaling</option>
+- <option value="remote">Remote Resizing</option>
+ </select>
+ </li>
+ <li><hr></li>
+- <li>
++ <li style="display:none;">
+ <div class="noVNC_expander">Advanced</div>
+ <div><ul>
+ <li>
+++ /dev/null
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Dominik Csapak <d.csapak@proxmox.com>
-Date: Tue, 13 Dec 2016 16:11:35 +0100
-Subject: [PATCH 01/12] add pve specific js code
-
-this adds a es6 module 'PVEUI' which we use for defining the pve related
-methods (API2Request, etc.)
-
-we also modify ui.js so that it uses this module and sets up our
-autoresizing, commandstoggle, etc.
-
-Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
----
- app/pve.js | 418 +++++++++++++++++++++++++++++++++++++++++++++++++++++
- app/ui.js | 66 +++++++--
- vnc.html | 10 +-
- 3 files changed, 480 insertions(+), 14 deletions(-)
- create mode 100644 app/pve.js
-
-diff --git a/app/pve.js b/app/pve.js
-new file mode 100644
-index 0000000..e2c37fb
---- /dev/null
-+++ b/app/pve.js
-@@ -0,0 +1,418 @@
-+/*
-+ * PVE Utility functions for noVNC
-+ * Copyright (C) 2017 Proxmox GmbH
-+ */
-+
-+import * as WebUtil from "./webutil.js";
-+
-+export default function PVEUI(UI){
-+ this.consoletype = WebUtil.getQueryVar('console');
-+ this.vmid = WebUtil.getQueryVar('vmid');
-+ this.vmname = WebUtil.getQueryVar('vmname');
-+ this.nodename = WebUtil.getQueryVar('node');
-+ this.resize = WebUtil.getQueryVar('resize');
-+ this.lastFBWidth = undefined;
-+ this.lastFBHeight = undefined;
-+ this.sizeUpdateTimer = undefined;
-+ this.UI = UI;
-+
-+ var baseUrl = '/nodes/' + this.nodename;
-+ var url;
-+ var params = { websocket: 1 };
-+ var title;
-+
-+ switch (this.consoletype) {
-+ case 'kvm':
-+ baseUrl += '/qemu/' + this.vmid;
-+ url = baseUrl + '/vncproxy';
-+ title = "VM " + this.vmid;
-+ if (this.vmname) {
-+ title += " ('" + this.vmname + "')";
-+ }
-+ break;
-+ case 'lxc':
-+ baseUrl += '/lxc/' + this.vmid;
-+ url = baseUrl + '/vncproxy';
-+ title = "CT " + this.vmid;
-+ if (this.vmname) {
-+ title += " ('" + this.vmname + "')";
-+ }
-+ break;
-+ case 'shell':
-+ url = baseUrl + '/vncshell';
-+ title = "node '" + this.nodename + "'";
-+ break;
-+ case 'upgrade':
-+ url = baseUrl + '/vncshell';
-+ params.upgrade = 1;
-+ title = 'System upgrade on node ' + this.nodename;
-+ break;
-+ default:
-+ throw 'implement me';
-+ break;
-+ }
-+
-+ if (this.resize == 'scale' &&
-+ (this.consoletype === 'lxc' || this.consoletype === 'shell')) {
-+ var size = this.getFBSize();
-+ params.width = size.width;
-+ params.height = size.height;
-+ }
-+
-+ this.baseUrl = baseUrl;
-+ this.url = url;
-+ this.params = params;
-+ document.title = title;
-+};
-+
-+PVEUI.prototype = {
-+ urlEncode: function(object) {
-+ var i,value, params = [];
-+
-+ for (i in object) {
-+ if (object.hasOwnProperty(i)) {
-+ value = object[i];
-+ if (value === undefined) value = '';
-+ params.push(encodeURIComponent(i) + '=' + encodeURIComponent(String(value)));
-+ }
-+ }
-+
-+ return params.join('&');
-+ },
-+
-+ API2Request: function(reqOpts) {
-+ var me = this;
-+
-+ reqOpts.method = reqOpts.method || 'GET';
-+
-+ var xhr = new XMLHttpRequest();
-+
-+ xhr.onload = function() {
-+ var scope = reqOpts.scope || this;
-+ var result;
-+ var errmsg;
-+
-+ if (xhr.readyState === 4) {
-+ var ctype = xhr.getResponseHeader('Content-Type');
-+ if (xhr.status === 200) {
-+ if (ctype.match(/application\/json;/)) {
-+ result = JSON.parse(xhr.responseText);
-+ } else {
-+ errmsg = 'got unexpected content type ' + ctype;
-+ }
-+ } else {
-+ errmsg = 'Error ' + xhr.status + ': ' + xhr.statusText;
-+ }
-+ } else {
-+ errmsg = 'Connection error - server offline?';
-+ }
-+
-+ if (errmsg !== undefined) {
-+ if (reqOpts.failure) {
-+ reqOpts.failure.call(scope, errmsg);
-+ }
-+ } else {
-+ if (reqOpts.success) {
-+ reqOpts.success.call(scope, result);
-+ }
-+ }
-+ if (reqOpts.callback) {
-+ reqOpts.callback.call(scope, errmsg === undefined);
-+ }
-+ }
-+
-+ var data = me.urlEncode(reqOpts.params || {});
-+
-+ if (reqOpts.method === 'GET') {
-+ xhr.open(reqOpts.method, "/api2/json" + reqOpts.url + '?' + data);
-+ } else {
-+ xhr.open(reqOpts.method, "/api2/json" + reqOpts.url);
-+ }
-+ xhr.setRequestHeader('Cache-Control', 'no-cache');
-+ if (reqOpts.method === 'POST' || reqOpts.method === 'PUT') {
-+ xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-+ xhr.setRequestHeader('CSRFPreventionToken', PVE.CSRFPreventionToken);
-+ xhr.send(data);
-+ } else if (reqOpts.method === 'GET') {
-+ xhr.send();
-+ } else {
-+ throw "unknown method";
-+ }
-+ },
-+
-+ pve_detect_migrated_vm: function() {
-+ var me = this;
-+ if (me.consoletype === 'kvm') {
-+ // try to detect migrated VM
-+ me.API2Request({
-+ url: '/cluster/resources',
-+ method: 'GET',
-+ success: function(result) {
-+ var list = result.data;
-+ list.every(function(item) {
-+ if (item.type === 'qemu' && item.vmid == me.vmid) {
-+ var url = "?" + me.urlEncode({
-+ console: me.consoletype,
-+ novnc: 1,
-+ vmid: me.vmid,
-+ vmname: me.vmname,
-+ node: item.node,
-+ resize: me.resize
-+ });
-+ location.href = url;
-+ return false; // break
-+ }
-+ return true;
-+ });
-+ }
-+ });
-+ } else if(me.consoletype === 'lxc') {
-+ // lxc restart migration can take a while,
-+ // so we need to find out if we are really migrating
-+ var migrating;
-+ var check = setInterval(function() {
-+ if (migrating === undefined ||
-+ migrating === true) {
-+ // check (again) if migrating
-+ me.UI.showStatus('Waiting for connection...', 'warning', 5000);
-+ me.API2Request({
-+ url: me.baseUrl + '/config',
-+ method: 'GET',
-+ success: function(result) {
-+ var lock = result.data.lock;
-+ if (lock == 'migrate') {
-+ migrating = true;
-+ me.UI.showStatus('Migration detected, waiting...', 'warning', 5000);
-+ } else {
-+ migrating = false;
-+ }
-+ },
-+ failure: function() {
-+ migrating = false;
-+ }
-+ });
-+ } else {
-+ // not migrating any more
-+ me.UI.showStatus('Connection resumed', 'warning');
-+ clearInterval(check);
-+ me.API2Request({
-+ url: '/cluster/resources',
-+ method: 'GET',
-+ success: function(result) {
-+ var list = result.data;
-+ list.every(function(item) {
-+ if (item.type === 'lxc' && item.vmid == me.vmid) {
-+ var url = "?" + me.urlEncode({
-+ console: me.consoletype,
-+ novnc: 1,
-+ vmid: me.vmid,
-+ vmname: me.vmname,
-+ node: item.node,
-+ resize: me.resize
-+ });
-+ location.href = url;
-+ return false; // break
-+ }
-+ return true;
-+ });
-+ }
-+ });
-+ }
-+ }, 5000);
-+ }
-+
-+ },
-+
-+ pve_vm_command: function(cmd, params, reload) {
-+ var me = this;
-+ var baseUrl;
-+ var confirmMsg = "";
-+
-+ switch(cmd) {
-+ case "start":
-+ reload = 1;
-+ case "shutdown":
-+ case "stop":
-+ case "reset":
-+ case "suspend":
-+ case "resume":
-+ confirmMsg = "Do you really want to " + cmd + " VM/CT {0}?";
-+ break;
-+ case "reload":
-+ location.reload();
-+ break;
-+ default:
-+ throw "implement me " + cmd;
-+ }
-+
-+ confirmMsg = confirmMsg.replace('{0}', me.vmid);
-+
-+ if (confirmMsg !== "" && confirm(confirmMsg) !== true) {
-+ return;
-+ }
-+
-+ me.UI.closePVECommandPanel();
-+
-+ if (me.consoletype === 'kvm') {
-+ baseUrl = '/nodes/' + me.nodename + '/qemu/' + me.vmid;
-+ } else if (me.consoletype === 'lxc') {
-+ baseUrl = '/nodes/' + me.nodename + '/lxc/' + me.vmid;
-+ } else {
-+ throw "unknown VM type";
-+ }
-+
-+ me.API2Request({
-+ params: params,
-+ url: baseUrl + "/status/" + cmd,
-+ method: 'POST',
-+ failure: function(msg) {
-+ me.UI.showStatus(msg, 'warning');
-+ },
-+ success: function() {
-+ me.UI.showStatus("VM command '" + cmd +"' successful", 'normal');
-+ if (reload) {
-+ setTimeout(function() {
-+ location.reload();
-+ }, 1000);
-+ };
-+ }
-+ });
-+ },
-+
-+ addPVEHandlers: function() {
-+ var me = this;
-+ document.getElementById('pve_commands_button')
-+ .addEventListener('click', me.UI.togglePVECommandPanel);
-+
-+ // show/hide the buttons
-+ document.getElementById('noVNC_disconnect_button')
-+ .classList.add('noVNC_hidden');
-+ if (me.consoletype === 'kvm') {
-+ document.getElementById('noVNC_clipboard_button')
-+ .classList.add('noVNC_hidden');
-+ }
-+
-+ if (me.consoletype === 'shell' || me.consoletype === 'upgrade') {
-+ document.getElementById('pve_commands_button')
-+ .classList.add('noVNC_hidden');
-+ }
-+
-+ // add command logic
-+ var commandArray = [
-+ { cmd: 'start', kvm: 1, lxc: 1},
-+ { cmd: 'stop', kvm: 1, lxc: 1},
-+ { cmd: 'shutdown', kvm: 1, lxc: 1},
-+ { cmd: 'suspend', kvm: 1},
-+ { cmd: 'resume', kvm: 1},
-+ { cmd: 'reset', kvm: 1},
-+ { cmd: 'reload', kvm: 1, lxc: 1, shell: 1},
-+ ];
-+
-+ commandArray.forEach(function(item) {
-+ var el = document.getElementById('pve_command_'+item.cmd);
-+ if (!el) {
-+ return;
-+ }
-+
-+ if (item[me.consoletype] === 1) {
-+ el.onclick = function() {
-+ me.pve_vm_command(item.cmd);
-+ };
-+ } else {
-+ el.classList.add('noVNC_hidden');
-+ }
-+ });
-+ },
-+
-+ getFBSize: function() {
-+ var oh;
-+ var ow;
-+
-+ if (window.innerHeight) {
-+ oh = window.innerHeight;
-+ ow = window.innerWidth;
-+ } else if (document.documentElement &&
-+ document.documentElement.clientHeight) {
-+ oh = document.documentElement.clientHeight;
-+ ow = document.documentElement.clientWidth;
-+ } else if (document.body) {
-+ oh = document.body.clientHeight;
-+ ow = document.body.clientWidth;
-+ } else {
-+ throw "can't get window size";
-+ }
-+
-+ return { width: ow, height: oh };
-+ },
-+
-+ pveStart: function(callback) {
-+ var me = this;
-+ me.API2Request({
-+ url: me.url,
-+ method: 'POST',
-+ params: me.params,
-+ success: function(result) {
-+ var wsparams = me.urlEncode({
-+ port: result.data.port,
-+ vncticket: result.data.ticket
-+ });
-+
-+ document.getElementById('noVNC_password_input').value = result.data.ticket;
-+ me.UI.forceSetting('path', 'api2/json' + me.baseUrl + '/vncwebsocket' + "?" + wsparams);
-+
-+ callback();
-+ },
-+ failure: function(msg) {
-+ me.UI.showStatus(msg, 'error');
-+ }
-+ });
-+ },
-+
-+ updateFBSize: function(rfb, width, height) {
-+ var me = this;
-+ try {
-+ // Note: window size must be even number for firefox
-+ me.lastFBWidth = Math.floor((width + 1)/2)*2;
-+ me.lastFBHeight = Math.floor((height + 1)/2)*2;
-+
-+ if (me.sizeUpdateTimer !== undefined) {
-+ clearInterval(me.sizeUpdateTimer);
-+ }
-+
-+ var update_size = function() {
-+ var clip = me.UI.getSetting('view_clip');
-+ var resize = me.UI.getSetting('resize');
-+ var autoresize = me.UI.getSetting('autoresize');
-+ if (clip || resize === 'scale' || !autoresize) {
-+ return;
-+ }
-+
-+ // we do not want to resize if we are in fullscreen
-+ if (document.fullscreenElement || // alternative standard method
-+ document.mozFullScreenElement || // currently working methods
-+ document.webkitFullscreenElement ||
-+ document.msFullscreenElement) {
-+ return;
-+ }
-+
-+ var oldsize = me.getFBSize();
-+ var offsetw = me.lastFBWidth - oldsize.width;
-+ var offseth = me.lastFBHeight - oldsize.height;
-+ if (offsetw !== 0 || offseth !== 0) {
-+ //console.log("try resize by " + offsetw + " " + offseth);
-+ try {
-+ window.resizeBy(offsetw, offseth);
-+ } catch (e) {
-+ console.log('resizing did not work', e);
-+ }
-+ }
-+ };
-+
-+ update_size();
-+ me.sizeUpdateTimer = setInterval(update_size, 1000);
-+
-+ } catch(e) {
-+ console.log(e);
-+ }
-+ },
-+};
-diff --git a/app/ui.js b/app/ui.js
-index 17ec48d..4683c02 100644
---- a/app/ui.js
-+++ b/app/ui.js
-@@ -16,6 +16,7 @@ import keysyms from "../core/input/keysymdef.js";
- import Keyboard from "../core/input/keyboard.js";
- import RFB from "../core/rfb.js";
- import * as WebUtil from "./webutil.js";
-+import PVEUI from "./pve.js";
-
- const UI = {
-
-@@ -54,6 +55,8 @@ const UI = {
- // Render default UI and initialize settings menu
- start() {
-
-+ UI.PVE = new PVEUI(UI);
-+
- UI.initSettings();
-
- // Translate the DOM
-@@ -81,6 +84,9 @@ const UI = {
- UI.addConnectionControlHandlers();
- UI.addClipboardHandlers();
- UI.addSettingsHandlers();
-+
-+ // add pve specific event handlers
-+ UI.PVE.addPVEHandlers();
- document.getElementById("noVNC_status")
- .addEventListener('click', UI.hideStatus);
-
-@@ -89,19 +95,15 @@ const UI = {
-
- UI.openControlbar();
-
-+ UI.updateViewClip();
-+
- UI.updateVisualState('init');
-
- document.documentElement.classList.remove("noVNC_loading");
-
-- let autoconnect = WebUtil.getConfigVar('autoconnect', false);
-- if (autoconnect === 'true' || autoconnect == '1') {
-- autoconnect = true;
-+ UI.PVE.pveStart(function() {
- UI.connect();
-- } else {
-- autoconnect = false;
-- // Show the connect panel on first load unless autoconnecting
-- UI.openConnectPanel();
-- }
-+ });
-
- return Promise.resolve(UI.rfb);
- },
-@@ -145,9 +147,10 @@ const UI = {
- /* Populate the controls if defaults are provided in the URL */
- UI.initSetting('host', window.location.hostname);
- UI.initSetting('port', port);
-- UI.initSetting('encrypt', (window.location.protocol === "https:"));
-+ UI.initSetting('encrypt', true);
- UI.initSetting('view_clip', false);
- UI.initSetting('resize', 'off');
-+ UI.initSetting('autoresize', true);
- UI.initSetting('shared', true);
- UI.initSetting('view_only', false);
- UI.initSetting('show_dot', false);
-@@ -334,6 +337,7 @@ const UI = {
- UI.addSettingChangeHandler('resize');
- UI.addSettingChangeHandler('resize', UI.applyResizeMode);
- UI.addSettingChangeHandler('resize', UI.updateViewClip);
-+ UI.addSettingChangeHandler('autoresize');
- UI.addSettingChangeHandler('view_clip');
- UI.addSettingChangeHandler('view_clip', UI.updateViewClip);
- UI.addSettingChangeHandler('shared');
-@@ -384,6 +388,9 @@ const UI = {
- document.documentElement.classList.add("noVNC_connecting");
- break;
- case 'connected':
-+ UI.connected = true;
-+ UI.inhibit_reconnect = false;
-+ UI.pveAllowMigratedTest = true;
- document.documentElement.classList.add("noVNC_connected");
- break;
- case 'disconnecting':
-@@ -391,6 +398,11 @@ const UI = {
- document.documentElement.classList.add("noVNC_disconnecting");
- break;
- case 'disconnected':
-+ UI.showStatus(_("Disconnected"));
-+ if (UI.pveAllowMigratedTest === true) {
-+ UI.pveAllowMigratedTest = false;
-+ UI.PVE.pve_detect_migrated_vm();
-+ }
- break;
- case 'reconnecting':
- transition_elem.textContent = _("Reconnecting...");
-@@ -805,6 +817,7 @@ const UI = {
- UI.closePowerPanel();
- UI.closeClipboardPanel();
- UI.closeExtraKeys();
-+ UI.closePVECommandPanel();
- },
-
- /* ------^-------
-@@ -980,6 +993,12 @@ const UI = {
- UI.reconnect_password = password;
- }
-
-+ var password = document.getElementById('noVNC_password_input').value;
-+
-+ if (!password) {
-+ password = WebUtil.getConfigVar('password');
-+ }
-+
- if (password === null) {
- password = undefined;
- }
-@@ -1549,9 +1568,36 @@ const UI = {
- /* ------^-------
- * /EXTRA KEYS
- * ==============
-- * MISC
-+ * PVE
- * ------v------*/
-
-+ togglePVECommandPanel: function() {
-+ if (document.getElementById('pve_commands').classList.contains("noVNC_open")) {
-+ UI.closePVECommandPanel();
-+ } else {
-+ UI.openPVECommandPanel();
-+ }
-+ },
-+
-+ openPVECommandPanel: function() {
-+ var me = this;
-+ UI.closeAllPanels();
-+ UI.openControlbar();
-+
-+ document.getElementById('pve_commands').classList.add("noVNC_open");
-+ document.getElementById('pve_commands_button').classList.add("noVNC_selected");
-+ },
-+
-+ closePVECommandPanel: function() {
-+ document.getElementById('pve_commands').classList.remove("noVNC_open");
-+ document.getElementById('pve_commands_button').classList.remove("noVNC_selected");
-+ },
-+
-+/* ------^-------
-+ * /PVE
-+ * ==============
-+ * MISC
-+ * ------v------*/
- setMouseButton(num) {
- const view_only = UI.rfb.viewOnly;
- if (UI.rfb && !view_only) {
-diff --git a/vnc.html b/vnc.html
-index 212321b..072d86b 100644
---- a/vnc.html
-+++ b/vnc.html
-@@ -191,7 +191,7 @@
- <li class="noVNC_heading">
- <img alt="" src="app/images/settings.svg"> Settings
- </li>
-- <li>
-+ <li style="display:none;">
- <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
- </li>
- <li>
-@@ -201,16 +201,18 @@
- <li>
- <label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
- </li>
-+ <li>
-+ <label><input id="noVNC_setting_autoresize" type="checkbox" /> Autoresize Window</label>
-+ </li>
- <li>
- <label for="noVNC_setting_resize">Scaling Mode:</label>
- <select id="noVNC_setting_resize" name="vncResize">
-- <option value="off">None</option>
-+ <option value="off">Off</option>
- <option value="scale">Local Scaling</option>
-- <option value="remote">Remote Resizing</option>
- </select>
- </li>
- <li><hr></li>
-- <li>
-+ <li style="display:none;">
- <div class="noVNC_expander">Advanced</div>
- <div><ul>
- <li>
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Wed, 9 May 2018 10:47:53 +0200
-Subject: [PATCH 02/12] add custom fbresize event on rfb
+Subject: [PATCH] add custom fbresize event on rfb
this can be use to react to changes of the resolution, like resizing the
window
2 files changed, 21 insertions(+)
diff --git a/app/ui.js b/app/ui.js
-index 4683c02..1b0f7aa 100644
+index 317f845..91bdcf4 100644
--- a/app/ui.js
+++ b/app/ui.js
-@@ -1039,6 +1039,7 @@ const UI = {
+@@ -1054,6 +1054,7 @@ const UI = {
UI.rfb.addEventListener("clipboard", UI.clipboardReceive);
UI.rfb.addEventListener("bell", UI.bell);
UI.rfb.addEventListener("desktopname", UI.updateDesktopName);
UI.rfb.clipViewport = UI.getSetting('view_clip');
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
-@@ -1593,6 +1594,16 @@ const UI = {
+@@ -1665,6 +1666,16 @@ const UI = {
document.getElementById('pve_commands_button').classList.remove("noVNC_selected");
},
* /PVE
* ==============
diff --git a/core/rfb.js b/core/rfb.js
-index 89b8130..c079af1 100644
+index f35d503..7ea2004 100644
--- a/core/rfb.js
+++ b/core/rfb.js
-@@ -1670,6 +1670,16 @@ export default class RFB extends EventTargetMixin {
+@@ -2492,6 +2492,16 @@ export default class RFB extends EventTargetMixin {
this._updateClip();
this._updateScale();
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Thu, 11 May 2017 10:34:10 +0200
-Subject: [PATCH 03/12] change scaling when toggling fullscreen
+Subject: [PATCH] change scaling when toggling fullscreen
when activating fullscreen, we change the scaling to 'scale',
and changing it back when leaving fullscreen
1 file changed, 11 insertions(+)
diff --git a/app/ui.js b/app/ui.js
-index 1b0f7aa..8cc6cfd 100644
+index 91bdcf4..ef2c77f 100644
--- a/app/ui.js
+++ b/app/ui.js
-@@ -1201,6 +1201,13 @@ const UI = {
+@@ -1239,6 +1239,13 @@ const UI = {
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
-@@ -1211,7 +1218,11 @@ const UI = {
+@@ -1249,7 +1256,11 @@ const UI = {
} else if (document.body.msRequestFullscreen) {
document.body.msRequestFullscreen();
}
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Tue, 13 Dec 2016 16:03:41 +0100
-Subject: [PATCH 04/12] add pve style
+Subject: [PATCH] add pve style
this adds the custom pve style (based on black.css)
+ background: #5BA8DF;
+}
diff --git a/vnc.html b/vnc.html
-index 072d86b..57b44a1 100644
+index 5ec354a..a49e3a2 100644
--- a/vnc.html
+++ b/vnc.html
-@@ -48,7 +48,8 @@
+@@ -52,7 +52,8 @@
<link rel="apple-touch-icon" sizes="152x152" type="image/png" href="app/images/icons/novnc-152x152.png">
<!-- Stylesheets -->
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Fri, 20 Jan 2017 10:35:05 +0100
-Subject: [PATCH 05/12] remove vnc logos
+Subject: [PATCH] remove vnc logos
to show the pve icon instead
1 file changed, 3 insertions(+), 29 deletions(-)
diff --git a/vnc.html b/vnc.html
-index 57b44a1..1420849 100644
+index a49e3a2..12db665 100644
--- a/vnc.html
+++ b/vnc.html
-@@ -17,36 +17,10 @@
-
- <meta charset="utf-8">
+@@ -21,36 +21,10 @@
+ Remove this if you use the .htaccess -->
+ <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <!-- Icons (see app/images/icons/Makefile for what the sizes are for) -->
- <link rel="icon" sizes="16x16" type="image/png" href="app/images/icons/novnc-16x16.png">
--- /dev/null
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Dominik Csapak <d.csapak@proxmox.com>
+Date: Tue, 17 Jan 2017 17:24:03 +0100
+Subject: [PATCH] change source-directory for fetching images/js files
+
+since they will be served from `/novnc/`
+also change the directory in the build script
+
+Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
+---
+ app/ui.js | 2 +-
+ vnc.html | 50 +++++++++++++++++++++++++-------------------------
+ 2 files changed, 26 insertions(+), 26 deletions(-)
+
+diff --git a/app/ui.js b/app/ui.js
+index ef2c77f..d604067 100644
+--- a/app/ui.js
++++ b/app/ui.js
+@@ -1767,7 +1767,7 @@ l10n.setup(LINGUAS);
+ if (l10n.language === "en" || l10n.dictionary !== undefined) {
+ UI.prime();
+ } else {
+- WebUtil.fetchJSON('app/locale/' + l10n.language + '.json')
++ WebUtil.fetchJSON('/novnc/app/locale/' + l10n.language + '.json')
+ .then((translations) => { l10n.dictionary = translations; })
+ .catch(err => Log.Error("Failed to load translations: " + err))
+ .then(UI.prime);
+diff --git a/vnc.html b/vnc.html
+index 12db665..396ded8 100644
+--- a/vnc.html
++++ b/vnc.html
+@@ -26,19 +26,19 @@
+ <meta name="apple-mobile-web-app-capable" content="yes" />
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
+ <!-- Stylesheets -->
+- <link rel="stylesheet" href="app/styles/base.css" />
++ <link rel="stylesheet" href="/novnc/app/styles/base.css" />
+ <link rel="stylesheet" href="/novnc/app/styles/pve.css" />
+
+ <!-- this is included as a normal file in order to catch script-loading errors as well -->
+- <script src="app/error-handler.js"></script>
++ <script src="/novnc/app/error-handler.js"></script>
+
+ <!-- begin scripts -->
+ <!-- promise polyfills promises for IE11 -->
+- <script src="vendor/promise.js"></script>
++ <script src="/novnc/vendor/promise.js"></script>
+ <!-- ES2015/ES6 modules polyfill -->
+- <script nomodule src="vendor/browser-es-module-loader/dist/browser-es-module-loader.js"></script>
++ <script nomodule src="/novnc/vendor/browser-es-module-loader/dist/browser-es-module-loader.js"></script>
+ <!-- actual script modules -->
+- <script type="module" crossorigin="anonymous" src="app/ui.js"></script>
++ <script type="module" crossorigin="anonymous" src="/novnc/app/ui.js"></script>
+ <!-- end scripts -->
+ </head>
+
+@@ -63,51 +63,51 @@
+ <h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
+
+ <!-- Drag/Pan the viewport -->
+- <input type="image" alt="Drag" src="app/images/drag.svg"
++ <input type="image" alt="Drag" src="/novnc/app/images/drag.svg"
+ id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden"
+ title="Move/Drag Viewport">
+
+ <!--noVNC Touch Device only buttons-->
+ <div id="noVNC_mobile_buttons">
+- <input type="image" alt="Keyboard" src="app/images/keyboard.svg"
++ <input type="image" alt="Keyboard" src="/novnc/app/images/keyboard.svg"
+ id="noVNC_keyboard_button" class="noVNC_button" title="Show Keyboard">
+ </div>
+
+ <!-- Extra manual keys -->
+- <input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
++ <input type="image" alt="Extra keys" src="/novnc/app/images/toggleextrakeys.svg"
+ id="noVNC_toggle_extra_keys_button" class="noVNC_button"
+ title="Show Extra Keys">
+ <div class="noVNC_vcenter">
+ <div id="noVNC_modifiers" class="noVNC_panel">
+- <input type="image" alt="Ctrl" src="app/images/ctrl.svg"
++ <input type="image" alt="Ctrl" src="/novnc/app/images/ctrl.svg"
+ id="noVNC_toggle_ctrl_button" class="noVNC_button"
+ title="Toggle Ctrl">
+- <input type="image" alt="Alt" src="app/images/alt.svg"
++ <input type="image" alt="Alt" src="/novnc/app/images/alt.svg"
+ id="noVNC_toggle_alt_button" class="noVNC_button"
+ title="Toggle Alt">
+- <input type="image" alt="Windows" src="app/images/windows.svg"
++ <input type="image" alt="Windows" src="/novnc/app/images/windows.svg"
+ id="noVNC_toggle_windows_button" class="noVNC_button"
+ title="Toggle Windows">
+- <input type="image" alt="Tab" src="app/images/tab.svg"
++ <input type="image" alt="Tab" src="/novnc/app/images/tab.svg"
+ id="noVNC_send_tab_button" class="noVNC_button"
+ title="Send Tab">
+- <input type="image" alt="Esc" src="app/images/esc.svg"
++ <input type="image" alt="Esc" src="/novnc/app/images/esc.svg"
+ id="noVNC_send_esc_button" class="noVNC_button"
+ title="Send Escape">
+- <input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
++ <input type="image" alt="Ctrl+Alt+Del" src="/novnc/app/images/ctrlaltdel.svg"
+ id="noVNC_send_ctrl_alt_del_button" class="noVNC_button"
+ title="Send Ctrl-Alt-Del">
+ </div>
+ </div>
+
+ <!-- Shutdown/Reboot -->
+- <input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
++ <input type="image" alt="Shutdown/Reboot" src="/novnc/app/images/power.svg"
+ id="noVNC_power_button" class="noVNC_button"
+ title="Shutdown/Reboot...">
+ <div class="noVNC_vcenter">
+ <div id="noVNC_power" class="noVNC_panel">
+ <div class="noVNC_heading">
+- <img alt="" src="app/images/power.svg"> Power
++ <img alt="" src="/novnc/app/images/power.svg"> Power
+ </div>
+ <input type="button" id="noVNC_shutdown_button" value="Shutdown">
+ <input type="button" id="noVNC_reboot_button" value="Reboot">
+@@ -116,13 +116,13 @@
+ </div>
+
+ <!-- Clipboard -->
+- <input type="image" alt="Clipboard" src="app/images/clipboard.svg"
++ <input type="image" alt="Clipboard" src="/novnc/app/images/clipboard.svg"
+ id="noVNC_clipboard_button" class="noVNC_button"
+ title="Clipboard">
+ <div class="noVNC_vcenter">
+ <div id="noVNC_clipboard" class="noVNC_panel">
+ <div class="noVNC_heading">
+- <img alt="" src="app/images/clipboard.svg"> Clipboard
++ <img alt="" src="/novnc/app/images/clipboard.svg"> Clipboard
+ </div>
+ <textarea id="noVNC_clipboard_text" rows=5></textarea>
+ <br>
+@@ -132,19 +132,19 @@
+ </div>
+
+ <!-- Toggle fullscreen -->
+- <input type="image" alt="Fullscreen" src="app/images/fullscreen.svg"
++ <input type="image" alt="Fullscreen" src="/novnc/app/images/fullscreen.svg"
+ id="noVNC_fullscreen_button" class="noVNC_button noVNC_hidden"
+ title="Fullscreen">
+
+ <!-- Settings -->
+- <input type="image" alt="Settings" src="app/images/settings.svg"
++ <input type="image" alt="Settings" src="/novnc/app/images/settings.svg"
+ id="noVNC_settings_button" class="noVNC_button"
+ title="Settings">
+ <div class="noVNC_vcenter">
+ <div id="noVNC_settings" class="noVNC_panel">
+ <ul>
+ <li class="noVNC_heading">
+- <img alt="" src="app/images/settings.svg"> Settings
++ <img alt="" src="/novnc/app/images/settings.svg"> Settings
+ </li>
+ <li style="display:none;">
+ <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
+@@ -235,7 +235,7 @@
+ </div>
+
+ <!-- Connection Controls -->
+- <input type="image" alt="Disconnect" src="app/images/disconnect.svg"
++ <input type="image" alt="Disconnect" src="/novnc/app/images/disconnect.svg"
+ id="noVNC_disconnect_button" class="noVNC_button"
+ title="Disconnect">
+
+@@ -254,7 +254,7 @@
+ <div id="noVNC_connect_dlg">
+ <div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
+ <div id="noVNC_connect_button"><div>
+- <img alt="" src="app/images/connect.svg"> Connect
++ <img alt="" src="/novnc/app/images/connect.svg"> Connect
+ </div></div>
+ </div>
+ </div>
+@@ -298,8 +298,8 @@
+ </div>
+
+ <audio id="noVNC_bell">
+- <source src="app/sounds/bell.oga" type="audio/ogg">
+- <source src="app/sounds/bell.mp3" type="audio/mpeg">
++ <source src="/novnc/app/sounds/bell.oga" type="audio/ogg">
++ <source src="/novnc/app/sounds/bell.mp3" type="audio/mpeg">
+ </audio>
+ </body>
+ </html>
+++ /dev/null
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Dominik Csapak <d.csapak@proxmox.com>
-Date: Tue, 17 Jan 2017 17:24:03 +0100
-Subject: [PATCH 06/12] change src directory for images/js files
-
-since they will be in /novnc/
-also change the directory in the build script
-
-Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
----
- app/ui.js | 2 +-
- vnc.html | 58 +++++++++++++++++++++++++++----------------------------
- 2 files changed, 30 insertions(+), 30 deletions(-)
-
-diff --git a/app/ui.js b/app/ui.js
-index 8cc6cfd..7201179 100644
---- a/app/ui.js
-+++ b/app/ui.js
-@@ -1713,7 +1713,7 @@ l10n.setup(LINGUAS);
- if (l10n.language === "en" || l10n.dictionary !== undefined) {
- UI.prime();
- } else {
-- WebUtil.fetchJSON('app/locale/' + l10n.language + '.json')
-+ WebUtil.fetchJSON('/novnc/app/locale/' + l10n.language + '.json')
- .then((translations) => { l10n.dictionary = translations; })
- .catch(err => Log.Error("Failed to load translations: " + err))
- .then(UI.prime);
-diff --git a/vnc.html b/vnc.html
-index 1420849..f93cf89 100644
---- a/vnc.html
-+++ b/vnc.html
-@@ -22,15 +22,15 @@
- <meta name="apple-mobile-web-app-capable" content="yes" />
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
- <!-- Stylesheets -->
-- <link rel="stylesheet" href="app/styles/base.css" />
-+ <link rel="stylesheet" href="/novnc/app/styles/base.css" />
- <link rel="stylesheet" href="/novnc/app/styles/pve.css" />
-
- <!-- this is included as a normal file in order to catch script-loading errors as well -->
-- <script src="app/error-handler.js"></script>
-+ <script src="/novnc/app/error-handler.js"></script>
-
- <!-- begin scripts -->
- <!-- promise polyfills promises for IE11 -->
-- <script src="vendor/promise.js"></script>
-+ <script src="/novnc/vendor/promise.js"></script>
- <!-- ES2015/ES6 modules polyfill -->
- <script type="module">
- window._noVNC_has_module_support = true;
-@@ -39,12 +39,12 @@
- window.addEventListener("load", function() {
- if (window._noVNC_has_module_support) return;
- var loader = document.createElement("script");
-- loader.src = "vendor/browser-es-module-loader/dist/browser-es-module-loader.js";
-+ loader.src = "/novnc/vendor/browser-es-module-loader/dist/browser-es-module-loader.js";
- document.head.appendChild(loader);
- });
- </script>
- <!-- actual script modules -->
-- <script type="module" crossorigin="anonymous" src="app/ui.js"></script>
-+ <script type="module" crossorigin="anonymous" src="/novnc/app/ui.js"></script>
- <!-- end scripts -->
- </head>
-
-@@ -69,51 +69,51 @@
- <h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
-
- <!-- Drag/Pan the viewport -->
-- <input type="image" alt="viewport drag" src="app/images/drag.svg"
-+ <input type="image" alt="viewport drag" src="/novnc/app/images/drag.svg"
- id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden"
- title="Move/Drag Viewport">
-
- <!--noVNC Touch Device only buttons-->
- <div id="noVNC_mobile_buttons">
-- <input type="image" alt="No mousebutton" src="app/images/mouse_none.svg"
-+ <input type="image" alt="No mousebutton" src="/novnc/app/images/mouse_none.svg"
- id="noVNC_mouse_button0" class="noVNC_button"
- title="Active Mouse Button">
-- <input type="image" alt="Left mousebutton" src="app/images/mouse_left.svg"
-+ <input type="image" alt="Left mousebutton" src="/novnc/app/images/mouse_left.svg"
- id="noVNC_mouse_button1" class="noVNC_button"
- title="Active Mouse Button">
-- <input type="image" alt="Middle mousebutton" src="app/images/mouse_middle.svg"
-+ <input type="image" alt="Middle mousebutton" src="/novnc/app/images/mouse_middle.svg"
- id="noVNC_mouse_button2" class="noVNC_button"
- title="Active Mouse Button">
-- <input type="image" alt="Right mousebutton" src="app/images/mouse_right.svg"
-+ <input type="image" alt="Right mousebutton" src="/novnc/app/images/mouse_right.svg"
- id="noVNC_mouse_button4" class="noVNC_button"
- title="Active Mouse Button">
-- <input type="image" alt="Keyboard" src="app/images/keyboard.svg"
-+ <input type="image" alt="Keyboard" src="/novnc/app/images/keyboard.svg"
- id="noVNC_keyboard_button" class="noVNC_button" title="Show Keyboard">
- </div>
-
- <!-- Extra manual keys -->
- <div id="noVNC_extra_keys">
-- <input type="image" alt="Extra keys" src="app/images/toggleextrakeys.svg"
-+ <input type="image" alt="Extra keys" src="/novnc/app/images/toggleextrakeys.svg"
- id="noVNC_toggle_extra_keys_button" class="noVNC_button"
- title="Show Extra Keys">
- <div class="noVNC_vcenter">
- <div id="noVNC_modifiers" class="noVNC_panel">
-- <input type="image" alt="Ctrl" src="app/images/ctrl.svg"
-+ <input type="image" alt="Ctrl" src="/novnc/app/images/ctrl.svg"
- id="noVNC_toggle_ctrl_button" class="noVNC_button"
- title="Toggle Ctrl">
-- <input type="image" alt="Alt" src="app/images/alt.svg"
-+ <input type="image" alt="Alt" src="/novnc/app/images/alt.svg"
- id="noVNC_toggle_alt_button" class="noVNC_button"
- title="Toggle Alt">
-- <input type="image" alt="Windows" src="app/images/windows.svg"
-+ <input type="image" alt="Alt" src="/novnc/app/images/windows.svg"
- id="noVNC_toggle_windows_button" class="noVNC_button"
- title="Toggle Windows">
-- <input type="image" alt="Tab" src="app/images/tab.svg"
-+ <input type="image" alt="Tab" src="/novnc/app/images/tab.svg"
- id="noVNC_send_tab_button" class="noVNC_button"
- title="Send Tab">
-- <input type="image" alt="Esc" src="app/images/esc.svg"
-+ <input type="image" alt="Esc" src="/novnc/app/images/esc.svg"
- id="noVNC_send_esc_button" class="noVNC_button"
- title="Send Escape">
-- <input type="image" alt="Ctrl+Alt+Del" src="app/images/ctrlaltdel.svg"
-+ <input type="image" alt="Ctrl+Alt+Del" src="/novnc/app/images/ctrlaltdel.svg"
- id="noVNC_send_ctrl_alt_del_button" class="noVNC_button"
- title="Send Ctrl-Alt-Del">
- </div>
-@@ -121,13 +121,13 @@
- </div>
-
- <!-- Shutdown/Reboot -->
-- <input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
-+ <input type="image" alt="Shutdown/Reboot" src="/novnc/app/images/power.svg"
- id="noVNC_power_button" class="noVNC_button"
- title="Shutdown/Reboot...">
- <div class="noVNC_vcenter">
- <div id="noVNC_power" class="noVNC_panel">
- <div class="noVNC_heading">
-- <img alt="" src="app/images/power.svg"> Power
-+ <img alt="" src="/novnc/app/images/power.svg"> Power
- </div>
- <input type="button" id="noVNC_shutdown_button" value="Shutdown">
- <input type="button" id="noVNC_reboot_button" value="Reboot">
-@@ -136,13 +136,13 @@
- </div>
-
- <!-- Clipboard -->
-- <input type="image" alt="Clipboard" src="app/images/clipboard.svg"
-+ <input type="image" alt="Clipboard" src="/novnc/app/images/clipboard.svg"
- id="noVNC_clipboard_button" class="noVNC_button"
- title="Clipboard">
- <div class="noVNC_vcenter">
- <div id="noVNC_clipboard" class="noVNC_panel">
- <div class="noVNC_heading">
-- <img alt="" src="app/images/clipboard.svg"> Clipboard
-+ <img alt="" src="/novnc/app/images/clipboard.svg"> Clipboard
- </div>
- <textarea id="noVNC_clipboard_text" rows=5></textarea>
- <br>
-@@ -152,19 +152,19 @@
- </div>
-
- <!-- Toggle fullscreen -->
-- <input type="image" alt="Fullscreen" src="app/images/fullscreen.svg"
-+ <input type="image" alt="Fullscreen" src="/novnc/app/images/fullscreen.svg"
- id="noVNC_fullscreen_button" class="noVNC_button noVNC_hidden"
- title="Fullscreen">
-
- <!-- Settings -->
-- <input type="image" alt="Settings" src="app/images/settings.svg"
-+ <input type="image" alt="Settings" src="/novnc/app/images/settings.svg"
- id="noVNC_settings_button" class="noVNC_button"
- title="Settings">
- <div class="noVNC_vcenter">
- <div id="noVNC_settings" class="noVNC_panel">
- <ul>
- <li class="noVNC_heading">
-- <img alt="" src="app/images/settings.svg"> Settings
-+ <img alt="" src="/novnc/app/images/settings.svg"> Settings
- </li>
- <li style="display:none;">
- <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
-@@ -241,7 +241,7 @@
- </div>
-
- <!-- Connection Controls -->
-- <input type="image" alt="Disconnect" src="app/images/disconnect.svg"
-+ <input type="image" alt="Disconnect" src="/novnc/app/images/disconnect.svg"
- id="noVNC_disconnect_button" class="noVNC_button"
- title="Disconnect">
-
-@@ -260,7 +260,7 @@
- <div id="noVNC_connect_dlg">
- <div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
- <div id="noVNC_connect_button"><div>
-- <img alt="" src="app/images/connect.svg"> Connect
-+ <img alt="" src="/novnc/app/images/connect.svg"> Connect
- </div></div>
- </div>
- </div>
-@@ -300,8 +300,8 @@
- </div>
-
- <audio id="noVNC_bell">
-- <source src="app/sounds/bell.oga" type="audio/ogg">
-- <source src="app/sounds/bell.mp3" type="audio/mpeg">
-+ <source src="/novnc/app/sounds/bell.oga" type="audio/ogg">
-+ <source src="/novnc/app/sounds/bell.mp3" type="audio/mpeg">
- </audio>
- </body>
- </html>
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Fri, 20 Jan 2017 10:35:43 +0100
-Subject: [PATCH 07/12] add pve vnc commands
+Subject: [PATCH] add pve vnc commands
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
1 file changed, 21 insertions(+)
diff --git a/vnc.html b/vnc.html
-index f93cf89..fad5d4a 100644
+index 396ded8..a0802e0 100644
--- a/vnc.html
+++ b/vnc.html
-@@ -240,6 +240,27 @@
+@@ -234,6 +234,27 @@
</div>
</div>
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Fri, 20 Jan 2017 10:16:09 +0100
-Subject: [PATCH 08/12] add replaceable snippets in vnc.html
+Subject: [PATCH] add replaceable snippets in vnc.html
so that we can insert the username/csrftoken via search/replace
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/vnc.html b/vnc.html
-index fad5d4a..bba7d7d 100644
+index a0802e0..5f09cd2 100644
--- a/vnc.html
+++ b/vnc.html
@@ -13,7 +13,7 @@
+ <title>[% nodename %] - Proxmox Console</title>
<meta charset="utf-8">
-
-@@ -26,7 +26,13 @@
+
+@@ -30,7 +30,13 @@
<link rel="stylesheet" href="/novnc/app/styles/pve.css" />
<!-- this is included as a normal file in order to catch script-loading errors as well -->
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Fri, 20 Jan 2017 10:55:49 +0100
-Subject: [PATCH 09/12] decrease animation time
+Subject: [PATCH] decrease animation time
because 0.5s is too long
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/app/styles/base.css b/app/styles/base.css
-index 3ca9894..137aec8 100644
+index fd78b79..db52eaa 100644
--- a/app/styles/base.css
+++ b/app/styles/base.css
-@@ -283,7 +283,7 @@ select:active {
+@@ -339,7 +339,7 @@ select:active {
position: fixed;
z-index: 10;
/* Edge misrenders animations wihthout this */
transform: translateX(0);
-@@ -300,7 +300,7 @@ select:active {
+@@ -356,7 +356,7 @@ select:active {
position: relative;
left: -100%;
background-color: rgb(110, 132, 163);
border-radius: 0 10px 10px 0;
-@@ -318,7 +318,7 @@ select:active {
+@@ -374,7 +374,7 @@ select:active {
height: 100%;
width: 30px;
left: -30px;
}
#noVNC_control_bar.noVNC_open::before {
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-@@ -352,7 +352,7 @@ select:active {
+@@ -408,7 +408,7 @@ select:active {
}
#noVNC_control_bar_handle:after {
content: "";
background: url("../images/handle.svg");
position: absolute;
top: 22px; /* (50px-6px)/2 */
-@@ -474,7 +474,7 @@ select:active {
+@@ -530,7 +530,7 @@ select:active {
.noVNC_panel {
transform: translateX(25px);
max-height: 100vh; /* Chrome is buggy with 100% */
overflow-x: hidden;
-@@ -651,7 +651,7 @@ select:active {
+@@ -717,7 +717,7 @@ select:active {
cursor: pointer;
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Tue, 16 May 2017 10:36:15 +0200
-Subject: [PATCH 10/12] use only app.js
+Subject: [PATCH] use only app.js
-because we will use the commonjs version,
-we only need to use the generated app.js
+As PVE now uses the commonjs version, there's only need to fetch the
+generated app.js
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
- vnc.html | 17 +----------------
- 1 file changed, 1 insertion(+), 16 deletions(-)
+ vnc.html | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/vnc.html b/vnc.html
-index bba7d7d..6fb195e 100644
+index 5f09cd2..9f594e2 100644
--- a/vnc.html
+++ b/vnc.html
-@@ -35,22 +35,7 @@
+@@ -39,12 +39,7 @@
</script>
<!-- begin scripts -->
- <!-- promise polyfills promises for IE11 -->
- <script src="/novnc/vendor/promise.js"></script>
- <!-- ES2015/ES6 modules polyfill -->
-- <script type="module">
-- window._noVNC_has_module_support = true;
-- </script>
-- <script>
-- window.addEventListener("load", function() {
-- if (window._noVNC_has_module_support) return;
-- var loader = document.createElement("script");
-- loader.src = "/novnc/vendor/browser-es-module-loader/dist/browser-es-module-loader.js";
-- document.head.appendChild(loader);
-- });
-- </script>
+- <script nomodule src="/novnc/vendor/browser-es-module-loader/dist/browser-es-module-loader.js"></script>
- <!-- actual script modules -->
- <script type="module" crossorigin="anonymous" src="/novnc/app/ui.js"></script>
+ <script crossorigin=anonymous" src="/novnc/app.js"></script>
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dominik Csapak <d.csapak@proxmox.com>
Date: Thu, 19 Jul 2018 11:31:51 +0200
-Subject: [PATCH 11/12] add localCursor setting to rfb
+Subject: [PATCH] add localCursor setting to rfb
and use it in app.js (default true)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
+Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
---
- app/ui.js | 9 +++++++++
+ app/ui.js | 10 ++++++++++
core/rfb.js | 10 ++++++++++
core/util/cursor.js | 15 ++++++++++++++-
vnc.html | 3 +++
- 4 files changed, 36 insertions(+), 1 deletion(-)
+ 4 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/app/ui.js b/app/ui.js
-index 7201179..35d5d7a 100644
+index d604067..d8126bc 100644
--- a/app/ui.js
+++ b/app/ui.js
-@@ -151,6 +151,7 @@ const UI = {
- UI.initSetting('view_clip', false);
- UI.initSetting('resize', 'off');
+@@ -166,6 +166,7 @@ const UI = {
+ UI.initSetting('quality', 6);
+ UI.initSetting('compression', 2);
UI.initSetting('autoresize', true);
+ UI.initSetting('local_cursor', true);
UI.initSetting('shared', true);
UI.initSetting('view_only', false);
UI.initSetting('show_dot', false);
-@@ -345,6 +346,8 @@ const UI = {
+@@ -356,6 +357,8 @@ const UI = {
UI.addSettingChangeHandler('view_only', UI.updateViewOnly);
UI.addSettingChangeHandler('show_dot');
UI.addSettingChangeHandler('show_dot', UI.updateShowDotCursor);
UI.addSettingChangeHandler('host');
UI.addSettingChangeHandler('port');
UI.addSettingChangeHandler('path');
-@@ -1041,6 +1044,7 @@ const UI = {
+@@ -1056,6 +1059,7 @@ const UI = {
UI.rfb.addEventListener("desktopname", UI.updateDesktopName);
UI.rfb.addEventListener("fbresize", UI.updateSessionSize);
UI.rfb.clipViewport = UI.getSetting('view_clip');
+ UI.rfb.localCursor = UI.getSetting('local_cursor');
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
-
-@@ -1638,6 +1642,11 @@ const UI = {
- }
- },
-
+ UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
+@@ -1692,6 +1696,12 @@ const UI = {
+ * ==============
+ * MISC
+ * ------v------*/
++
+ updateLocalCursor() {
+ if (!UI.rfb) return;
+ UI.rfb.localCursor = UI.getSetting('local_cursor');
if (!UI.rfb) return;
UI.rfb.viewOnly = UI.getSetting('view_only');
diff --git a/core/rfb.js b/core/rfb.js
-index c079af1..2beb00c 100644
+index 7ea2004..85c7836 100644
--- a/core/rfb.js
+++ b/core/rfb.js
-@@ -246,6 +246,7 @@ export default class RFB extends EventTargetMixin {
+@@ -296,6 +296,7 @@ export default class RFB extends EventTargetMixin {
this._clipViewport = false;
this._scaleViewport = false;
this._resizeSession = false;
+ this._localCursor = false;
- }
- // ===== PROPERTIES =====
-@@ -308,6 +309,15 @@ export default class RFB extends EventTargetMixin {
- get background() { return this._screen.style.background; }
- set background(cssValue) { this._screen.style.background = cssValue; }
+ this._showDotCursor = false;
+ if (options.showDotCursor !== undefined) {
+@@ -356,6 +357,15 @@ export default class RFB extends EventTargetMixin {
+ }
+ }
+ get localCursor() { return this._localCursor; }
+ set localCursor(localCursor) {
+ }
+ }
+
- // ===== PUBLIC METHODS =====
-
- disconnect() {
+ get showDotCursor() { return this._showDotCursor; }
+ set showDotCursor(show) {
+ this._showDotCursor = show;
diff --git a/core/util/cursor.js b/core/util/cursor.js
-index 0d0b754..73d7880 100644
+index 4db1dab..e5b1768 100644
--- a/core/util/cursor.js
+++ b/core/util/cursor.js
@@ -12,6 +12,8 @@ export default class Cursor {
this._canvas = document.createElement('canvas');
if (useFallback) {
-@@ -115,7 +117,7 @@ export default class Cursor {
+@@ -110,7 +112,7 @@ export default class Cursor {
}
clear() {
this._canvas.width = 0;
this._canvas.height = 0;
this._position.x = this._position.x + this._hotSpot.x;
-@@ -124,6 +126,11 @@ export default class Cursor {
- this._hotSpot.y = 0;
+@@ -140,6 +142,11 @@ export default class Cursor {
+ this._updateVisibility(target);
}
+ setLocalCursor(cursor) {
_handleMouseOver(event) {
// This event could be because we're entering the target, or
// moving around amongst its sub elements. Let the move handler
-@@ -218,4 +225,10 @@ export default class Cursor {
- this._canvas.style.left = this._position.x + "px";
- this._canvas.style.top = this._position.y + "px";
+@@ -192,6 +199,11 @@ export default class Cursor {
+ }
}
-+
+
+ _updateLocalCursor() {
+ if (this._target)
+ this._target.style.cursor = this._showLocalCursor ? 'default' : 'none';
+ }
++
+ _showCursor() {
+ if (this._canvas.style.visibility === 'hidden') {
+ this._canvas.style.visibility = '';
+@@ -250,4 +262,5 @@ export default class Cursor {
+ return document.captureElement &&
+ document.documentElement.contains(document.captureElement);
+ }
+
}
diff --git a/vnc.html b/vnc.html
-index 6fb195e..d48091d 100644
+index 9f594e2..bf1fde5 100644
--- a/vnc.html
+++ b/vnc.html
-@@ -167,6 +167,9 @@
+@@ -157,6 +157,9 @@
<li>
<label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
</li>
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tim Marx <t.marx@proxmox.com>
Date: Fri, 21 Dec 2018 11:46:13 +0100
-Subject: [PATCH 12/12] pass custom command to vnc
+Subject: [PATCH] pass custom command to vnc
Signed-off-by: Tim Marx <t.marx@proxmox.com>
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
-0001-add-pve-specific-js-code.patch
+0001-add-PVE-specific-JS-code.patch
0002-add-custom-fbresize-event-on-rfb.patch
0003-change-scaling-when-toggling-fullscreen.patch
0004-add-pve-style.patch
0005-remove-vnc-logos.patch
-0006-change-src-directory-for-images-js-files.patch
+0006-change-source-directory-for-fetching-images-js-files.patch
0007-add-pve-vnc-commands.patch
0008-add-replaceable-snippets-in-vnc.html.patch
0009-decrease-animation-time.patch