1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-07-31 12:41:08 +00:00

update novnc 1.1.0 ->1.2.0

This commit is contained in:
catborise 2020-08-11 15:05:09 +03:00
parent bb935b3713
commit 43f1461e29
53 changed files with 109904 additions and 56529 deletions

View file

@ -1,3 +1,11 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
// NB: this should *not* be included as a module until we have
// native support in the browsers, so that our error handler
// can catch script-loading errors.

View file

@ -15,18 +15,18 @@
inkscape:export-xdpi="90"
sodipodi:docname="windows.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
inkscape:version="0.92.4 (unknown)"
x="0px"
y="0px"
viewBox="-293 384 25 23"
viewBox="-293 384 25 25"
xml:space="preserve"
width="25"
height="23"><metadata
height="25"><metadata
id="metadata21"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs19" /><sodipodi:namedview
pagecolor="#ffffff"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
@ -35,51 +35,31 @@
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-height="1136"
id="namedview17"
showgrid="false"
inkscape:pagecheckerboard="true"
inkscape:zoom="9.44"
inkscape:cx="-0.84745763"
inkscape:cy="12.5"
inkscape:window-x="2552"
inkscape:window-y="122"
showgrid="true"
inkscape:pagecheckerboard="false"
inkscape:zoom="32"
inkscape:cx="3.926913"
inkscape:cy="13.255959"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
inkscape:current-layer="svg2"><inkscape:grid
type="xygrid"
id="grid818" /></sodipodi:namedview>
<style
type="text/css"
id="style2">
.st0{fill:#FFFFFF;}
</style>
<g
id="g14"
transform="matrix(1.2624869,0,0,1.3601695,73.614445,-144.84322)">
<g
id="g12">
<path
class="st0"
d="m -277.4,396 c -0.7,0 -1.3,0 -2,0 -0.4,0 -0.5,-0.1 -0.5,-0.5 0,-1 0,-2 0,-3 0,-0.3 0.2,-0.5 0.5,-0.5 1.3,-0.1 2.6,-0.3 3.9,-0.4 0.4,0 0.7,0.1 0.7,0.6 0,1.1 0,2.2 0,3.3 0,0.4 -0.2,0.6 -0.6,0.6 -0.7,-0.1 -1.4,-0.1 -2,-0.1 z"
id="path4"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
class="st0"
d="m -274.9,399.3 c 0,0.6 0,1.1 0,1.7 0,0.4 -0.1,0.6 -0.6,0.6 -1.4,-0.1 -2.8,-0.3 -4.1,-0.4 -0.3,0 -0.4,-0.3 -0.4,-0.5 0,-1 0,-2 0,-3 0,-0.4 0.2,-0.5 0.6,-0.5 1.3,0 2.6,0 3.9,0 0.5,0 0.6,0.2 0.6,0.6 0,0.4 0,0.9 0,1.5 z"
id="path6"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
class="st0"
d="m -283.5,396 c -0.6,0 -1.3,0 -1.9,0 -0.4,0 -0.6,-0.1 -0.6,-0.6 0,-0.8 0,-1.5 0,-2.3 0,-0.4 0.2,-0.6 0.6,-0.7 1.3,-0.1 2.7,-0.3 4,-0.4 0.4,0 0.5,0.1 0.5,0.5 0,1 0,1.9 0,2.9 0,0.4 -0.2,0.5 -0.5,0.5 -0.8,0.1 -1.5,0.1 -2.1,0.1 z"
id="path8"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
<path
class="st0"
d="m -283.5,397 c 0.6,0 1.3,0 1.9,0 0.4,0 0.6,0.1 0.6,0.5 0,1 0,1.9 0,2.9 0,0.4 -0.2,0.5 -0.5,0.5 -1.3,-0.1 -2.7,-0.3 -4,-0.4 -0.4,0 -0.6,-0.2 -0.6,-0.7 0,-0.7 0,-1.5 0,-2.2 0,-0.5 0.2,-0.7 0.7,-0.7 0.6,0.1 1.2,0.1 1.9,0.1 z"
id="path10"
inkscape:connector-curvature="0"
style="fill:#ffffff" />
</g>
</g>
</svg>
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 21 4 L 11 5.1757812 L 11 12 L 21 12 L 21 4 z M 10 5.2949219 L 4 6 L 4 12 L 10 12 L 10 5.2949219 z "
transform="translate(-293,384)"
id="path853" /><path
id="path858"
d="m -272,405 -10,-1.17578 V 397 h 10 z M -283,403.70508 -289,403 v -6 h 6 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:connector-curvature="0" /></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -0,0 +1 @@
DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES.

View file

@ -0,0 +1,73 @@
{
"Connecting...": "接続しています...",
"Disconnecting...": "切断しています...",
"Reconnecting...": "再接続しています...",
"Internal error": "内部エラー",
"Must set host": "ホストを設定する必要があります",
"Connected (encrypted) to ": "接続しました (暗号化済み): ",
"Connected (unencrypted) to ": "接続しました (暗号化されていません): ",
"Something went wrong, connection is closed": "何かが問題で、接続が閉じられました",
"Failed to connect to server": "サーバーへの接続に失敗しました",
"Disconnected": "切断しました",
"New connection has been rejected with reason: ": "新規接続は次の理由で拒否されました: ",
"New connection has been rejected": "新規接続は拒否されました",
"Password is required": "パスワードが必要です",
"noVNC encountered an error:": "noVNC でエラーが発生しました:",
"Hide/Show the control bar": "コントロールバーを隠す/表示する",
"Move/Drag Viewport": "ビューポートを移動/ドラッグ",
"viewport drag": "ビューポートをドラッグ",
"Active Mouse Button": "アクティブなマウスボタン",
"No mousebutton": "マウスボタンなし",
"Left mousebutton": "左マウスボタン",
"Middle mousebutton": "中マウスボタン",
"Right mousebutton": "右マウスボタン",
"Keyboard": "キーボード",
"Show Keyboard": "キーボードを表示",
"Extra keys": "追加キー",
"Show Extra Keys": "追加キーを表示",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Ctrl キーを切り替え",
"Alt": "Alt",
"Toggle Alt": "Alt キーを切り替え",
"Toggle Windows": "Windows キーを切り替え",
"Windows": "Windows",
"Send Tab": "Tab キーを送信",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Escape キーを送信",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Ctrl-Alt-Del を送信",
"Shutdown/Reboot": "シャットダウン/再起動",
"Shutdown/Reboot...": "シャットダウン/再起動...",
"Power": "電源",
"Shutdown": "シャットダウン",
"Reboot": "再起動",
"Reset": "リセット",
"Clipboard": "クリップボード",
"Clear": "クリア",
"Fullscreen": "全画面表示",
"Settings": "設定",
"Shared Mode": "共有モード",
"View Only": "表示のみ",
"Clip to Window": "ウィンドウにクリップ",
"Scaling Mode:": "スケーリングモード:",
"None": "なし",
"Local Scaling": "ローカルスケーリング",
"Remote Resizing": "リモートでリサイズ",
"Advanced": "高度",
"Repeater ID:": "リピーター ID:",
"WebSocket": "WebSocket",
"Encrypt": "暗号化",
"Host:": "ホスト:",
"Port:": "ポート:",
"Path:": "パス:",
"Automatic Reconnect": "自動再接続",
"Reconnect Delay (ms):": "再接続する遅延 (ミリ秒):",
"Show Dot when No Cursor": "カーソルがないときにドットを表示",
"Logging:": "ロギング:",
"Disconnect": "切断",
"Connect": "接続",
"Password:": "パスワード:",
"Send Password": "パスワードを送信",
"Cancel": "キャンセル"
}

View file

@ -11,16 +11,11 @@
"Disconnected": "Frånkopplad",
"New connection has been rejected with reason: ": "Ny anslutning har blivit nekad med följande skäl: ",
"New connection has been rejected": "Ny anslutning har blivit nekad",
"Password is required": "Lösenord krävs",
"Credentials are required": "Användaruppgifter krävs",
"noVNC encountered an error:": "noVNC stötte på ett problem:",
"Hide/Show the control bar": "Göm/Visa kontrollbaren",
"Drag": "Dra",
"Move/Drag Viewport": "Flytta/Dra Vyn",
"viewport drag": "dra vy",
"Active Mouse Button": "Aktiv musknapp",
"No mousebutton": "Ingen musknapp",
"Left mousebutton": "Vänster musknapp",
"Middle mousebutton": "Mitten-musknapp",
"Right mousebutton": "Höger musknapp",
"Keyboard": "Tangentbord",
"Show Keyboard": "Visa Tangentbord",
"Extra keys": "Extraknappar",
@ -55,6 +50,8 @@
"Local Scaling": "Lokal Skalning",
"Remote Resizing": "Ändra Storlek",
"Advanced": "Avancerat",
"Quality:": "Kvalitet:",
"Compression level:": "Kompressionsnivå:",
"Repeater ID:": "Repeater-ID:",
"WebSocket": "WebSocket",
"Encrypt": "Kryptera",
@ -65,9 +62,11 @@
"Reconnect Delay (ms):": "Fördröjning (ms):",
"Show Dot when No Cursor": "Visa prick när ingen muspekare finns",
"Logging:": "Loggning:",
"Version:": "Version:",
"Disconnect": "Koppla från",
"Connect": "Anslut",
"Username:": "Användarnamn:",
"Password:": "Lösenord:",
"Send Password": "Skicka lösenord",
"Send Credentials": "Skicka Användaruppgifter",
"Cancel": "Avbryt"
}

View file

@ -1,19 +1,19 @@
{
"Connecting...": "接中...",
"Disconnecting...": "正在断连接...",
"Reconnecting...": "重新接中...",
"Connecting...": "接中...",
"Disconnecting...": "正在连接...",
"Reconnecting...": "重新接中...",
"Internal error": "内部错误",
"Must set host": "请提供主机名",
"Connected (encrypted) to ": "已加密链接到",
"Connected (unencrypted) to ": "未加密链接到",
"Something went wrong, connection is closed": "发生错误,接已关闭",
"Failed to connect to server": "无法接到服务器",
"Disconnected": "链接已中断",
"New connection has been rejected with reason: ": "接被拒绝,原因:",
"New connection has been rejected": "接被拒绝",
"Connected (encrypted) to ": "已连接到(加密)",
"Connected (unencrypted) to ": "已连接到(未加密)",
"Something went wrong, connection is closed": "发生错误,接已关闭",
"Failed to connect to server": "无法接到服务器",
"Disconnected": "已断开连接",
"New connection has been rejected with reason: ": "接被拒绝,原因:",
"New connection has been rejected": "接被拒绝",
"Password is required": "请提供密码",
"noVNC encountered an error:": "noVNC 遇到一个错误:",
"Hide/Show the control bar": "显示/隐藏控制",
"Hide/Show the control bar": "显示/隐藏控制",
"Move/Drag Viewport": "拖放显示范围",
"viewport drag": "显示范围拖放",
"Active Mouse Button": "启动鼠标按鍵",
@ -43,10 +43,10 @@
"Reset": "重置",
"Clipboard": "剪贴板",
"Clear": "清除",
"Fullscreen": "全屏",
"Fullscreen": "全屏",
"Settings": "设置",
"Shared Mode": "分享模式",
"View Only": "仅检视",
"View Only": "仅查看",
"Clip to Window": "限制/裁切窗口大小",
"Scaling Mode:": "缩放模式:",
"None": "无",
@ -59,11 +59,11 @@
"Host:": "主机:",
"Port:": "端口:",
"Path:": "路径:",
"Automatic Reconnect": "自动重新接",
"Reconnect Delay (ms):": "重新接间隔 (ms)",
"Automatic Reconnect": "自动重新接",
"Reconnect Delay (ms):": "重新接间隔 (ms)",
"Logging:": "日志级别:",
"Disconnect": "终端链接",
"Connect": "接",
"Disconnect": "中断连接",
"Connect": "接",
"Password:": "密码:",
"Cancel": "取消"
}

View file

@ -1,6 +1,6 @@
/*
* noVNC base CSS
* Copyright (C) 2018 The noVNC Authors
* Copyright (C) 2019 The noVNC Authors
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
*/
@ -22,13 +22,12 @@
body {
margin:0;
padding:0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: Helvetica;
/*Background image with light grey curve.*/
background-color:#494949;
background-repeat:no-repeat;
background-position:right bottom;
height:100%;
display: flex;
touch-action: none;
}
@ -84,8 +83,20 @@ html {
* ----------------------------------------
*/
input[type=input], input[type=password], input[type=number],
input:not([type]), textarea {
input:not([type]),
input[type=date],
input[type=datetime-local],
input[type=email],
input[type=month],
input[type=number],
input[type=password],
input[type=search],
input[type=tel],
input[type=text],
input[type=time],
input[type=url],
input[type=week],
textarea {
/* Disable default rendering */
-webkit-appearance: none;
-moz-appearance: none;
@ -99,7 +110,11 @@ input:not([type]), textarea {
background: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240));
}
input[type=button], input[type=submit], select {
input[type=button],
input[type=color],
input[type=reset],
input[type=submit],
select {
/* Disable default rendering */
-webkit-appearance: none;
-moz-appearance: none;
@ -117,7 +132,10 @@ input[type=button], input[type=submit], select {
vertical-align: middle;
}
input[type=button], input[type=submit] {
input[type=button],
input[type=color],
input[type=reset],
input[type=submit] {
padding-left: 20px;
padding-right: 20px;
}
@ -127,35 +145,72 @@ option {
background: white;
}
input[type=input]:focus, input[type=password]:focus,
input:not([type]):focus, input[type=button]:focus,
input:not([type]):focus,
input[type=button]:focus,
input[type=color]:focus,
input[type=date]:focus,
input[type=datetime-local]:focus,
input[type=email]:focus,
input[type=month]:focus,
input[type=number]:focus,
input[type=password]:focus,
input[type=reset]:focus,
input[type=search]:focus,
input[type=submit]:focus,
textarea:focus, select:focus {
input[type=tel]:focus,
input[type=text]:focus,
input[type=time]:focus,
input[type=url]:focus,
input[type=week]:focus,
select:focus,
textarea:focus {
box-shadow: 0px 0px 3px rgba(74, 144, 217, 0.5);
border-color: rgb(74, 144, 217);
outline: none;
}
input[type=button]::-moz-focus-inner,
input[type=color]::-moz-focus-inner,
input[type=reset]::-moz-focus-inner,
input[type=submit]::-moz-focus-inner {
border: none;
}
input[type=input]:disabled, input[type=password]:disabled,
input:not([type]):disabled, input[type=button]:disabled,
input[type=submit]:disabled, input[type=number]:disabled,
textarea:disabled, select:disabled {
input:not([type]):disabled,
input[type=button]:disabled,
input[type=color]:disabled,
input[type=date]:disabled,
input[type=datetime-local]:disabled,
input[type=email]:disabled,
input[type=month]:disabled,
input[type=number]:disabled,
input[type=password]:disabled,
input[type=reset]:disabled,
input[type=search]:disabled,
input[type=submit]:disabled,
input[type=tel]:disabled,
input[type=text]:disabled,
input[type=time]:disabled,
input[type=url]:disabled,
input[type=week]:disabled,
select:disabled,
textarea:disabled {
color: rgb(128, 128, 128);
background: rgb(240, 240, 240);
}
input[type=button]:active, input[type=submit]:active,
input[type=button]:active,
input[type=color]:active,
input[type=reset]:active,
input[type=submit]:active,
select:active {
border-bottom-width: 1px;
margin-top: 3px;
}
:root:not(.noVNC_touch) input[type=button]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=color]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=reset]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=submit]:hover:not(:disabled),
:root:not(.noVNC_touch) select:hover:not(:disabled) {
background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250));
@ -580,7 +635,7 @@ select:active {
}
/* Extra manual keys */
:root:not(.noVNC_connected) #noVNC_extra_keys {
:root:not(.noVNC_connected) #noVNC_toggle_extra_keys_button {
display: none;
}
@ -632,6 +687,16 @@ select:active {
width: 100px;
}
/* Version */
.noVNC_version_wrapper {
font-size: small;
}
.noVNC_version {
margin-left: 1rem;
}
/* Connection Controls */
:root:not(.noVNC_connected) #noVNC_disconnect_button {
display: none;
@ -781,19 +846,23 @@ select:active {
* ----------------------------------------
*/
#noVNC_password_dlg {
#noVNC_credentials_dlg {
position: relative;
transform: translateY(-50px);
}
#noVNC_password_dlg.noVNC_open {
#noVNC_credentials_dlg.noVNC_open {
transform: translateY(0);
}
#noVNC_password_dlg ul {
#noVNC_credentials_dlg ul {
list-style: none;
margin: 0px;
padding: 0px;
}
.noVNC_hidden {
display: none;
}
/* ----------------------------------------
* Main Area

View file

@ -60,3 +60,8 @@ html {
display: flex;
justify-content: flex-end;
}
#noVNC_container {
flex: 1; /* fill remaining space */
overflow: hidden;
}

View file

@ -1,6 +1,6 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
@ -8,7 +8,7 @@
import * as Log from '../core/util/logging.js';
import _, { l10n } from './localization.js';
import { isTouchDevice, isSafari, isIOS, isAndroid, dragThreshold }
import { isTouchDevice, isSafari, hasScrollbarGutter, dragThreshold }
from '../core/util/browser.js';
import { setCapture, getPointerEvent } from '../core/util/events.js';
import KeyTable from "../core/input/keysym.js";
@ -17,6 +17,8 @@ import Keyboard from "../core/input/keyboard.js";
import RFB from "../core/rfb.js";
import * as WebUtil from "./webutil.js";
const PAGE_TITLE = "noVNC";
const UI = {
connected: false,
@ -35,9 +37,9 @@ const UI = {
lastKeyboardinput: null,
defaultKeyboardinputLen: 100,
inhibit_reconnect: true,
reconnect_callback: null,
reconnect_password: null,
inhibitReconnect: true,
reconnectCallback: null,
reconnectPassword: null,
prime() {
return WebUtil.initSettings().then(() => {
@ -59,6 +61,17 @@ const UI = {
// Translate the DOM
l10n.translateDOM();
WebUtil.fetchJSON('/static/js/novnc/package.json')
.then((packageInfo) => {
Array.from(document.getElementsByClassName('noVNC_version')).forEach(el => el.innerText = packageInfo.version);
})
.catch((err) => {
Log.Error("Couldn't fetch package.json: " + err);
Array.from(document.getElementsByClassName('noVNC_version_wrapper'))
.concat(Array.from(document.getElementsByClassName('noVNC_version_separator')))
.forEach(el => el.style.display = 'none');
});
// Adapt the interface for touch screen devices
if (isTouchDevice) {
document.documentElement.classList.add("noVNC_touch");
@ -148,6 +161,8 @@ const UI = {
UI.initSetting('encrypt', (window.location.protocol === "https:"));
UI.initSetting('view_clip', false);
UI.initSetting('resize', 'off');
UI.initSetting('quality', 6);
UI.initSetting('compression', 2);
UI.initSetting('shared', true);
UI.initSetting('view_only', false);
UI.initSetting('show_dot', false);
@ -219,14 +234,6 @@ const UI = {
},
addTouchSpecificHandlers() {
document.getElementById("noVNC_mouse_button0")
.addEventListener('click', () => UI.setMouseButton(1));
document.getElementById("noVNC_mouse_button1")
.addEventListener('click', () => UI.setMouseButton(2));
document.getElementById("noVNC_mouse_button2")
.addEventListener('click', () => UI.setMouseButton(4));
document.getElementById("noVNC_mouse_button4")
.addEventListener('click', () => UI.setMouseButton(0));
document.getElementById("noVNC_keyboard_button")
.addEventListener('click', UI.toggleVirtualKeyboard);
@ -282,33 +289,6 @@ const UI = {
.addEventListener('click', UI.sendEsc);
document.getElementById("noVNC_send_ctrl_alt_del_button")
.addEventListener('click', UI.sendCtrlAltDel);
document.getElementById('ctrlaltdel')
.addEventListener('click', UI.sendCtrlAltDel);
document.getElementById('ctrlaltf1')
.addEventListener('click', () => UI.sendCtrlAltFN(0));
document.getElementById('ctrlaltf2')
.addEventListener('click', () => UI.sendCtrlAltFN(1));
document.getElementById('ctrlaltf3')
.addEventListener('click', () => UI.sendCtrlAltFN(2));
document.getElementById('ctrlaltf4')
.addEventListener('click', () => UI.sendCtrlAltFN(3));
document.getElementById('ctrlaltf5')
.addEventListener('click', () => UI.sendCtrlAltFN(4));
document.getElementById('ctrlaltf6')
.addEventListener('click', () => UI.sendCtrlAltFN(5));
document.getElementById('ctrlaltf7')
.addEventListener('click', () => UI.sendCtrlAltFN(6));
document.getElementById('ctrlaltf8')
.addEventListener('click', () => UI.sendCtrlAltFN(7));
document.getElementById('ctrlaltf9')
.addEventListener('click', () => UI.sendCtrlAltFN(8));
document.getElementById('ctrlaltf10')
.addEventListener('click', () => UI.sendCtrlAltFN(9));
document.getElementById('ctrlaltf11')
.addEventListener('click', () => UI.sendCtrlAltFN(10));
document.getElementById('ctrlaltf12')
.addEventListener('click', () => UI.sendCtrlAltFN(11));
},
addMachineHandlers() {
@ -330,8 +310,8 @@ const UI = {
document.getElementById("noVNC_cancel_reconnect_button")
.addEventListener('click', UI.cancelReconnect);
document.getElementById("noVNC_password_button")
.addEventListener('click', UI.setPassword);
document.getElementById("noVNC_credentials_button")
.addEventListener('click', UI.setCredentials);
},
addClipboardHandlers() {
@ -361,6 +341,10 @@ const UI = {
UI.addSettingChangeHandler('resize');
UI.addSettingChangeHandler('resize', UI.applyResizeMode);
UI.addSettingChangeHandler('resize', UI.updateViewClip);
UI.addSettingChangeHandler('quality');
UI.addSettingChangeHandler('quality', UI.updateQuality);
UI.addSettingChangeHandler('compression');
UI.addSettingChangeHandler('compression', UI.updateCompression);
UI.addSettingChangeHandler('view_clip');
UI.addSettingChangeHandler('view_clip', UI.updateViewClip);
UI.addSettingChangeHandler('shared');
@ -381,8 +365,6 @@ const UI = {
addFullscreenHandlers() {
document.getElementById("noVNC_fullscreen_button")
.addEventListener('click', UI.toggleFullscreen);
document.getElementById("fullscreen_button")
.addEventListener('click', UI.toggleFullscreen);
window.addEventListener('fullscreenchange', UI.updateFullscreenButton);
window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton);
@ -404,25 +386,25 @@ const UI = {
document.documentElement.classList.remove("noVNC_disconnecting");
document.documentElement.classList.remove("noVNC_reconnecting");
const transition_elem = document.getElementById("noVNC_transition_text");
const transitionElem = document.getElementById("noVNC_transition_text");
switch (state) {
case 'init':
break;
case 'connecting':
transition_elem.textContent = _("Connecting...");
transitionElem.textContent = _("Connecting...");
document.documentElement.classList.add("noVNC_connecting");
break;
case 'connected':
document.documentElement.classList.add("noVNC_connected");
break;
case 'disconnecting':
transition_elem.textContent = _("Disconnecting...");
transitionElem.textContent = _("Disconnecting...");
document.documentElement.classList.add("noVNC_disconnecting");
break;
case 'disconnected':
break;
case 'reconnecting':
transition_elem.textContent = _("Reconnecting...");
transitionElem.textContent = _("Reconnecting...");
document.documentElement.classList.add("noVNC_reconnecting");
break;
default:
@ -440,7 +422,6 @@ const UI = {
UI.disableSetting('port');
UI.disableSetting('path');
UI.disableSetting('repeaterID');
UI.setMouseButton(1);
// Hide the controlbar after 2 seconds
UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000);
@ -455,38 +436,35 @@ const UI = {
UI.keepControlbar();
}
// State change closes the password dialog
document.getElementById('noVNC_password_dlg')
// State change closes dialogs as they may not be relevant
// anymore
UI.closeAllPanels();
document.getElementById('noVNC_credentials_dlg')
.classList.remove('noVNC_open');
},
showStatus(text, status_type, time) {
showStatus(text, statusType, time) {
const statusElem = document.getElementById('noVNC_status');
clearTimeout(UI.statusTimeout);
if (typeof status_type === 'undefined') {
status_type = 'normal';
if (typeof statusType === 'undefined') {
statusType = 'normal';
}
// Don't overwrite more severe visible statuses and never
// errors. Only shows the first error.
let visible_status_type = 'none';
if (statusElem.classList.contains("noVNC_open")) {
if (statusElem.classList.contains("noVNC_status_error")) {
visible_status_type = 'error';
} else if (statusElem.classList.contains("noVNC_status_warn")) {
visible_status_type = 'warn';
} else {
visible_status_type = 'normal';
return;
}
if (statusElem.classList.contains("noVNC_status_warn") &&
statusType === 'normal') {
return;
}
}
if (visible_status_type === 'error' ||
(visible_status_type === 'warn' && status_type === 'normal')) {
return;
}
switch (status_type) {
clearTimeout(UI.statusTimeout);
switch (statusType) {
case 'error':
statusElem.classList.remove("noVNC_status_warn");
statusElem.classList.remove("noVNC_status_normal");
@ -516,7 +494,7 @@ const UI = {
}
// Error messages do not timeout
if (status_type !== 'error') {
if (statusType !== 'error') {
UI.statusTimeout = window.setTimeout(UI.hideStatus, time);
}
},
@ -536,6 +514,13 @@ const UI = {
},
idleControlbar() {
// Don't fade if a child of the control bar has focus
if (document.getElementById('noVNC_control_bar')
.contains(document.activeElement) && document.hasFocus()) {
UI.activateControlbar();
return;
}
document.getElementById('noVNC_control_bar_anchor')
.classList.add("noVNC_idle");
},
@ -553,6 +538,7 @@ const UI = {
UI.closeAllPanels();
document.getElementById('noVNC_control_bar')
.classList.remove("noVNC_open");
UI.rfb.focus();
},
toggleControlbar() {
@ -850,6 +836,8 @@ const UI = {
UI.updateSetting('encrypt');
UI.updateSetting('view_clip');
UI.updateSetting('resize');
UI.updateSetting('quality');
UI.updateSetting('compression');
UI.updateSetting('shared');
UI.updateSetting('view_only');
UI.updateSetting('path');
@ -1006,7 +994,7 @@ const UI = {
if (typeof password === 'undefined') {
password = WebUtil.getConfigVar('password');
UI.reconnect_password = password;
UI.reconnectPassword = password;
}
if (password === null) {
@ -1021,7 +1009,6 @@ const UI = {
return;
}
UI.closeAllPanels();
UI.closeConnectPanel();
UI.updateVisualState('connecting');
@ -1038,7 +1025,6 @@ const UI = {
UI.rfb = new RFB(document.getElementById('noVNC_container'), url,
{ shared: UI.getSetting('shared'),
showDotCursor: UI.getSetting('show_dot'),
repeaterID: UI.getSetting('repeaterID'),
credentials: { password: password } });
UI.rfb.addEventListener("connect", UI.connectFinished);
@ -1052,18 +1038,20 @@ const UI = {
UI.rfb.clipViewport = UI.getSetting('view_clip');
UI.rfb.scaleViewport = UI.getSetting('resize') === 'scale';
UI.rfb.resizeSession = UI.getSetting('resize') === 'remote';
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
UI.rfb.showDotCursor = UI.getSetting('show_dot');
UI.updateViewOnly(); // requires UI.rfb
},
disconnect() {
UI.closeAllPanels();
UI.rfb.disconnect();
UI.connected = false;
// Disable automatic reconnecting
UI.inhibit_reconnect = true;
UI.inhibitReconnect = true;
UI.updateVisualState('disconnecting');
@ -1071,20 +1059,20 @@ const UI = {
},
reconnect() {
UI.reconnect_callback = null;
UI.reconnectCallback = null;
// if reconnect has been disabled in the meantime, do nothing.
if (UI.inhibit_reconnect) {
if (UI.inhibitReconnect) {
return;
}
UI.connect(null, UI.reconnect_password);
UI.connect(null, UI.reconnectPassword);
},
cancelReconnect() {
if (UI.reconnect_callback !== null) {
clearTimeout(UI.reconnect_callback);
UI.reconnect_callback = null;
if (UI.reconnectCallback !== null) {
clearTimeout(UI.reconnectCallback);
UI.reconnectCallback = null;
}
UI.updateVisualState('disconnected');
@ -1095,7 +1083,7 @@ const UI = {
connectFinished(e) {
UI.connected = true;
UI.inhibit_reconnect = false;
UI.inhibitReconnect = false;
let msg;
if (UI.getSetting('encrypt')) {
@ -1129,17 +1117,19 @@ const UI = {
} else {
UI.showStatus(_("Failed to connect to server"), 'error');
}
} else if (UI.getSetting('reconnect', false) === true && !UI.inhibit_reconnect) {
} else if (UI.getSetting('reconnect', false) === true && !UI.inhibitReconnect) {
UI.updateVisualState('reconnecting');
const delay = parseInt(UI.getSetting('reconnect_delay'));
UI.reconnect_callback = setTimeout(UI.reconnect, delay);
UI.reconnectCallback = setTimeout(UI.reconnect, delay);
return;
} else {
UI.updateVisualState('disconnected');
UI.showStatus(_("Disconnected"), 'normal');
}
document.title = PAGE_TITLE;
UI.openControlbar();
UI.openConnectPanel();
},
@ -1166,27 +1156,46 @@ const UI = {
credentials(e) {
// FIXME: handle more types
document.getElementById('noVNC_password_dlg')
document.getElementById("noVNC_username_block").classList.remove("noVNC_hidden");
document.getElementById("noVNC_password_block").classList.remove("noVNC_hidden");
let inputFocus = "none";
if (e.detail.types.indexOf("username") === -1) {
document.getElementById("noVNC_username_block").classList.add("noVNC_hidden");
} else {
inputFocus = inputFocus === "none" ? "noVNC_username_input" : inputFocus;
}
if (e.detail.types.indexOf("password") === -1) {
document.getElementById("noVNC_password_block").classList.add("noVNC_hidden");
} else {
inputFocus = inputFocus === "none" ? "noVNC_password_input" : inputFocus;
}
document.getElementById('noVNC_credentials_dlg')
.classList.add('noVNC_open');
setTimeout(() => document
.getElementById('noVNC_password_input').focus(), 100);
.getElementById(inputFocus).focus(), 100);
Log.Warn("Server asked for a password");
UI.showStatus(_("Password is required"), "warning");
Log.Warn("Server asked for credentials");
UI.showStatus(_("Credentials are required"), "warning");
},
setPassword(e) {
setCredentials(e) {
// Prevent actually submitting the form
e.preventDefault();
const inputElem = document.getElementById('noVNC_password_input');
const password = inputElem.value;
let inputElemUsername = document.getElementById('noVNC_username_input');
const username = inputElemUsername.value;
let inputElemPassword = document.getElementById('noVNC_password_input');
const password = inputElemPassword.value;
// Clear the input after reading the password
inputElem.value = "";
UI.rfb.sendCredentials({ password: password });
UI.reconnect_password = password;
document.getElementById('noVNC_password_dlg')
inputElemPassword.value = "";
UI.rfb.sendCredentials({ username: username, password: password });
UI.reconnectPassword = password;
document.getElementById('noVNC_credentials_dlg')
.classList.remove('noVNC_open');
},
@ -1269,8 +1278,9 @@ const UI = {
// Can't be clipping if viewport is scaled to fit
UI.forceSetting('view_clip', false);
UI.rfb.clipViewport = false;
} else if (isIOS() || isAndroid()) {
// iOS and Android usually have shit scrollbars
} else if (!hasScrollbarGutter) {
// Some platforms have scrollbars that are difficult
// to use in our case, so we always use our own panning
UI.forceSetting('view_clip', true);
UI.rfb.clipViewport = true;
} else {
@ -1313,30 +1323,40 @@ const UI = {
viewDragButton.classList.remove("noVNC_selected");
}
// Different behaviour for touch vs non-touch
// The button is disabled instead of hidden on touch devices
if (isTouchDevice) {
if (UI.rfb.clipViewport) {
viewDragButton.classList.remove("noVNC_hidden");
if (UI.rfb.clipViewport) {
viewDragButton.disabled = false;
} else {
viewDragButton.disabled = true;
}
} else {
viewDragButton.disabled = false;
if (UI.rfb.clipViewport) {
viewDragButton.classList.remove("noVNC_hidden");
} else {
viewDragButton.classList.add("noVNC_hidden");
}
viewDragButton.classList.add("noVNC_hidden");
}
},
/* ------^-------
* /VIEWDRAG
* ==============
* QUALITY
* ------v------*/
updateQuality() {
if (!UI.rfb) return;
UI.rfb.qualityLevel = parseInt(UI.getSetting('quality'));
},
/* ------^-------
* /QUALITY
* ==============
* COMPRESSION
* ------v------*/
updateCompression() {
if (!UI.rfb) return;
UI.rfb.compressionLevel = parseInt(UI.getSetting('compression'));
},
/* ------^-------
* /COMPRESSION
* ==============
* KEYBOARD
* ------v------*/
@ -1531,20 +1551,20 @@ const UI = {
},
sendEsc() {
UI.rfb.sendKey(KeyTable.XK_Escape, "Escape");
UI.sendKey(KeyTable.XK_Escape, "Escape");
},
sendTab() {
UI.rfb.sendKey(KeyTable.XK_Tab);
UI.sendKey(KeyTable.XK_Tab, "Tab");
},
toggleCtrl() {
const btn = document.getElementById('noVNC_toggle_ctrl_button');
if (btn.classList.contains("noVNC_selected")) {
UI.rfb.sendKey(KeyTable.XK_Control_L, "ControlLeft", false);
UI.sendKey(KeyTable.XK_Control_L, "ControlLeft", false);
btn.classList.remove("noVNC_selected");
} else {
UI.rfb.sendKey(KeyTable.XK_Control_L, "ControlLeft", true);
UI.sendKey(KeyTable.XK_Control_L, "ControlLeft", true);
btn.classList.add("noVNC_selected");
}
},
@ -1552,10 +1572,10 @@ const UI = {
toggleWindows() {
const btn = document.getElementById('noVNC_toggle_windows_button');
if (btn.classList.contains("noVNC_selected")) {
UI.rfb.sendKey(KeyTable.XK_Super_L, "MetaLeft", false);
UI.sendKey(KeyTable.XK_Super_L, "MetaLeft", false);
btn.classList.remove("noVNC_selected");
} else {
UI.rfb.sendKey(KeyTable.XK_Super_L, "MetaLeft", true);
UI.sendKey(KeyTable.XK_Super_L, "MetaLeft", true);
btn.classList.add("noVNC_selected");
}
},
@ -1563,20 +1583,39 @@ const UI = {
toggleAlt() {
const btn = document.getElementById('noVNC_toggle_alt_button');
if (btn.classList.contains("noVNC_selected")) {
UI.rfb.sendKey(KeyTable.XK_Alt_L, "AltLeft", false);
UI.sendKey(KeyTable.XK_Alt_L, "AltLeft", false);
btn.classList.remove("noVNC_selected");
} else {
UI.rfb.sendKey(KeyTable.XK_Alt_L, "AltLeft", true);
UI.sendKey(KeyTable.XK_Alt_L, "AltLeft", true);
btn.classList.add("noVNC_selected");
}
},
sendCtrlAltDel() {
UI.rfb.sendCtrlAltDel();
// See below
UI.rfb.focus();
UI.idleControlbar();
},
sendCtrlAltFN: function(f) {
UI.rfb.sendCtrlAltFN(f);
sendKey(keysym, code, down) {
UI.rfb.sendKey(keysym, code, down);
// Move focus to the screen in order to be able to use the
// keyboard right after these extra keys.
// The exception is when a virtual keyboard is used, because
// if we focus the screen the virtual keyboard would be closed.
// In this case we focus our special virtual keyboard input
// element instead.
if (document.getElementById('noVNC_keyboard_button')
.classList.contains("noVNC_selected")) {
document.getElementById('noVNC_keyboardinput').focus();
} else {
UI.rfb.focus();
}
// fade out the controlbar to highlight that
// the focus has been moved to the screen
UI.idleControlbar();
},
/* ------^-------
@ -1585,24 +1624,6 @@ const UI = {
* MISC
* ------v------*/
setMouseButton(num) {
const view_only = UI.rfb.viewOnly;
if (UI.rfb && !view_only) {
UI.rfb.touchButton = num;
}
const blist = [0, 1, 2, 4];
for (let b = 0; b < blist.length; b++) {
const button = document.getElementById('noVNC_mouse_button' +
blist[b]);
if (blist[b] === num && !view_only) {
button.classList.remove("noVNC_hidden");
} else {
button.classList.add("noVNC_hidden");
}
}
},
updateViewOnly() {
if (!UI.rfb) return;
UI.rfb.viewOnly = UI.getSetting('view_only');
@ -1613,14 +1634,14 @@ const UI = {
.classList.add('noVNC_hidden');
document.getElementById('noVNC_toggle_extra_keys_button')
.classList.add('noVNC_hidden');
document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton)
document.getElementById('noVNC_clipboard_button')
.classList.add('noVNC_hidden');
} else {
document.getElementById('noVNC_keyboard_button')
.classList.remove('noVNC_hidden');
document.getElementById('noVNC_toggle_extra_keys_button')
.classList.remove('noVNC_hidden');
document.getElementById('noVNC_mouse_button' + UI.rfb.touchButton)
document.getElementById('noVNC_clipboard_button')
.classList.remove('noVNC_hidden');
}
},
@ -1631,13 +1652,13 @@ const UI = {
},
updateLogging() {
WebUtil.init_logging(UI.getSetting('logging'));
WebUtil.initLogging(UI.getSetting('logging'));
},
updateDesktopName(e) {
UI.desktopName = e.detail.name;
// Display the desktop name in the document title
document.title = e.detail.name + " - noVNC";
document.title = e.detail.name + " - " + PAGE_TITLE;
},
bell(e) {
@ -1673,7 +1694,7 @@ const UI = {
};
// Set up translations
const LINGUAS = ["cs", "de", "el", "es", "ko", "nl", "pl", "ru", "sv", "tr", "zh_CN", "zh_TW"];
const LINGUAS = ["cs", "de", "el", "es", "ja", "ko", "nl", "pl", "ru", "sv", "tr", "zh_CN", "zh_TW"];
l10n.setup(LINGUAS);
if (l10n.language === "en" || l10n.dictionary !== undefined) {
UI.prime();

View file

@ -1,21 +1,21 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
import { init_logging as main_init_logging } from '../core/util/logging.js';
import { initLogging as mainInitLogging } from '../core/util/logging.js';
// init log level reading the logging HTTP param
export function init_logging(level) {
export function initLogging(level) {
"use strict";
if (typeof level !== "undefined") {
main_init_logging(level);
mainInitLogging(level);
} else {
const param = document.location.href.match(/logging=([A-Za-z0-9._-]*)/);
main_init_logging(param || undefined);
mainInitLogging(param || undefined);
}
}
@ -184,7 +184,7 @@ export function injectParamIfMissing(path, param, value) {
const elem = document.createElement('a');
elem.href = path;
const param_eq = encodeURIComponent(param) + "=";
const paramEq = encodeURIComponent(param) + "=";
let query;
if (elem.search) {
query = elem.search.slice(1).split('&');
@ -192,8 +192,8 @@ export function injectParamIfMissing(path, param, value) {
query = [];
}
if (!query.some(v => v.startsWith(param_eq))) {
query.push(param_eq + encodeURIComponent(value));
if (!query.some(v => v.startsWith(paramEq))) {
query.push(paramEq + encodeURIComponent(value));
elem.search = "?" + query.join("&");
}