adding special keys, changing clipboard to write text function

This commit is contained in:
Pawel Raczyk 2019-04-10 10:35:00 +02:00
parent 9a9645829a
commit fdfc5e36dd
2 changed files with 407 additions and 199 deletions

167
app/ui.js
View File

@ -53,7 +53,6 @@ const UI = {
// Render default UI and initialize settings menu // Render default UI and initialize settings menu
start() { start() {
UI.initSettings(); UI.initSettings();
// Translate the DOM // Translate the DOM
@ -77,6 +76,7 @@ const UI = {
UI.addControlbarHandlers(); UI.addControlbarHandlers();
UI.addTouchSpecificHandlers(); UI.addTouchSpecificHandlers();
UI.addExtraKeysHandlers(); UI.addExtraKeysHandlers();
UI.addSpecialKeysHandlers();
UI.addMachineHandlers(); UI.addMachineHandlers();
UI.addConnectionControlHandlers(); UI.addConnectionControlHandlers();
UI.addClipboardHandlers(); UI.addClipboardHandlers();
@ -103,7 +103,9 @@ const UI = {
UI.openConnectPanel(); UI.openConnectPanel();
} }
UI.connect();
return Promise.resolve(UI.rfb); return Promise.resolve(UI.rfb);
}, },
initFullscreen() { initFullscreen() {
@ -283,6 +285,34 @@ const UI = {
document.getElementById("noVNC_send_ctrl_alt_del_button") document.getElementById("noVNC_send_ctrl_alt_del_button")
.addEventListener('click', UI.sendCtrlAltDel); .addEventListener('click', UI.sendCtrlAltDel);
}, },
addSpecialKeysHandlers() {
document.getElementById("noVNC_toggle_special_keys_button")
.addEventListener('click', UI.toggleSpecialKeys);
document.getElementById("noVNC_send_f1_button")
.addEventListener('click', UI.sendF1);
document.getElementById("noVNC_send_f2_button")
.addEventListener('click', UI.sendF2);
document.getElementById("noVNC_send_f3_button")
.addEventListener('click', UI.sendF3);
document.getElementById("noVNC_send_f4_button")
.addEventListener('click', UI.sendF4);
document.getElementById("noVNC_send_f5_button")
.addEventListener('click', UI.sendF5);
document.getElementById("noVNC_send_f6_button")
.addEventListener('click', UI.sendF6);
document.getElementById("noVNC_send_f7_button")
.addEventListener('click', UI.sendF7);
document.getElementById("noVNC_send_f8_button")
.addEventListener('click', UI.sendF8);
document.getElementById("noVNC_send_f9_button")
.addEventListener('click', UI.sendF9);
document.getElementById("noVNC_send_f10_button")
.addEventListener('click', UI.sendF10);
document.getElementById("noVNC_send_f11_button")
.addEventListener('click', UI.sendF11);
document.getElementById("noVNC_send_f12_button")
.addEventListener('click', UI.sendF12);
},
addMachineHandlers() { addMachineHandlers() {
document.getElementById("noVNC_shutdown_button") document.getElementById("noVNC_shutdown_button")
@ -310,8 +340,8 @@ const UI = {
addClipboardHandlers() { addClipboardHandlers() {
document.getElementById("noVNC_clipboard_button") document.getElementById("noVNC_clipboard_button")
.addEventListener('click', UI.toggleClipboardPanel); .addEventListener('click', UI.toggleClipboardPanel);
document.getElementById("noVNC_clipboard_text") document.getElementById("noVNC_clipboard_send_button")
.addEventListener('change', UI.clipboardSend); .addEventListener('click', UI.writeText);
document.getElementById("noVNC_clipboard_clear_button") document.getElementById("noVNC_clipboard_clear_button")
.addEventListener('click', UI.clipboardClear); .addEventListener('click', UI.clipboardClear);
}, },
@ -414,7 +444,7 @@ const UI = {
UI.setMouseButton(1); UI.setMouseButton(1);
// Hide the controlbar after 2 seconds // Hide the controlbar after 2 seconds
UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000); // UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
} else { } else {
UI.enableSetting('encrypt'); UI.enableSetting('encrypt');
UI.enableSetting('shared'); UI.enableSetting('shared');
@ -805,6 +835,7 @@ const UI = {
UI.closePowerPanel(); UI.closePowerPanel();
UI.closeClipboardPanel(); UI.closeClipboardPanel();
UI.closeExtraKeys(); UI.closeExtraKeys();
UI.closeSpecialKeys();
}, },
/* ------^------- /* ------^-------
@ -930,21 +961,46 @@ const UI = {
} }
}, },
clipboardReceive(e) {
Log.Debug(">> UI.clipboardReceive: " + e.detail.text.substr(0, 40) + "...");
document.getElementById('noVNC_clipboard_text').value = e.detail.text;
Log.Debug("<< UI.clipboardReceive");
},
clipboardClear() { clipboardClear() {
document.getElementById('noVNC_clipboard_text').value = ""; document.getElementById('noVNC_clipboard_text').value = "";
UI.rfb.clipboardPasteFrom(""); UI.rfb.clipboardPasteFrom("");
}, },
clipboardSend() { writeText() {
const text = document.getElementById('noVNC_clipboard_text').value; const text = document.getElementById('noVNC_clipboard_text').value;
Log.Debug(">> UI.clipboardSend: " + text.substr(0, 40) + "..."); Log.Debug(">> UI.clipboardSend: " + text.substr(0, 40) + "...");
UI.rfb.clipboardPasteFrom(text);
const textClip = text.split("");
function f(t) {
const character = t.shift();
if (character === undefined) return;
const code = character.charCodeAt();
const needs_shift = '[A-Z!@#$%^&*()_+{}:"<>?~|]'.indexOf(character) !== -1;
const enter = '[\n]'.indexOf(character) !== -1;
if (enter) {
UI.rfb.sendKey(KeyTable.XK_Return, 'XK_Return', true);
}
if (!enter) {
if (needs_shift) {
UI.rfb.sendKey(KeyTable.XK_Shift_L, "ShiftLeft", true);
}
UI.rfb.sendKey(code, "keysym", true);
UI.rfb.sendKey(code, "keysym", false);
if (needs_shift) {
UI.rfb.sendKey(KeyTable.XK_Shift_L, "ShiftLeft", false);
}
}
if (t.length > 0) {
setTimeout( () => {
f(t);
}, 10);
}
}
f(textClip);
Log.Debug("<< UI.clipboardSend"); Log.Debug("<< UI.clipboardSend");
}, },
@ -965,7 +1021,6 @@ const UI = {
}, },
connect(event, password) { connect(event, password) {
// Ignore when rfb already exists // Ignore when rfb already exists
if (typeof UI.rfb !== 'undefined') { if (typeof UI.rfb !== 'undefined') {
return; return;
@ -1025,6 +1080,7 @@ const UI = {
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote'; UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
UI.updateViewOnly(); // requires UI.rfb UI.updateViewOnly(); // requires UI.rfb
}, },
disconnect() { disconnect() {
@ -1548,6 +1604,87 @@ const UI = {
/* ------^------- /* ------^-------
* /EXTRA KEYS * /EXTRA KEYS
* ============== * ==============
* EXTRA SPECIAL KEYS
* ------v------*/
openSpecialKeys() {
UI.closeAllPanels();
UI.openControlbar();
document.getElementById('noVNC_special_modifiers')
.classList.add("noVNC_open");
document.getElementById('noVNC_toggle_special_keys_button')
.classList.add("noVNC_selected");
},
closeSpecialKeys() {
document.getElementById('noVNC_special_modifiers')
.classList.remove("noVNC_open");
document.getElementById('noVNC_toggle_special_keys_button')
.classList.remove("noVNC_selected");
},
toggleSpecialKeys() {
if (document.getElementById('noVNC_special_modifiers')
.classList.contains("noVNC_open")) {
UI.closeSpecialKeys();
} else {
UI.openSpecialKeys();
}
},
sendF1() {
UI.rfb.sendKey(KeyTable.XK_F1, "F1");
},
sendF2() {
UI.rfb.sendKey(KeyTable.XK_F2, "F2");
},
sendF3() {
UI.rfb.sendKey(KeyTable.XK_F3, "F3");
},
sendF4() {
UI.rfb.sendKey(KeyTable.XK_F4, "F4");
},
sendF5() {
UI.rfb.sendKey(KeyTable.XK_F5, "F5");
},
sendF6() {
UI.rfb.sendKey(KeyTable.XK_F6, "F6");
},
sendF7() {
UI.rfb.sendKey(KeyTable.XK_F7, "F7");
},
sendF8() {
UI.rfb.sendKey(KeyTable.XK_F8, "F8");
},
sendF9() {
UI.rfb.sendKey(KeyTable.XK_F9, "F9");
},
sendF10() {
UI.rfb.sendKey(KeyTable.XK_F10, "F10");
},
sendF11() {
UI.rfb.sendKey(KeyTable.XK_F11, "F11");
},
sendF12() {
UI.rfb.sendKey(KeyTable.XK_F12, "F12");
},
/* ------^-------
* /EXTRA SPECIAL KEYS
* ============== * ==============
* MISC * MISC
* ------v------*/ * ------v------*/
@ -1580,6 +1717,8 @@ const UI = {
.classList.add('noVNC_hidden'); .classList.add('noVNC_hidden');
document.getElementById('noVNC_toggle_extra_keys_button') document.getElementById('noVNC_toggle_extra_keys_button')
.classList.add('noVNC_hidden'); .classList.add('noVNC_hidden');
document.getElementById('noVNC_toggle_special_keys_button')
.classList.add('noVNC_hidden');
document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton) document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton)
.classList.add('noVNC_hidden'); .classList.add('noVNC_hidden');
} else { } else {
@ -1587,6 +1726,8 @@ const UI = {
.classList.remove('noVNC_hidden'); .classList.remove('noVNC_hidden');
document.getElementById('noVNC_toggle_extra_keys_button') document.getElementById('noVNC_toggle_extra_keys_button')
.classList.remove('noVNC_hidden'); .classList.remove('noVNC_hidden');
document.getElementById('noVNC_toggle_special_keys_button')
.classList.remove('noVNC_hidden');
document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton) document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton)
.classList.remove('noVNC_hidden'); .classList.remove('noVNC_hidden');
} }

151
vnc.html
View File

@ -75,24 +75,24 @@
<body> <body>
<div id="noVNC_fallback_error" class="noVNC_center"> <div id="noVNC_fallback_error" class="noVNC_center">
<div> <div>
<div>noVNC encountered an error:</div> <div>noVNC encountered an error:</div>
<br> <br>
<div id="noVNC_fallback_errormsg"></div> <div id="noVNC_fallback_errormsg"></div>
</div> </div>
</div>
<!-- noVNC Control Bar -->
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar" class="noVNC_open">
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar">
<div></div>
</div> </div>
<!-- noVNC Control Bar -->
<div id="noVNC_control_bar_anchor" class="noVNC_vcenter">
<div id="noVNC_control_bar">
<div id="noVNC_control_bar_handle" title="Hide/Show the control bar"><div></div></div>
<div class="noVNC_scroll"> <div class="noVNC_scroll">
<h1 class="noVNC_logo" translate="no"><span>no</span><br>VNC</h1>
<!-- Drag/Pan the viewport --> <!-- Drag/Pan the viewport -->
<input type="image" alt="viewport drag" src="app/images/drag.svg" <input type="image" alt="viewport drag" src="app/images/drag.svg"
id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden" id="noVNC_view_drag_button" class="noVNC_button noVNC_hidden"
@ -145,6 +145,53 @@
</div> </div>
</div> </div>
<!-- Extra F1-F12 keys -->
<div id="noVNC_special_keys">
<input type="image" alt="Extra keys F1-F12" src="app/images/togglespecialkeys.svg"
id="noVNC_toggle_special_keys_button" class="noVNC_button"
title="Show F1-F12 Keys">
<div class="noVNC_vcenter">
<div id="noVNC_special_modifiers" class="noVNC_panel">
<input type="image" alt="F1" src="app/images/f1.svg"
id="noVNC_send_f1_button" class="noVNC_button"
title="Send F1">
<input type="image" alt="F2" src="app/images/f2.svg"
id="noVNC_send_f2_button" class="noVNC_button"
title="Send F2">
<input type="image" alt="F3" src="app/images/f3.svg"
id="noVNC_send_f3_button" class="noVNC_button"
title="Send F3">
<input type="image" alt="F4" src="app/images/f4.svg"
id="noVNC_send_f4_button" class="noVNC_button"
title="Send F4">
<input type="image" alt="F5" src="app/images/f5.svg"
id="noVNC_send_f5_button" class="noVNC_button"
title="Send F5">
<input type="image" alt="F6" src="app/images/f6.svg"
id="noVNC_send_f6_button" class="noVNC_button"
title="Send F6">
<input type="image" alt="F7" src="app/images/f7.svg"
id="noVNC_send_f7_button" class="noVNC_button"
title="Send F7">
<input type="image" alt="F8" src="app/images/f8.svg"
id="noVNC_send_f8_button" class="noVNC_button"
title="Send F8">
<input type="image" alt="F9" src="app/images/f9.svg"
id="noVNC_send_f9_button" class="noVNC_button"
title="Send F9">
<input type="image" alt="F10" src="app/images/f10.svg"
id="noVNC_send_f10_button" class="noVNC_button"
title="Send F10">
<input type="image" alt="F11" src="app/images/f11.svg"
id="noVNC_send_f11_button" class="noVNC_button"
title="Send F11">
<input type="image" alt="F12" src="app/images/f12.svg"
id="noVNC_send_f12_button" class="noVNC_button"
title="Send F12">
</div>
</div>
</div>
<!-- Shutdown/Reboot --> <!-- Shutdown/Reboot -->
<input type="image" alt="Shutdown/Reboot" src="app/images/power.svg" <input type="image" alt="Shutdown/Reboot" src="app/images/power.svg"
id="noVNC_power_button" class="noVNC_button" id="noVNC_power_button" class="noVNC_button"
@ -173,6 +220,8 @@
<br> <br>
<input id="noVNC_clipboard_clear_button" type="button" <input id="noVNC_clipboard_clear_button" type="button"
value="Clear" class="noVNC_submit"> value="Clear" class="noVNC_submit">
<input id="noVNC_clipboard_send_button" type="button"
value="Send" class="noVNC_submit">
</div> </div>
</div> </div>
@ -191,13 +240,12 @@
<li class="noVNC_heading"> <li class="noVNC_heading">
<img alt="" src="app/images/settings.svg"> Settings <img alt="" src="app/images/settings.svg"> Settings
</li> </li>
<li> <li style="display: none;">
<label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label> <label><input id="noVNC_setting_shared" type="checkbox"> Shared Mode</label>
</li> </li>
<li> <li style="display: none;">
<label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label> <label><input id="noVNC_setting_view_only" type="checkbox"> View Only</label>
</li> </li>
<li><hr></li>
<li> <li>
<label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label> <label><input id="noVNC_setting_view_clip" type="checkbox"> Clip to Window</label>
</li> </li>
@ -209,19 +257,24 @@
<option value="remote">Remote Resizing</option> <option value="remote">Remote Resizing</option>
</select> </select>
</li> </li>
<li><hr></li>
<li> <li>
<hr>
</li>
<li style="display: none;">
<div class="noVNC_expander">Advanced</div> <div class="noVNC_expander">Advanced</div>
<div><ul> <div>
<ul>
<li> <li>
<label for="noVNC_setting_repeaterID">Repeater ID:</label> <label for="noVNC_setting_repeaterID">Repeater ID:</label>
<input id="noVNC_setting_repeaterID" type="text" value=""> <input id="noVNC_setting_repeaterID" type="text" value="">
</li> </li>
<li> <li>
<div class="noVNC_expander">WebSocket</div> <div class="noVNC_expander">WebSocket</div>
<div><ul> <div>
<ul>
<li> <li>
<label><input id="noVNC_setting_encrypt" type="checkbox"> Encrypt</label> <label><input id="noVNC_setting_encrypt" type="checkbox">
Encrypt</label>
</li> </li>
<li> <li>
<label for="noVNC_setting_host">Host:</label> <label for="noVNC_setting_host">Host:</label>
@ -235,9 +288,12 @@
<label for="noVNC_setting_path">Path:</label> <label for="noVNC_setting_path">Path:</label>
<input id="noVNC_setting_path" type="text" value="websockify"> <input id="noVNC_setting_path" type="text" value="websockify">
</li> </li>
</ul></div> </ul>
</div>
</li>
<li>
<hr>
</li> </li>
<li><hr></li>
<li> <li>
<label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic Reconnect</label> <label><input id="noVNC_setting_reconnect" type="checkbox"> Automatic Reconnect</label>
</li> </li>
@ -245,11 +301,16 @@
<label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label> <label for="noVNC_setting_reconnect_delay">Reconnect Delay (ms):</label>
<input id="noVNC_setting_reconnect_delay" type="number"> <input id="noVNC_setting_reconnect_delay" type="number">
</li> </li>
<li><hr></li>
<li> <li>
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No Cursor</label> <hr>
</li>
<li>
<label><input id="noVNC_setting_show_dot" type="checkbox"> Show Dot when No
Cursor</label>
</li>
<li>
<hr>
</li> </li>
<li><hr></li>
<!-- Logging selection dropdown --> <!-- Logging selection dropdown -->
<li> <li>
<label>Logging: <label>Logging:
@ -257,7 +318,8 @@
</select> </select>
</label> </label>
</li> </li>
</ul></div> </ul>
</div>
</li> </li>
</ul> </ul>
</div> </div>
@ -273,24 +335,27 @@
<div id="noVNC_control_bar_hint"></div> <div id="noVNC_control_bar_hint"></div>
</div> <!-- End of noVNC_control_bar --> </div> <!-- End of noVNC_control_bar -->
<!-- Status Dialog --> <!-- Status Dialog -->
<div id="noVNC_status"></div> <div id="noVNC_status"></div>
<!-- Connect button --> <!-- Connect button -->
<div class="noVNC_center"> <div class="noVNC_center">
<div id="noVNC_connect_dlg"> <div id="noVNC_connect_dlg">
<div class="noVNC_logo" translate="no"><span>no</span>VNC</div> <div class="noVNC_logo" translate="no"><span>no</span>VNC</div>
<div id="noVNC_connect_button"><div> <div id="noVNC_connect_button">
<div>
<img alt="" src="app/images/connect.svg"> Connect <img alt="" src="app/images/connect.svg"> Connect
</div></div>
</div> </div>
</div> </div>
</div>
</div>
<!-- Password Dialog --> <!-- Password Dialog -->
<div class="noVNC_center noVNC_connect_layer"> <div class="noVNC_center noVNC_connect_layer">
<div id="noVNC_password_dlg" class="noVNC_panel"><form> <div id="noVNC_password_dlg" class="noVNC_panel">
<form>
<ul> <ul>
<li> <li>
<label>Password:</label> <label>Password:</label>
@ -300,31 +365,33 @@
<input id="noVNC_password_button" type="submit" value="Send Password" class="noVNC_submit"> <input id="noVNC_password_button" type="submit" value="Send Password" class="noVNC_submit">
</li> </li>
</ul> </ul>
</form></div> </form>
</div> </div>
</div>
<!-- Transition Screens --> <!-- Transition Screens -->
<div id="noVNC_transition"> <div id="noVNC_transition">
<div id="noVNC_transition_text"></div> <div id="noVNC_transition_text"></div>
<div> <div>
<input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit"> <input type="button" id="noVNC_cancel_reconnect_button" value="Cancel" class="noVNC_submit">
</div> </div>
<div class="noVNC_spinner"></div> <div class="noVNC_spinner"></div>
</div> </div>
<!-- This is where the RFB elements will attach --> <!-- This is where the RFB elements will attach -->
<div id="noVNC_container"> <div id="noVNC_container">
<!-- Note that Google Chrome on Android doesn't respect any of these, <!-- Note that Google Chrome on Android doesn't respect any of these,
html attributes which attempt to disable text suggestions on the html attributes which attempt to disable text suggestions on the
on-screen keyboard. Let's hope Chrome implements the ime-mode on-screen keyboard. Let's hope Chrome implements the ime-mode
style for example --> style for example -->
<textarea id="noVNC_keyboardinput" autocapitalize="off" <textarea id="noVNC_keyboardinput" autocapitalize="off"
autocomplete="off" spellcheck="false" tabindex="-1"></textarea> autocomplete="off" spellcheck="false" tabindex="-1"></textarea>
</div> </div>
<audio id="noVNC_bell"> <audio id="noVNC_bell">
<source src="app/sounds/bell.oga" type="audio/ogg"> <source src="app/sounds/bell.oga" type="audio/ogg">
<source src="app/sounds/bell.mp3" type="audio/mpeg"> <source src="app/sounds/bell.mp3" type="audio/mpeg">
</audio> </audio>
</body>
</body>
</html> </html>