mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
refactor(console): one keys menu module for both VNC console pages
The lite and the full console page each carried the same 150 lines that send key combinations (Ctrl+Alt+Del, Ctrl+Alt+F1..F12, Alt+Tab, ...). They now import static/js/console_keys.js, which binds the menu to the page's RFB connection.
This commit is contained in:
parent
f6d4886d1b
commit
a0b203749a
3 changed files with 55 additions and 234 deletions
|
|
@ -56,84 +56,7 @@
|
|||
<!-- actual script modules -->
|
||||
<script type="module" crossorigin="anonymous">
|
||||
import UI from '{% static "js/novnc/app/ui.js" %}';
|
||||
import KeyTable from '{% static "js/novnc/core/input/keysym.js" %}';
|
||||
|
||||
const fnKeys = [
|
||||
{ keysym: KeyTable.XK_F1, code: 'F1' },
|
||||
{ keysym: KeyTable.XK_F2, code: 'F2' },
|
||||
{ keysym: KeyTable.XK_F3, code: 'F3' },
|
||||
{ keysym: KeyTable.XK_F4, code: 'F4' },
|
||||
{ keysym: KeyTable.XK_F5, code: 'F5' },
|
||||
{ keysym: KeyTable.XK_F6, code: 'F6' },
|
||||
{ keysym: KeyTable.XK_F7, code: 'F7' },
|
||||
{ keysym: KeyTable.XK_F8, code: 'F8' },
|
||||
{ keysym: KeyTable.XK_F9, code: 'F9' },
|
||||
{ keysym: KeyTable.XK_F10, code: 'F10' },
|
||||
{ keysym: KeyTable.XK_F11, code: 'F11' },
|
||||
{ keysym: KeyTable.XK_F12, code: 'F12' }
|
||||
];
|
||||
|
||||
function isConnected() {
|
||||
return UI.rfb && (!UI.rfb._rfbConnectionState || UI.rfb._rfbConnectionState === 'connected');
|
||||
}
|
||||
|
||||
function sendSingleKey(keysym, code) {
|
||||
if (!isConnected()) { return false; }
|
||||
UI.rfb.sendKey(keysym, code, true);
|
||||
setTimeout(() => {
|
||||
if (isConnected()) {
|
||||
UI.rfb.sendKey(keysym, code, false);
|
||||
}
|
||||
}, 20);
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendKeyCombo(keys) {
|
||||
if (!isConnected()) { return false; }
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
UI.rfb.sendKey(keys[i].keysym, keys[i].code, true);
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (isConnected()) {
|
||||
for (let i = keys.length - 1; i >= 0; i--) {
|
||||
UI.rfb.sendKey(keys[i].keysym, keys[i].code, false);
|
||||
}
|
||||
}
|
||||
}, 20);
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendCtrlAltDel() {
|
||||
if (isConnected() && typeof UI.rfb.sendCtrlAltDel === 'function') {
|
||||
UI.rfb.sendCtrlAltDel();
|
||||
} else {
|
||||
sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_Delete, code: 'Delete' }
|
||||
]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendCtrlAltFN(f) {
|
||||
if (f < 0 || f >= fnKeys.length) { return false; }
|
||||
return sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
fnKeys[f]
|
||||
]);
|
||||
}
|
||||
|
||||
function bindKeyAction(id, handler) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
el.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
handler();
|
||||
});
|
||||
}
|
||||
}
|
||||
import { bindKeyAction, bindSendKeys } from '{% static "js/console_keys.js" %}';
|
||||
|
||||
bindKeyAction('fullscreen_button', () => {
|
||||
if (typeof UI.fullscreen === 'function') {
|
||||
|
|
@ -141,40 +64,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
bindKeyAction('ctrlaltdel', sendCtrlAltDel);
|
||||
bindKeyAction('ctrlaltbackspace', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_BackSpace, code: 'Backspace' }
|
||||
]));
|
||||
bindKeyAction('alttab', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_Tab, code: 'Tab' }
|
||||
]));
|
||||
bindKeyAction('superkey', () => sendSingleKey(KeyTable.XK_Super_L, 'MetaLeft'));
|
||||
bindKeyAction('sendesc', () => sendSingleKey(KeyTable.XK_Escape, 'Escape'));
|
||||
bindKeyAction('sendtab', () => sendSingleKey(KeyTable.XK_Tab, 'Tab'));
|
||||
|
||||
bindKeyAction('ctrlc', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_c, code: 'KeyC' }
|
||||
]));
|
||||
bindKeyAction('ctrlz', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_z, code: 'KeyZ' }
|
||||
]));
|
||||
bindKeyAction('ctrld', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_d, code: 'KeyD' }
|
||||
]));
|
||||
bindKeyAction('ctrlbackslash', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_backslash, code: 'Backslash' }
|
||||
]));
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
bindKeyAction('ctrlaltf' + (i + 1), () => sendCtrlAltFN(i));
|
||||
}
|
||||
bindSendKeys(() => UI.rfb);
|
||||
|
||||
// novncd behind the panel's own address (nginx's /novncd/); a VM with a
|
||||
// QEMU websocket port is reached on that port of the panel's host name
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<script type="module" crossorigin="anonymous">
|
||||
// RFB holds the API to connect and communicate with a VNC server
|
||||
import RFB from '{% static "js/novnc/core/rfb.js" %}';
|
||||
import KeyTable from '{% static "js/novnc/core/input/keysym.js" %}';
|
||||
import { bindKeyAction, bindSendKeys } from '{% static "js/console_keys.js" %}';
|
||||
|
||||
let rfb;
|
||||
let desktopName;
|
||||
|
|
@ -60,76 +60,6 @@
|
|||
desktopName = e.detail.name;
|
||||
}
|
||||
|
||||
function isConnected() {
|
||||
return rfb && (!rfb._rfbConnectionState || rfb._rfbConnectionState === 'connected');
|
||||
}
|
||||
|
||||
function sendSingleKey(keysym, code) {
|
||||
if (!isConnected()) { return false; }
|
||||
rfb.sendKey(keysym, code, true);
|
||||
setTimeout(() => {
|
||||
if (isConnected()) {
|
||||
rfb.sendKey(keysym, code, false);
|
||||
}
|
||||
}, 20);
|
||||
return false;
|
||||
}
|
||||
|
||||
function sendKeyCombo(keys) {
|
||||
if (!isConnected()) { return false; }
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
rfb.sendKey(keys[i].keysym, keys[i].code, true);
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (isConnected()) {
|
||||
for (let i = keys.length - 1; i >= 0; i--) {
|
||||
rfb.sendKey(keys[i].keysym, keys[i].code, false);
|
||||
}
|
||||
}
|
||||
}, 20);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Since most operating systems will catch Ctrl+Alt+Del
|
||||
// before they get a chance to be intercepted by the browser,
|
||||
// we provide a way to emulate this key sequence.
|
||||
function sendCtrlAltDel() {
|
||||
if (isConnected() && typeof rfb.sendCtrlAltDel === 'function') {
|
||||
rfb.sendCtrlAltDel();
|
||||
} else {
|
||||
sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_Delete, code: 'Delete' }
|
||||
]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const fnKeys = [
|
||||
{ keysym: KeyTable.XK_F1, code: 'F1' },
|
||||
{ keysym: KeyTable.XK_F2, code: 'F2' },
|
||||
{ keysym: KeyTable.XK_F3, code: 'F3' },
|
||||
{ keysym: KeyTable.XK_F4, code: 'F4' },
|
||||
{ keysym: KeyTable.XK_F5, code: 'F5' },
|
||||
{ keysym: KeyTable.XK_F6, code: 'F6' },
|
||||
{ keysym: KeyTable.XK_F7, code: 'F7' },
|
||||
{ keysym: KeyTable.XK_F8, code: 'F8' },
|
||||
{ keysym: KeyTable.XK_F9, code: 'F9' },
|
||||
{ keysym: KeyTable.XK_F10, code: 'F10' },
|
||||
{ keysym: KeyTable.XK_F11, code: 'F11' },
|
||||
{ keysym: KeyTable.XK_F12, code: 'F12' }
|
||||
];
|
||||
|
||||
function sendCtrlAltFN(f) {
|
||||
if (f < 0 || f >= fnKeys.length) { return false; }
|
||||
return sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
fnKeys[f]
|
||||
]);
|
||||
}
|
||||
|
||||
function fullscreen() {
|
||||
if (document.fullscreenElement || // alternative standard method
|
||||
document.mozFullScreenElement || // currently working methods
|
||||
|
|
@ -170,16 +100,13 @@
|
|||
});
|
||||
|
||||
function machineShutdown() {
|
||||
if (isConnected()) { rfb.machineShutdown(); }
|
||||
return false;
|
||||
rfb.machineShutdown();
|
||||
}
|
||||
function machineReboot() {
|
||||
if (isConnected()) { rfb.machineReboot(); }
|
||||
return false;
|
||||
rfb.machineReboot();
|
||||
}
|
||||
function machineReset() {
|
||||
if (isConnected()) { rfb.machineReset(); }
|
||||
return false;
|
||||
rfb.machineReset();
|
||||
}
|
||||
|
||||
// Show a status text in the top bar
|
||||
|
|
@ -187,16 +114,6 @@
|
|||
document.getElementById('noVNC_status').textContent = text;
|
||||
}
|
||||
|
||||
function bindKeyAction(id, handler) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
el.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
handler();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// This function extracts the value of one variable from the
|
||||
// query string. If the variable isn't defined in the URL
|
||||
// it returns the default value instead.
|
||||
|
|
@ -217,7 +134,6 @@
|
|||
return defaultValue;
|
||||
}
|
||||
|
||||
bindKeyAction('sendCtrlAltDelButton', sendCtrlAltDel);
|
||||
bindKeyAction('machineShutdownButton', machineShutdown);
|
||||
bindKeyAction('machineRebootButton', machineReboot);
|
||||
bindKeyAction('machineResetButton', machineReset);
|
||||
|
|
@ -230,40 +146,7 @@
|
|||
link.setAttribute('aria-pressed', rfb.scaleViewport);
|
||||
});
|
||||
|
||||
bindKeyAction('ctrlaltdel', sendCtrlAltDel);
|
||||
bindKeyAction('ctrlaltbackspace', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_BackSpace, code: 'Backspace' }
|
||||
]));
|
||||
bindKeyAction('alttab', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Alt_L, code: 'AltLeft' },
|
||||
{ keysym: KeyTable.XK_Tab, code: 'Tab' }
|
||||
]));
|
||||
bindKeyAction('superkey', () => sendSingleKey(KeyTable.XK_Super_L, 'MetaLeft'));
|
||||
bindKeyAction('sendesc', () => sendSingleKey(KeyTable.XK_Escape, 'Escape'));
|
||||
bindKeyAction('sendtab', () => sendSingleKey(KeyTable.XK_Tab, 'Tab'));
|
||||
|
||||
bindKeyAction('ctrlc', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_c, code: 'KeyC' }
|
||||
]));
|
||||
bindKeyAction('ctrlz', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_z, code: 'KeyZ' }
|
||||
]));
|
||||
bindKeyAction('ctrld', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_d, code: 'KeyD' }
|
||||
]));
|
||||
bindKeyAction('ctrlbackslash', () => sendKeyCombo([
|
||||
{ keysym: KeyTable.XK_Control_L, code: 'ControlLeft' },
|
||||
{ keysym: KeyTable.XK_backslash, code: 'Backslash' }
|
||||
]));
|
||||
|
||||
for (let i = 0; i < 12; i++) {
|
||||
bindKeyAction('ctrlaltf' + (i + 1), () => sendCtrlAltFN(i));
|
||||
}
|
||||
bindSendKeys(() => rfb);
|
||||
|
||||
// novncd behind the panel's own address (nginx's /novncd/), never a host
|
||||
// from the link: the page sends it a console token. A VM with a QEMU
|
||||
|
|
|
|||
48
static/js/console_keys.js
Normal file
48
static/js/console_keys.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
// The keys menu of the VNC console pages (lite and full): key combinations
|
||||
// the browser or the operating system would otherwise catch.
|
||||
import KeyTable from './novnc/core/input/keysym.js';
|
||||
|
||||
const CTRL = { keysym: KeyTable.XK_Control_L, code: 'ControlLeft' };
|
||||
const ALT = { keysym: KeyTable.XK_Alt_L, code: 'AltLeft' };
|
||||
|
||||
// press the keys in order, release them in reverse
|
||||
function sendKeys(rfb, keys) {
|
||||
if (!rfb || (rfb._rfbConnectionState && rfb._rfbConnectionState !== 'connected')) { return; }
|
||||
keys.forEach((key) => rfb.sendKey(key.keysym, key.code, true));
|
||||
setTimeout(() => [...keys].reverse().forEach((key) => rfb.sendKey(key.keysym, key.code, false)), 20);
|
||||
}
|
||||
|
||||
export function bindKeyAction(id, handler) {
|
||||
const el = document.getElementById(id);
|
||||
if (el) {
|
||||
el.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
handler();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// getRfb: the page's RFB object, which the full page creates on connect
|
||||
export function bindSendKeys(getRfb) {
|
||||
const send = (...keys) => () => sendKeys(getRfb(), keys);
|
||||
const ctrlAltDel = () => {
|
||||
const rfb = getRfb();
|
||||
if (rfb && typeof rfb.sendCtrlAltDel === 'function') {
|
||||
rfb.sendCtrlAltDel();
|
||||
}
|
||||
};
|
||||
bindKeyAction('ctrlaltdel', ctrlAltDel);
|
||||
bindKeyAction('sendCtrlAltDelButton', ctrlAltDel);
|
||||
bindKeyAction('ctrlaltbackspace', send(CTRL, ALT, { keysym: KeyTable.XK_BackSpace, code: 'Backspace' }));
|
||||
bindKeyAction('alttab', send(ALT, { keysym: KeyTable.XK_Tab, code: 'Tab' }));
|
||||
bindKeyAction('superkey', send({ keysym: KeyTable.XK_Super_L, code: 'MetaLeft' }));
|
||||
bindKeyAction('sendesc', send({ keysym: KeyTable.XK_Escape, code: 'Escape' }));
|
||||
bindKeyAction('sendtab', send({ keysym: KeyTable.XK_Tab, code: 'Tab' }));
|
||||
bindKeyAction('ctrlc', send(CTRL, { keysym: KeyTable.XK_c, code: 'KeyC' }));
|
||||
bindKeyAction('ctrlz', send(CTRL, { keysym: KeyTable.XK_z, code: 'KeyZ' }));
|
||||
bindKeyAction('ctrld', send(CTRL, { keysym: KeyTable.XK_d, code: 'KeyD' }));
|
||||
bindKeyAction('ctrlbackslash', send(CTRL, { keysym: KeyTable.XK_backslash, code: 'Backslash' }));
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
bindKeyAction('ctrlaltf' + i, send(CTRL, ALT, { keysym: KeyTable['XK_F' + i], code: 'F' + i }));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue