From ecd49c159fce2d17097f1e622f678621a346f93e Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 2 Sep 2016 16:16:04 +0200 Subject: [PATCH 01/46] Create separate style sheet for vnc_auto.html The style sheet is intimately connected to the Javascript code and HTML so trying to share it between both sets is not sensible. --- app/styles/auto.css | 89 +++++++++++++++++++++++++++++++++++++++++++++ app/styles/base.css | 4 -- vnc_auto.html | 2 +- 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 app/styles/auto.css diff --git a/app/styles/auto.css b/app/styles/auto.css new file mode 100644 index 00000000..50f9a822 --- /dev/null +++ b/app/styles/auto.css @@ -0,0 +1,89 @@ +/* + * noVNC auto CSS + * Copyright (C) 2012 Joel Martin + * Copyright (C) 2016 Samuel Mannehed for Cendio AB + * noVNC is licensed under the MPL 2.0 (see LICENSE.txt) + * This file is licensed under the 2-Clause BSD license (see LICENSE.txt). + */ + +body { + margin:0; + padding:0; + font-family: Helvetica; + /*Background image with light grey curve.*/ + background-color:#494949; + background-repeat:no-repeat; + background-position:right bottom; + height:100%; +} + +html { + height:100%; +} + +#noVNC_container { + display: table; + width:100%; + height:100%; + background-color:#313131; + border-bottom-right-radius: 800px 600px; + /*border-top-left-radius: 800px 600px;*/ +} + +#noVNC_status { + font-size: 12px; + padding-top: 4px; + height:32px; + text-align: center; + font-weight: bold; + color: #fff; + z-index: 0; + position: absolute; + width: 100%; + margin-left: 0px; +} + +.noVNC_status_normal { + background: #b2bdcd; /* Old browsers */ + background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ + background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ +} + +.noVNC_status_error { + background: #f04040; /* Old browsers */ + background: -moz-linear-gradient(top, #f04040 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f04040), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ + background: linear-gradient(top, #f04040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ +} + +.noVNC_status_warn { + background: #f0f040; /* Old browsers */ + background: -moz-linear-gradient(top, #f0f040 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f0f040), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ + background: linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ +} + +#noVNC_buttons { + white-space: nowrap; +} + +/* Do not set width/height for VNC_canvas or incorrect + * scaling will occur. Canvas size depends on remote VNC + * settings and noVNC settings. */ +#noVNC_canvas { + position: absolute; + left: 0; + right: 0; + margin-left: auto; + margin-right: auto; +} diff --git a/app/styles/base.css b/app/styles/base.css index 382234e3..ab6e31d0 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -49,10 +49,6 @@ html { float:right; } -#noVNC_buttons { - white-space: nowrap; -} - #noVNC_view_drag_button { display: none; } diff --git a/vnc_auto.html b/vnc_auto.html index a3c5dc9c..a4cbb236 100644 --- a/vnc_auto.html +++ b/vnc_auto.html @@ -36,7 +36,7 @@ - +
- +
+ + + +
@@ -90,29 +95,99 @@
-
+ + + +
+ + + + + +
+ + +
+ +
+ +
+ + + + +
+ +
    +
  • Encrypt
  • +
  • True Color
  • +
  • Local Cursor
  • +
  • Clip to Window
  • +
  • Shared Mode
  • +
  • View Only
  • +
    +
  • Path
  • +
  • +
  • +
  • Repeater ID
  • +
    + +
  • +
  • + +
  • +
  • +
    +
  • +
+
+
+ + +
+
    +
  • +
  • +
  • +
  • +
  • +
+
@@ -135,78 +210,8 @@
- -
- -
- -
- - -
- - - - - -
- - -
- -
    -
  • Encrypt
  • -
  • True Color
  • -
  • Local Cursor
  • -
  • Clip to Window
  • -
  • Shared Mode
  • -
  • View Only
  • -
    -
  • Path
  • -
  • -
  • -
  • Repeater ID
  • -
    - -
  • -
  • - - -
  • -
  • -
    -
  • -
-
-
- - -
-
    -
  • -
  • -
  • -
  • -
  • -
-
-
-

no
VNC

From 2869308c80d8e30967457ab4ba12ae9318efbf3e Mon Sep 17 00:00:00 2001 From: samhed Date: Wed, 24 Aug 2016 12:17:53 +0200 Subject: [PATCH 05/46] Sort style sheet Sort and group the entries in the style sheet the same way as in the HTML document. Makes it easier to find things. --- app/styles/base.css | 607 ++++++++++++++++++++++---------------------- 1 file changed, 306 insertions(+), 301 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index ff1469ad..a4d6708f 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -21,48 +21,136 @@ html { height:100%; } -#noVNC_controls ul { - list-style: none; - margin: 0px; - padding: 0px; -} -#noVNC_controls li { - padding-bottom:8px; +#noVNC_buttons { + white-space: nowrap; } -#noVNC_setting_host { - width:150px; -} -#noVNC_setting_port { - width: 80px; -} -#noVNC_setting_password { - width: 150px; -} -#noVNC_setting_path { - width: 100px; -} -#noVNC_connect_button { - width: 110px; - float:right; +/* ---------------------------------------- + * Control Bar + * ---------------------------------------- + */ + +#noVNC_control_bar { + position: fixed; + display: block; + height: 36px; + left: 0; + top: 0; + width: 100%; + z-index: 200; } +/* General button style */ +.noVNC_status_button { + padding: 4px 4px; + vertical-align: middle; + border:1px solid #869dbc; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + background: #b2bdcd; /* Old browsers */ + background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b2bdcd', endColorstr='#6e84a3',GradientType=0 ); /* IE6-9 */ + background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ + /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ + font-size: 12px; +} +.noVNC_status_button_selected { + padding: 4px 4px; + vertical-align: middle; + border:1px solid #4366a9; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + background: #779ced; /* Old browsers */ + background: -moz-linear-gradient(top, #779ced 0%, #3970e0 49%, #2160dd 51%, #2463df 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#779ced), color-stop(49%,#3970e0), color-stop(51%,#2160dd), color-stop(100%,#2463df)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Opera11.10+ */ + background: -ms-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* IE10+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#779ced', endColorstr='#2463df',GradientType=0 ); /* IE6-9 */ + background: linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* W3C */ + /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ +} +.noVNC_status_button:disabled { + opacity: 0.4; +} + +/* Panels */ +.triangle-right { + position: relative; + padding: 15px; + color: #fff; + background: #fff; /* default background for browsers without gradient support */ + /* css3 */ + /*background: -webkit-gradient(linear, 0 0, 0 100%, from(#2e88c4), to(#075698)); + background: -moz-linear-gradient(#2e88c4, #075698); + background: -o-linear-gradient(#2e88c4, #075698); + background: linear-gradient(#2e88c4, #075698);*/ + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + color: #000; + border: 2px solid #E0E0E0; +} +.triangle-right.top:after { + border-color: transparent #E0E0E0; + border-width: 20px 20px 0 0; + bottom: auto; + left: auto; + right: 50px; + top: -20px; +} +.triangle-right:after { + content: ""; + position: absolute; + bottom: -20px; /* value = - border-top-width - border-bottom-width */ + left: 50px; /* controls horizontal position */ + border-width: 20px 0 0 20px; /* vary these values to change the angle of the vertex */ + border-style: solid; + border-color: #E0E0E0 transparent; + /* reduce the damage in FF3.0 */ + display: block; + width: 0; +} +.triangle-right.top:after { + top: -40px; /* value = - border-top-width - border-bottom-width */ + right: 50px; /* controls horizontal position */ + bottom: auto; + left: auto; + border-width: 40px 40px 0 0; /* vary these values to change the angle of the vertex */ + border-color: transparent #E0E0E0; +} + +/* Drag/Pan button */ #noVNC_view_drag_button { display: none; } -#noVNC_sendCtrlAltDel_button { - display: none; -} -#noVNC_fullscreen_button { - display: none; -} -#noVNC_xvp_buttons { - display: none; -} + +/* noVNC Touch Device only buttons */ #noVNC_mobile_buttons { display: none; } +#noVNC_keyboardinput { + width: 1px; + height: 1px; + background-color: #fff; + color: #fff; + border: 0; + position: relative; + left: -40px; + z-index: -1; + ime-mode: disabled; +} + +#noVNC_toggleExtraKeys_button { + display: none; +} + #noVNC_extra_keys { display: inline; list-style-type: none; @@ -70,20 +158,28 @@ html { margin: 0px; position: relative; } +#noVNC_toggleCtrl_button { + display: inline; +} +#noVNC_toggleAlt_button { + display: inline; +} +#noVNC_sendTab_button { + display: inline; +} +#noVNC_sendEsc_button { + display: inline; +} +/* Left side buttons */ .noVNC_buttons_left { float: left; z-index: 1; position: relative; + padding-left: 10px; } -.noVNC_buttons_right { - float:right; - right: 0px; - z-index: 2; - position: absolute; -} - +/* Center status display */ #noVNC_status { font-size: 12px; padding-top: 4px; @@ -91,152 +187,11 @@ html { text-align: center; font-weight: bold; color: #fff; -} - -#noVNC_settings_menu { - margin: 3px; - text-align: left; -} -#noVNC_settings_menu ul { - list-style: none; - margin: 0px; - padding: 0px; -} - -#noVNC_settings_apply { - float:right; -} - -#noVNC_container { - display: table; - width:100%; - height:100%; - background-color:#313131; - border-bottom-right-radius: 800px 600px; - /*border-top-left-radius: 800px 600px;*/ -} - -#noVNC_screen { - display: none; + z-index: 0; position: absolute; - margin: 0px; - padding: 0px; - bottom: 0px; - top: 36px; /* the height of the control bar */ - left: 0px; - right: 0px; - width: auto; - height: auto; + width: 100%; + margin-left: 0px; } - -/* Do not set width/height for VNC_canvas or incorrect - * scaling will occur. Canvas size depends on remote VNC - * settings and noVNC settings. */ -#noVNC_canvas { - position: absolute; - left: 0; - right: 0; - margin-left: auto; - margin-right: auto; -} - - -#noVNC_clipboard_clear_button { - float:right; -} - -/*Bubble contents divs*/ -#noVNC_settings { - display:none; - top:73px; - right:20px; - position:fixed; -} - -#noVNC_controls { - display:none; - top:73px; - right:12px; - position:fixed; -} -#noVNC_controls.top:after { - right:15px; -} - -#noVNC_description { - display:none; - position:fixed; - - top:73px; - right:20px; - left:20px; - padding:15px; - color:#000; - background:#eee; /* default background for browsers without gradient support */ - - border:2px solid #E0E0E0; - -webkit-border-radius:10px; - -moz-border-radius:10px; - border-radius:10px; -} - -#noVNC_popup_status { - display:none; - position: fixed; - z-index: 1; - - margin:15px; - top:60px; - padding:15px; - width:auto; - - text-align:center; - font-weight:bold; - word-wrap:break-word; - color:#fff; - background:rgba(0,0,0,0.65); - - -webkit-border-radius:10px; - -moz-border-radius:10px; - border-radius:10px; -} - -#noVNC_xvp { - display:none; - top:73px; - right:30px; - position:fixed; -} -#noVNC_xvp.top:after { - right:125px; -} - -#noVNC_clipboard { - display:none; - top:73px; - right:30px; - position:fixed; -} -#noVNC_clipboard.top:after { - right:85px; -} - -#noVNC_keyboardinput { - width:1px; - height:1px; - background-color:#fff; - color:#fff; - border:0; - position: relative; - left: -40px; - z-index: -1; - ime-mode: disabled; -} - -/* - * Advanced Styling - */ - .noVNC_status_normal { background: #b2bdcd; /* Old browsers */ background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ @@ -265,105 +220,188 @@ html { background: linear-gradient(top, #f0f040 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ } -/* Control bar */ -#noVNC_control_bar { - position:fixed; - - display:block; - height:36px; - left:0; - top:0; - width:100%; - z-index:200; +/* Right side buttons */ +.noVNC_buttons_right { + float: right; + right: 0px; + z-index: 2; + position: absolute; + padding-right: 10px; } -.noVNC_status_button { - padding: 4px 4px; - vertical-align: middle; - border:1px solid #869dbc; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - background: #b2bdcd; /* Old browsers */ - background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b2bdcd', endColorstr='#6e84a3',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ - /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ +/* Send Ctrl+Alt+Delete */ +#noVNC_sendCtrlAltDel_button { + display: none; } -.noVNC_status_button_selected { - padding: 4px 4px; - vertical-align: middle; - border:1px solid #4366a9; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - background: #779ced; /* Old browsers */ - background: -moz-linear-gradient(top, #779ced 0%, #3970e0 49%, #2160dd 51%, #2463df 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#779ced), color-stop(49%,#3970e0), color-stop(51%,#2160dd), color-stop(100%,#2463df)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#779ced', endColorstr='#2463df',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* W3C */ - /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ +/* XVP Shutdown/Reboot */ +#noVNC_xvp { + display: none; + top: 73px; + right: 30px; + position: fixed; +} +#noVNC_xvp.top:after { + right: 125px; +} +#noVNC_xvp_buttons { + display: none; } -.noVNC_status_button:disabled { - opacity: 0.4; +/* Clipboard */ +#noVNC_clipboard { + display: none; + top: 73px; + right: 30px; + position: fixed; +} +#noVNC_clipboard.top:after { + right: 85px; +} +#noVNC_clipboard_text { + width: 500px; +} +#noVNC_clipboard_clear_button { + float: right; } - -/*Settings Bubble*/ -.triangle-right { - position:relative; - padding:15px; - color:#fff; - background:#fff; /* default background for browsers without gradient support */ - /* css3 */ - /*background:-webkit-gradient(linear, 0 0, 0 100%, from(#2e88c4), to(#075698)); - background:-moz-linear-gradient(#2e88c4, #075698); - background:-o-linear-gradient(#2e88c4, #075698); - background:linear-gradient(#2e88c4, #075698);*/ - -webkit-border-radius:10px; - -moz-border-radius:10px; - border-radius:10px; - color:#000; - border:2px solid #E0E0E0; +/* Toggle fullscreen */ +#noVNC_fullscreen_button { + display: none; } -.triangle-right.top:after { - border-color: transparent #E0E0E0; - border-width: 20px 20px 0 0; - bottom: auto; - left: auto; - right: 50px; - top: -20px; +/* Settings */ +#noVNC_settings { + display: none; + top: 73px; + right: 20px; + position: fixed; +} +#noVNC_settings_menu { + margin: 3px; + text-align: left; +} +#noVNC_settings_menu ul { + list-style: none; + margin: 0px; + padding: 0px; +} +#noVNC_setting_path { + width: 100px; +} +#noVNC_settings_apply { + float: right; } -.triangle-right:after { - content:""; - position:absolute; - bottom:-20px; /* value = - border-top-width - border-bottom-width */ - left:50px; /* controls horizontal position */ - border-width:20px 0 0 20px; /* vary these values to change the angle of the vertex */ - border-style:solid; - border-color:#E0E0E0 transparent; - /* reduce the damage in FF3.0 */ - display:block; - width:0; +/* Connection Controls */ +#noVNC_controls { + display: none; + top: 73px; + right: 12px; + position: fixed; +} +#noVNC_controls.top:after { + right:15px; +} +#noVNC_controls ul { + list-style: none; + margin: 0px; + padding: 0px; +} +#noVNC_controls li { + padding-bottom:8px; +} +#noVNC_setting_host { + width:150px; +} +#noVNC_setting_port { + width: 80px; +} +#noVNC_setting_password { + width: 150px; +} +#noVNC_connect_button { + width: 110px; + float: right; } -.triangle-right.top:after { - top:-40px; /* value = - border-top-width - border-bottom-width */ - right:50px; /* controls horizontal position */ - bottom:auto; - left:auto; - border-width:40px 40px 0 0; /* vary these values to change the angle of the vertex */ - border-color:transparent #E0E0E0; +/* Description Panel */ +#noVNC_description { + display: none; + position: fixed; + + top: 73px; + right: 20px; + left: 20px; + padding: 15px; + color: #000; + background: #eee; /* default background for browsers without gradient support */ + + border: 2px solid #E0E0E0; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; +} + +/* Popup Status */ +#noVNC_popup_status { + display: none; + position: fixed; + z-index: 1; + + margin: 15px; + top: 60px; + padding: 15px; + width: auto; + + text-align: center; + font-weight: bold; + word-wrap: break-word; + color: #fff; + background: rgba(0,0,0,0.65); + + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; +} + +/* ---------------------------------------- + * Main Area + * ---------------------------------------- + */ + +#noVNC_container { + display: table; + width: 100%; + height: 100%; + background-color: #313131; + border-bottom-right-radius: 800px 600px; + /*border-top-left-radius: 800px 600px;*/ +} + +/* HTML5 Canvas */ +#noVNC_screen { + display: none; + position: absolute; + margin: 0px; + padding: 0px; + bottom: 0px; + top: 36px; /* the height of the control bar */ + left: 0px; + right: 0px; + width: auto; + height: auto; +} + +/* Do not set width/height for VNC_canvas or incorrect + * scaling will occur. Canvas size depends on remote VNC + * settings and noVNC settings. */ +#noVNC_canvas { + position: absolute; + left: 0; + right: 0; + margin-left: auto; + margin-right: auto; } /*Default noVNC logo.*/ @@ -382,6 +420,7 @@ html { color:yellow; text-align:left; font-family: 'Orbitron', 'OrbitronTTF', sans-serif; + font-size: 180px; line-height:90%; text-shadow: 5px 5px 0 #000, @@ -401,40 +440,6 @@ html { * ---------------------------------------- */ - -.noVNC_status_button { - font-size: 12px; -} - -#noVNC_clipboard_text { - width: 500px; -} - -#noVNC_logo { - font-size: 180px; -} - -.noVNC_buttons_left { - padding-left: 10px; -} - -.noVNC_buttons_right { - padding-right: 10px; -} - -#noVNC_status { - z-index: 0; - position: absolute; - width: 100%; - margin-left: 0px; -} - -#noVNC_toggleExtraKeys_button { display: none; } -#noVNC_toggleCtrl_button { display: inline; } -#noVNC_toggleAlt_button { display: inline; } -#noVNC_sendTab_button { display: inline; } -#noVNC_sendEsc_button { display: inline; } - /* left-align the status text on lower resolutions */ @media screen and (max-width: 800px){ #noVNC_status { From 17eb0fcf504e366bb501e55fdc8784ab1f632897 Mon Sep 17 00:00:00 2001 From: samhed Date: Wed, 24 Aug 2016 16:35:44 +0200 Subject: [PATCH 06/46] Trigger autoconnect at proper time It needs to happen after everything is fully initialised. --- app/ui.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/ui.js b/app/ui.js index 78d397d7..81b7a2d4 100644 --- a/app/ui.js +++ b/app/ui.js @@ -115,14 +115,6 @@ var UI; UI.initSetting('repeaterID', ''); UI.initSetting('token', ''); - var autoconnect = WebUtil.getConfigVar('autoconnect', false); - if (autoconnect === 'true' || autoconnect == '1') { - autoconnect = true; - UI.connect(); - } else { - autoconnect = false; - } - UI.updateVisualState(); document.getElementById('noVNC_setting_host').focus(); @@ -194,6 +186,14 @@ var UI; // Add mouse event click/focus/blur event handlers to the UI UI.addMouseHandlers(); + var autoconnect = WebUtil.getConfigVar('autoconnect', false); + if (autoconnect === 'true' || autoconnect == '1') { + autoconnect = true; + UI.connect(); + } else { + autoconnect = false; + } + if (typeof callback === "function") { callback(UI.rfb); } From bfa414e5e8b3d4e766c8f5989785370439993a1b Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 12:58:58 +0200 Subject: [PATCH 07/46] Remove unused event handlers These do not work and the mechanism for releasing keyboard grab on the settings panel needs more work. --- app/ui.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/ui.js b/app/ui.js index 81b7a2d4..e66ac3a5 100644 --- a/app/ui.js +++ b/app/ui.js @@ -253,8 +253,6 @@ var UI; document.getElementById("noVNC_clipboard_text").onchange = UI.clipboardSend; document.getElementById("noVNC_clipboard_clear_button").onclick = UI.clipboardClear; - document.getElementById("noVNC_settings_menu").onmouseover = UI.displayBlur; - document.getElementById("noVNC_settings_menu").onmouseover = UI.displayFocus; document.getElementById("noVNC_settings_apply").onclick = UI.settingsApply; document.getElementById("noVNC_connect_button").onclick = UI.connect; From d7f790719a1a78eba947ff2de1d9ffb3d4a95556 Mon Sep 17 00:00:00 2001 From: samhed Date: Wed, 24 Aug 2016 17:01:03 +0200 Subject: [PATCH 08/46] Add events to objects the modern way The old way only allows a single event handler per event, so switch over everything to the new model. --- app/ui.js | 102 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/app/ui.js b/app/ui.js index e66ac3a5..e6e34ab1 100644 --- a/app/ui.js +++ b/app/ui.js @@ -217,47 +217,81 @@ var UI; addMouseHandlers: function() { // Setup interface handlers that can't be inline - document.getElementById("noVNC_view_drag_button").onclick = UI.toggleViewDrag; - document.getElementById("noVNC_mouse_button0").onclick = function () { UI.setMouseButton(1); }; - document.getElementById("noVNC_mouse_button1").onclick = function () { UI.setMouseButton(2); }; - document.getElementById("noVNC_mouse_button2").onclick = function () { UI.setMouseButton(4); }; - document.getElementById("noVNC_mouse_button4").onclick = function () { UI.setMouseButton(0); }; - document.getElementById("noVNC_keyboard_button").onclick = UI.showKeyboard; + document.getElementById("noVNC_view_drag_button") + .addEventListener('click', UI.toggleViewDrag); + document.getElementById("noVNC_mouse_button0") + .addEventListener('click', function () { UI.setMouseButton(1); }); + document.getElementById("noVNC_mouse_button1") + .addEventListener('click', function () { UI.setMouseButton(2); }); + document.getElementById("noVNC_mouse_button2") + .addEventListener('click', function () { UI.setMouseButton(4); }); + document.getElementById("noVNC_mouse_button4") + .addEventListener('click', function () { UI.setMouseButton(0); }); + document.getElementById("noVNC_keyboard_button") + .addEventListener('click', UI.showKeyboard); - document.getElementById("noVNC_keyboardinput").oninput = UI.keyInput; - document.getElementById("noVNC_keyboardinput").onblur = UI.hideKeyboard; - document.getElementById("noVNC_keyboardinput").onsubmit = function () { return false; }; + document.getElementById("noVNC_keyboardinput") + .addEventListener('input', UI.keyInput); + document.getElementById("noVNC_keyboardinput") + .addEventListener('blur', UI.hideKeyboard); + document.getElementById("noVNC_keyboardinput") + .addEventListener('submit', function () { return false; }); - document.getElementById("noVNC_toggleExtraKeys_button").onclick = UI.toggleExtraKeys; - document.getElementById("noVNC_toggleCtrl_button").onclick = UI.toggleCtrl; - document.getElementById("noVNC_toggleAlt_button").onclick = UI.toggleAlt; - document.getElementById("noVNC_sendTab_button").onclick = UI.sendTab; - document.getElementById("noVNC_sendEsc_button").onclick = UI.sendEsc; + document.getElementById("noVNC_toggleExtraKeys_button") + .addEventListener('click', UI.toggleExtraKeys); + document.getElementById("noVNC_toggleCtrl_button") + .addEventListener('click', UI.toggleCtrl); + document.getElementById("noVNC_toggleAlt_button") + .addEventListener('click', UI.toggleAlt); + document.getElementById("noVNC_sendTab_button") + .addEventListener('click', UI.sendTab); + document.getElementById("noVNC_sendEsc_button") + .addEventListener('click', UI.sendEsc); - document.getElementById("noVNC_sendCtrlAltDel_button").onclick = UI.sendCtrlAltDel; - document.getElementById("noVNC_xvpShutdown_button").onclick = function() { UI.rfb.xvpShutdown(); }, - document.getElementById("noVNC_xvpReboot_button").onclick = function() { UI.rfb.xvpReboot(); }, - document.getElementById("noVNC_xvpReset_button").onclick = function() { UI.rfb.xvpReset(); }, - document.getElementById("noVNC_status").onclick = UI.popupStatus; - document.getElementById("noVNC_popup_status").onclick = UI.closePopup; - document.getElementById("noVNC_toggleXvp_button").onclick = UI.toggleXvpPanel; - document.getElementById("noVNC_clipboard_button").onclick = UI.toggleClipboardPanel; - document.getElementById("noVNC_fullscreen_button").onclick = UI.toggleFullscreen; - document.getElementById("noVNC_settings_button").onclick = UI.toggleSettingsPanel; - document.getElementById("noVNC_connectPanel_button").onclick = UI.toggleConnectPanel; - document.getElementById("noVNC_disconnect_button").onclick = UI.disconnect; - document.getElementById("noVNC_description_button").onclick = UI.toggleConnectPanel; + document.getElementById("noVNC_sendCtrlAltDel_button") + .addEventListener('click', UI.sendCtrlAltDel); + document.getElementById("noVNC_xvpShutdown_button") + .addEventListener('click', function() { UI.rfb.xvpShutdown(); }); + document.getElementById("noVNC_xvpReboot_button") + .addEventListener('click', function() { UI.rfb.xvpReboot(); }); + document.getElementById("noVNC_xvpReset_button") + .addEventListener('click', function() { UI.rfb.xvpReset(); }); + document.getElementById("noVNC_status") + .addEventListener('click', UI.popupStatus); + document.getElementById("noVNC_popup_status") + .addEventListener('click', UI.closePopup); + document.getElementById("noVNC_toggleXvp_button") + .addEventListener('click', UI.toggleXvpPanel); + document.getElementById("noVNC_clipboard_button") + .addEventListener('click', UI.toggleClipboardPanel); + document.getElementById("noVNC_fullscreen_button") + .addEventListener('click', UI.toggleFullscreen); + document.getElementById("noVNC_settings_button") + .addEventListener('click', UI.toggleSettingsPanel); + document.getElementById("noVNC_connectPanel_button") + .addEventListener('click', UI.toggleConnectPanel); + document.getElementById("noVNC_disconnect_button") + .addEventListener('click', UI.disconnect); + document.getElementById("noVNC_description_button") + .addEventListener('click', UI.toggleConnectPanel); - document.getElementById("noVNC_clipboard_text").onfocus = UI.displayBlur; - document.getElementById("noVNC_clipboard_text").onblur = UI.displayFocus; - document.getElementById("noVNC_clipboard_text").onchange = UI.clipboardSend; - document.getElementById("noVNC_clipboard_clear_button").onclick = UI.clipboardClear; + document.getElementById("noVNC_clipboard_text") + .addEventListener('focus', UI.displayBlur); + document.getElementById("noVNC_clipboard_text") + .addEventListener('blur', UI.displayFocus); + document.getElementById("noVNC_clipboard_text") + .addEventListener('change', UI.clipboardSend); + document.getElementById("noVNC_clipboard_clear_button") + .addEventListener('click', UI.clipboardClear); - document.getElementById("noVNC_settings_apply").onclick = UI.settingsApply; + document.getElementById("noVNC_settings_apply") + .addEventListener('click', UI.settingsApply); - document.getElementById("noVNC_connect_button").onclick = UI.connect; + document.getElementById("noVNC_connect_button") + .addEventListener('click', UI.connect); - document.getElementById("noVNC_setting_resize").onchange = UI.enableDisableViewClip; + document.getElementById("noVNC_setting_resize") + .addEventListener('change', UI.enableDisableViewClip); }, /* ------^------- From 0f6af1e3ec323fda883816747e5a671a12c73e41 Mon Sep 17 00:00:00 2001 From: samhed Date: Wed, 24 Aug 2016 17:23:11 +0200 Subject: [PATCH 09/46] Separate UI.start() in to sub-functions --- app/ui.js | 229 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 130 insertions(+), 99 deletions(-) diff --git a/app/ui.js b/app/ui.js index e6e34ab1..4f17f416 100644 --- a/app/ui.js +++ b/app/ui.js @@ -64,8 +64,68 @@ var UI; // Render default UI and initialize settings menu start: function(callback) { - UI.isTouchDevice = 'ontouchstart' in document.documentElement; + // Setup global variables first + UI.isTouchDevice = 'ontouchstart' in document.documentElement; + UI.isSafari = (navigator.userAgent.indexOf('Safari') !== -1 && + navigator.userAgent.indexOf('Chrome') === -1); + + UI.initSettings(); + + // Show mouse selector buttons on touch screen devices + if (UI.isTouchDevice) { + // Show mobile buttons + document.getElementById('noVNC_mobile_buttons').style.display = "inline"; + UI.setMouseButton(); + // Remove the address bar + setTimeout(function() { window.scrollTo(0, 1); }, 100); + UI.forceSetting('clip', true); + } else { + UI.initSetting('clip', false); + } + + // Setup and initialize event handlers + UI.setupWindowEvents(); + UI.setupFullscreen(); + UI.addControlbarHandlers(); + UI.addTouchSpecificHandlers(); + UI.addXvpHandlers(); + UI.addConnectionControlHandlers(); + UI.addClipboardHandlers(); + UI.addSettingsHandlers(); + + // Show description by default when hosted at for kanaka.github.com + if (location.host === "kanaka.github.io") { + // Open the description dialog + document.getElementById('noVNC_description').style.display = "block"; + } else { + // Show the connect panel on first load unless autoconnecting + if (autoconnect === UI.connSettingsOpen) { + UI.toggleConnectPanel(); + } + } + + UI.setViewClip(); + UI.setBarPosition(); + + UI.updateVisualState(); + + document.getElementById('noVNC_setting_host').focus(); + + var autoconnect = WebUtil.getConfigVar('autoconnect', false); + if (autoconnect === 'true' || autoconnect == '1') { + autoconnect = true; + UI.connect(); + } else { + autoconnect = false; + } + + if (typeof callback === "function") { + callback(UI.rfb); + } + }, + + initSettings: function() { // Stylesheet selection dropdown var sheet = WebUtil.selectStylesheet(); var sheets = WebUtil.getStylesheets(); @@ -114,52 +174,16 @@ var UI; UI.initSetting('path', 'websockify'); UI.initSetting('repeaterID', ''); UI.initSetting('token', ''); + }, - UI.updateVisualState(); - - document.getElementById('noVNC_setting_host').focus(); - - // Show mouse selector buttons on touch screen devices - if (UI.isTouchDevice) { - // Show mobile buttons - document.getElementById('noVNC_mobile_buttons').style.display = "inline"; - UI.setMouseButton(); - // Remove the address bar - setTimeout(function() { window.scrollTo(0, 1); }, 100); - UI.forceSetting('clip', true); - } else { - UI.initSetting('clip', false); - } - - UI.setViewClip(); - UI.setBarPosition(); - - window.addEventListener('resize', function () { + setupWindowEvents: function() { + window.addEventListener( 'resize', function () { UI.applyResizeMode(); UI.setViewClip(); UI.updateViewDrag(); UI.setBarPosition(); } ); - UI.isSafari = (navigator.userAgent.indexOf('Safari') != -1 && - navigator.userAgent.indexOf('Chrome') == -1); - - // Only show the button if fullscreen is properly supported - // * Safari doesn't support alphanumerical input while in fullscreen - if (!UI.isSafari && - (document.documentElement.requestFullscreen || - document.documentElement.mozRequestFullScreen || - document.documentElement.webkitRequestFullscreen || - document.body.msRequestFullscreen)) { - document.getElementById('noVNC_fullscreen_button').style.display = "inline"; - window.addEventListener('fullscreenchange', UI.updateFullscreenButton); - window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton); - window.addEventListener('webkitfullscreenchange', UI.updateFullscreenButton); - window.addEventListener('msfullscreenchange', UI.updateFullscreenButton); - } - - window.addEventListener('load', UI.keyboardinputReset); - // While connected we want to display a confirmation dialogue // if the user tries to leave the page window.addEventListener('beforeunload', function (e) { @@ -171,54 +195,35 @@ var UI; return void 0; // To prevent the dialogue when disconnected } }); + }, - // Show description by default when hosted at for kanaka.github.com - if (location.host === "kanaka.github.io") { - // Open the description dialog - document.getElementById('noVNC_description').style.display = "block"; - } else { - // Show the connect panel on first load unless autoconnecting - if (autoconnect === UI.connSettingsOpen) { - UI.toggleConnectPanel(); - } - } - - // Add mouse event click/focus/blur event handlers to the UI - UI.addMouseHandlers(); - - var autoconnect = WebUtil.getConfigVar('autoconnect', false); - if (autoconnect === 'true' || autoconnect == '1') { - autoconnect = true; - UI.connect(); - } else { - autoconnect = false; - } - - if (typeof callback === "function") { - callback(UI.rfb); + setupFullscreen: function() { + // Only show the button if fullscreen is properly supported + // * Safari doesn't support alphanumerical input while in fullscreen + if (!UI.isSafari && + (document.documentElement.requestFullscreen || + document.documentElement.mozRequestFullScreen || + document.documentElement.webkitRequestFullscreen || + document.body.msRequestFullscreen)) { + document.getElementById('noVNC_fullscreen_button').style.display = "inline"; + UI.addFullscreenHandlers(); } }, - initRFB: function() { - try { - UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), - 'onUpdateState': UI.updateState, - 'onXvpInit': UI.updateXvpButton, - 'onClipboard': UI.clipboardReceive, - 'onFBUComplete': UI.initialResize, - 'onFBResize': UI.updateViewDrag, - 'onDesktopName': UI.updateDocumentTitle}); - return true; - } catch (exc) { - UI.updateState(null, 'fatal', null, 'Unable to create RFB client -- ' + exc); - return false; - } - }, - - addMouseHandlers: function() { - // Setup interface handlers that can't be inline + addControlbarHandlers: function() { document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); + document.getElementById("noVNC_sendCtrlAltDel_button") + .addEventListener('click', UI.sendCtrlAltDel); + document.getElementById("noVNC_status") + .addEventListener('click', UI.popupStatus); + document.getElementById("noVNC_popup_status") + .addEventListener('click', UI.closePopup); + document.getElementById("noVNC_description_button") + .addEventListener('click', UI.toggleConnectPanel); + }, + + addTouchSpecificHandlers: function() { document.getElementById("noVNC_mouse_button0") .addEventListener('click', function () { UI.setMouseButton(1); }); document.getElementById("noVNC_mouse_button1") @@ -237,6 +242,8 @@ var UI; document.getElementById("noVNC_keyboardinput") .addEventListener('submit', function () { return false; }); + window.addEventListener('load', UI.keyboardinputReset); + document.getElementById("noVNC_toggleExtraKeys_button") .addEventListener('click', UI.toggleExtraKeys); document.getElementById("noVNC_toggleCtrl_button") @@ -247,34 +254,31 @@ var UI; .addEventListener('click', UI.sendTab); document.getElementById("noVNC_sendEsc_button") .addEventListener('click', UI.sendEsc); + }, - document.getElementById("noVNC_sendCtrlAltDel_button") - .addEventListener('click', UI.sendCtrlAltDel); + addXvpHandlers: function() { document.getElementById("noVNC_xvpShutdown_button") .addEventListener('click', function() { UI.rfb.xvpShutdown(); }); document.getElementById("noVNC_xvpReboot_button") .addEventListener('click', function() { UI.rfb.xvpReboot(); }); document.getElementById("noVNC_xvpReset_button") .addEventListener('click', function() { UI.rfb.xvpReset(); }); - document.getElementById("noVNC_status") - .addEventListener('click', UI.popupStatus); - document.getElementById("noVNC_popup_status") - .addEventListener('click', UI.closePopup); document.getElementById("noVNC_toggleXvp_button") .addEventListener('click', UI.toggleXvpPanel); - document.getElementById("noVNC_clipboard_button") - .addEventListener('click', UI.toggleClipboardPanel); - document.getElementById("noVNC_fullscreen_button") - .addEventListener('click', UI.toggleFullscreen); - document.getElementById("noVNC_settings_button") - .addEventListener('click', UI.toggleSettingsPanel); + }, + + addConnectionControlHandlers: function() { document.getElementById("noVNC_connectPanel_button") .addEventListener('click', UI.toggleConnectPanel); document.getElementById("noVNC_disconnect_button") .addEventListener('click', UI.disconnect); - document.getElementById("noVNC_description_button") - .addEventListener('click', UI.toggleConnectPanel); + document.getElementById("noVNC_connect_button") + .addEventListener('click', UI.connect); + }, + addClipboardHandlers: function() { + document.getElementById("noVNC_clipboard_button") + .addEventListener('click', UI.toggleClipboardPanel); document.getElementById("noVNC_clipboard_text") .addEventListener('focus', UI.displayBlur); document.getElementById("noVNC_clipboard_text") @@ -283,17 +287,44 @@ var UI; .addEventListener('change', UI.clipboardSend); document.getElementById("noVNC_clipboard_clear_button") .addEventListener('click', UI.clipboardClear); + }, + addSettingsHandlers: function() { + document.getElementById("noVNC_settings_button") + .addEventListener('click', UI.toggleSettingsPanel); document.getElementById("noVNC_settings_apply") .addEventListener('click', UI.settingsApply); - document.getElementById("noVNC_connect_button") - .addEventListener('click', UI.connect); - document.getElementById("noVNC_setting_resize") .addEventListener('change', UI.enableDisableViewClip); }, + addFullscreenHandlers: function() { + document.getElementById("noVNC_fullscreen_button") + .addEventListener('click', UI.toggleFullscreen); + + window.addEventListener('fullscreenchange', UI.updateFullscreenButton); + window.addEventListener('mozfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('webkitfullscreenchange', UI.updateFullscreenButton); + window.addEventListener('msfullscreenchange', UI.updateFullscreenButton); + }, + + initRFB: function() { + try { + UI.rfb = new RFB({'target': document.getElementById('noVNC_canvas'), + 'onUpdateState': UI.updateState, + 'onXvpInit': UI.updateXvpButton, + 'onClipboard': UI.clipboardReceive, + 'onFBUComplete': UI.initialResize, + 'onFBResize': UI.updateViewDrag, + 'onDesktopName': UI.updateDocumentTitle}); + return true; + } catch (exc) { + UI.updateState(null, 'fatal', null, 'Unable to create RFB client -- ' + exc); + return false; + } + }, + /* ------^------- * /INIT * ============== From 3e3eec28f34005b6967c69b2da469fa9b2ea12bc Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 1 Sep 2016 12:35:22 +0200 Subject: [PATCH 10/46] Remove beforeunload handler Support for this is spotty and it is getting more and more restricted by the day. Give up on this approach. --- app/ui.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/ui.js b/app/ui.js index 4f17f416..ce54d34e 100644 --- a/app/ui.js +++ b/app/ui.js @@ -183,18 +183,6 @@ var UI; UI.updateViewDrag(); UI.setBarPosition(); } ); - - // While connected we want to display a confirmation dialogue - // if the user tries to leave the page - window.addEventListener('beforeunload', function (e) { - if (UI.rfb && UI.rfb_state === 'normal') { - var msg = "You are currently connected."; - e.returnValue = msg; - return msg; - } else { - return void 0; // To prevent the dialogue when disconnected - } - }); }, setupFullscreen: function() { From f0d9ab9698d811ead904414092f4730078eb27c7 Mon Sep 17 00:00:00 2001 From: samhed Date: Wed, 24 Aug 2016 18:03:32 +0200 Subject: [PATCH 11/46] Avoid ambigious optional arguments Some functions weren't obvious what they would do if an argument was omitted. Split them up in to separate functions in those cases to make the API clearer. --- app/ui.js | 188 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 90 deletions(-) diff --git a/app/ui.js b/app/ui.js index ce54d34e..124d9ad2 100644 --- a/app/ui.js +++ b/app/ui.js @@ -76,7 +76,7 @@ var UI; if (UI.isTouchDevice) { // Show mobile buttons document.getElementById('noVNC_mobile_buttons').style.display = "inline"; - UI.setMouseButton(); + UI.hideMouseButton(); // Remove the address bar setTimeout(function() { window.scrollTo(0, 1); }, 100); UI.forceSetting('clip', true); @@ -105,7 +105,7 @@ var UI; } } - UI.setViewClip(); + UI.updateViewClip(); UI.setBarPosition(); UI.updateVisualState(); @@ -179,7 +179,7 @@ var UI; setupWindowEvents: function() { window.addEventListener( 'resize', function () { UI.applyResizeMode(); - UI.setViewClip(); + UI.updateViewClip(); UI.updateViewDrag(); UI.setBarPosition(); } ); @@ -381,14 +381,14 @@ var UI; document.getElementById('noVNC_setting_repeaterID').disabled = connected; if (connected) { - UI.setViewClip(); + UI.updateViewClip(); UI.setMouseButton(1); document.getElementById('noVNC_clipboard_button').style.display = "inline"; document.getElementById('noVNC_keyboard_button').style.display = "inline"; document.getElementById('noVNC_extra_keys').style.display = ""; document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "inline"; } else { - UI.setMouseButton(); + UI.hideMouseButton(); document.getElementById('noVNC_clipboard_button').style.display = "none"; document.getElementById('noVNC_keyboard_button').style.display = "none"; document.getElementById('noVNC_extra_keys').style.display = "none"; @@ -398,7 +398,7 @@ var UI; // State change disables viewport dragging. // It is enabled (toggled) by direct click on the button - UI.updateViewDrag(false); + UI.setViewDrag(false); switch (UI.rfb_state) { case 'fatal': @@ -556,7 +556,7 @@ var UI; // Settings with immediate (non-connected related) effect WebUtil.selectStylesheet(UI.getSetting('stylesheet')); WebUtil.init_logging(UI.getSetting('logging')); - UI.setViewClip(); + UI.updateViewClip(); UI.updateViewDrag(); //Util.Debug("<< settingsApply"); }, @@ -956,54 +956,52 @@ var UI; // Set and configure viewport clipping setViewClip: function(clip) { + UI.updateSetting('clip', clip); + UI.updateViewClip(); + }, + + // Update parameters that depend on the clip setting + updateViewClip: function() { var display; - if (UI.rfb) { - display = UI.rfb.get_display(); - } else { - UI.forceSetting('clip', clip); + if (!UI.rfb) { return; } + var display = UI.rfb.get_display(); var cur_clip = display.get_viewport(); + var new_clip = UI.getSetting('clip'); - if (typeof(clip) !== 'boolean') { - // Use current setting - clip = UI.getSetting('clip'); + if (cur_clip !== new_clip) { + display.set_viewport(new_clip); } - if (clip && !cur_clip) { - // Turn clipping on - UI.updateSetting('clip', true); - } else if (!clip && cur_clip) { - // Turn clipping off - UI.updateSetting('clip', false); - display.set_viewport(false); + var size = UI.screenSize(); + + if (new_clip && size) { + // When clipping is enabled, the screen is limited to + // the size of the browser window. + display.set_maxWidth(size.w); + display.set_maxHeight(size.h); + + var screen = document.getElementById('noVNC_screen'); + var canvas = document.getElementById('noVNC_canvas'); + + // Hide potential scrollbars that can skew the position + screen.style.overflow = "hidden"; + + // The x position marks the left margin of the canvas, + // remove the margin from both sides to keep it centered. + var new_w = size.w - (2 * Util.getPosition(canvas).x); + + screen.style.overflow = "visible"; + + display.viewportChangeSize(new_w, size.h); + } else { // Disable max dimensions display.set_maxWidth(0); display.set_maxHeight(0); display.viewportChangeSize(); } - if (UI.getSetting('clip')) { - // If clipping, update clipping settings - display.set_viewport(true); - - var size = UI.screenSize(); - if (size) { - display.set_maxWidth(size.w); - display.set_maxHeight(size.h); - - // Hide potential scrollbars that can skew the position - document.getElementById('noVNC_screen').style.overflow = "hidden"; - - // The x position marks the left margin of the canvas, - // remove the margin from both sides to keep it centered - var new_w = size.w - (2 * Util.getPosition(document.getElementById('noVNC_canvas')).x); - - document.getElementById('noVNC_screen').style.overflow = "visible"; - - display.viewportChangeSize(new_w, size.h); - } - } }, // Handle special cases where clipping is forced on/off or locked @@ -1046,62 +1044,72 @@ var UI; * VIEWDRAG * ------v------*/ - // Update the viewport drag state - updateViewDrag: function(drag) { + toggleViewDrag: function() { if (!UI.rfb) return; - var viewDragButton = document.getElementById('noVNC_view_drag_button'); + var drag = UI.rfb.get_viewportDrag(); + UI.setViewDrag(!drag); + }, + + // Set the view drag mode which moves the viewport on mouse drags + setViewDrag: function(drag) { + if (!UI.rfb) return; + + UI.rfb.set_viewportDrag(drag); + + UI.updateViewDrag(); + }, + + updateViewDrag: function() { + var clipping = false; // Check if viewport drag is possible. It is only possible // if the remote display is clipping the client display. if (UI.rfb_state === 'normal' && UI.rfb.get_display().get_viewport() && UI.rfb.get_display().clippingDisplay()) { - - viewDragButton.style.display = "inline"; - viewDragButton.disabled = false; - - } else { - // The size of the remote display is the same or smaller - // than the client display. Make sure viewport drag isn't - // active when it can't be used. - if (UI.rfb.get_viewportDrag) { - viewDragButton.className = "noVNC_status_button"; - UI.rfb.set_viewportDrag(false); - } - - // The button is disabled instead of hidden on touch devices - if (UI.rfb_state === 'normal' && UI.isTouchDevice) { - viewDragButton.style.display = "inline"; - viewDragButton.disabled = true; - } else { - viewDragButton.style.display = "none"; - } - return; + clipping = true; } - if (typeof(drag) !== "undefined" && - typeof(drag) !== "object") { - if (drag) { - viewDragButton.className = "noVNC_status_button_selected"; - UI.rfb.set_viewportDrag(true); - } else { - viewDragButton.className = "noVNC_status_button"; - UI.rfb.set_viewportDrag(false); - } - } - }, - - toggleViewDrag: function() { - if (!UI.rfb) return; - var viewDragButton = document.getElementById('noVNC_view_drag_button'); - if (UI.rfb.get_viewportDrag()) { - viewDragButton.className = "noVNC_status_button"; - UI.rfb.set_viewportDrag(false); + + if (UI.rfb_state !== 'normal') { + // Always hide when not connected + viewDragButton.style.display = "none"; } else { - viewDragButton.className = "noVNC_status_button_selected"; - UI.rfb.set_viewportDrag(true); + if (!clipping && + UI.rfb.get_viewportDrag()) { + // The size of the remote display is the same or smaller + // than the client display. Make sure viewport drag isn't + // active when it can't be used. + UI.rfb.set_viewportDrag(false); + } + + if (UI.rfb.get_viewportDrag()) { + viewDragButton.className = "noVNC_status_button_selected"; + } else { + viewDragButton.className = "noVNC_status_button"; + } + + // Different behaviour for touch vs non-touch + // The button is disabled instead of hidden on touch devices + if (UI.isTouchDevice) { + viewDragButton.style.display = "inline"; + + if (clipping) { + viewDragButton.disabled = false; + } else { + viewDragButton.disabled = true; + } + } else { + viewDragButton.disabled = false; + + if (clipping) { + viewDragButton.style.display = "inline"; + } else { + viewDragButton.style.display = "none"; + } + } } }, @@ -1292,11 +1300,11 @@ var UI; * MISC * ------v------*/ + hideMouseButton: function() { + UI.setMouseButton(-1); + }, + setMouseButton: function(num) { - if (typeof num === 'undefined') { - // Disable mouse buttons - num = -1; - } if (UI.rfb) { UI.rfb.get_mouse().set_touchButton(num); } From f9fff03719de1d1410a69803a383a267fbd7e503 Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 10:51:43 +0200 Subject: [PATCH 12/46] Remove unused description --- app/styles/base.css | 18 ------------------ app/ui.js | 25 +++---------------------- vnc.html | 16 ---------------- 3 files changed, 3 insertions(+), 56 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index a4d6708f..722d8c38 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -325,24 +325,6 @@ html { float: right; } -/* Description Panel */ -#noVNC_description { - display: none; - position: fixed; - - top: 73px; - right: 20px; - left: 20px; - padding: 15px; - color: #000; - background: #eee; /* default background for browsers without gradient support */ - - border: 2px solid #E0E0E0; - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - border-radius: 10px; -} - /* Popup Status */ #noVNC_popup_status { display: none; diff --git a/app/ui.js b/app/ui.js index 124d9ad2..0a94a0f8 100644 --- a/app/ui.js +++ b/app/ui.js @@ -94,16 +94,9 @@ var UI; UI.addClipboardHandlers(); UI.addSettingsHandlers(); - // Show description by default when hosted at for kanaka.github.com - if (location.host === "kanaka.github.io") { - // Open the description dialog - document.getElementById('noVNC_description').style.display = "block"; - } else { - // Show the connect panel on first load unless autoconnecting - if (autoconnect === UI.connSettingsOpen) { - UI.toggleConnectPanel(); - } - } + // Show the connect panel on first load unless autoconnecting + if (!autoconnect && !UI.connSettingsOpen) + UI.toggleConnectPanel(); UI.updateViewClip(); UI.setBarPosition(); @@ -207,8 +200,6 @@ var UI; .addEventListener('click', UI.popupStatus); document.getElementById("noVNC_popup_status") .addEventListener('click', UI.closePopup); - document.getElementById("noVNC_description_button") - .addEventListener('click', UI.toggleConnectPanel); }, addTouchSpecificHandlers: function() { @@ -563,8 +554,6 @@ var UI; // Open menu openSettingsMenu: function() { - // Close the description panel - document.getElementById('noVNC_description').style.display = "none"; // Close clipboard panel if open if (UI.clipboardOpen === true) { UI.toggleClipboardPanel(); @@ -593,8 +582,6 @@ var UI; // On open, settings are refreshed from saved cookies. // On close, settings are applied toggleSettingsPanel: function() { - // Close the description panel - document.getElementById('noVNC_description').style.display = "none"; if (UI.settingsOpen) { UI.settingsApply(); UI.closeSettingsMenu(); @@ -628,8 +615,6 @@ var UI; // Show the XVP panel toggleXvpPanel: function() { - // Close the description panel - document.getElementById('noVNC_description').style.display = "none"; // Close settings if open if (UI.settingsOpen === true) { UI.settingsApply(); @@ -676,8 +661,6 @@ var UI; // Show the clipboard panel toggleClipboardPanel: function() { - // Close the description panel - document.getElementById('noVNC_description').style.display = "none"; // Close settings if open if (UI.settingsOpen === true) { UI.settingsApply(); @@ -729,8 +712,6 @@ var UI; // Show the connection settings panel/menu toggleConnectPanel: function() { - // Close the description panel - document.getElementById('noVNC_description').style.display = "none"; // Close connection settings if open if (UI.settingsOpen === true) { UI.settingsApply(); diff --git a/vnc.html b/vnc.html index 2830bc1a..5eb3af90 100644 --- a/vnc.html +++ b/vnc.html @@ -190,22 +190,6 @@
- - -
- noVNC is a browser based VNC client implemented using HTML5 Canvas - and WebSockets. You will either need a VNC server with WebSockets - support (such as libvncserver) - or you will need to use - websockify - to bridge between your browser and VNC server. See the noVNC - README - and website - for more information. -
- -
-
From 286947cbe2c0d75ccf38dd332afbbe09334ddb14 Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 11:10:25 +0200 Subject: [PATCH 13/46] Fix name for panel CSS class --- app/styles/base.css | 31 ++++++------------------------- app/styles/black.css | 2 +- app/styles/blue.css | 2 +- vnc.html | 8 ++++---- 4 files changed, 12 insertions(+), 31 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 722d8c38..bceb4f5d 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -80,7 +80,7 @@ html { } /* Panels */ -.triangle-right { +.noVNC_panel { position: relative; padding: 15px; color: #fff; @@ -96,31 +96,12 @@ html { color: #000; border: 2px solid #E0E0E0; } -.triangle-right.top:after { - border-color: transparent #E0E0E0; - border-width: 20px 20px 0 0; - bottom: auto; - left: auto; - right: 50px; - top: -20px; -} -.triangle-right:after { +.noVNC_panel:after { content: ""; position: absolute; - bottom: -20px; /* value = - border-top-width - border-bottom-width */ - left: 50px; /* controls horizontal position */ - border-width: 20px 0 0 20px; /* vary these values to change the angle of the vertex */ - border-style: solid; - border-color: #E0E0E0 transparent; - /* reduce the damage in FF3.0 */ - display: block; - width: 0; -} -.triangle-right.top:after { top: -40px; /* value = - border-top-width - border-bottom-width */ right: 50px; /* controls horizontal position */ - bottom: auto; - left: auto; + border-style: solid; border-width: 40px 40px 0 0; /* vary these values to change the angle of the vertex */ border-color: transparent #E0E0E0; } @@ -241,7 +222,7 @@ html { right: 30px; position: fixed; } -#noVNC_xvp.top:after { +#noVNC_xvp:after { right: 125px; } #noVNC_xvp_buttons { @@ -255,7 +236,7 @@ html { right: 30px; position: fixed; } -#noVNC_clipboard.top:after { +#noVNC_clipboard:after { right: 85px; } #noVNC_clipboard_text { @@ -300,7 +281,7 @@ html { right: 12px; position: fixed; } -#noVNC_controls.top:after { +#noVNC_controls:after { right:15px; } #noVNC_controls ul { diff --git a/app/styles/black.css b/app/styles/black.css index 5c4558dc..7788f7d0 100644 --- a/app/styles/black.css +++ b/app/styles/black.css @@ -38,7 +38,7 @@ background: linear-gradient(top, #f0f040 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */ } -.triangle-right { +.noVNC_panel { border:2px solid #fff; background:#000; color:#fff; diff --git a/app/styles/blue.css b/app/styles/blue.css index 4ab53bde..b986d9b2 100644 --- a/app/styles/blue.css +++ b/app/styles/blue.css @@ -52,7 +52,7 @@ ); } -.triangle-right { +.noVNC_panel { border:2px solid #fff; background:#04073d; color:#fff; diff --git a/vnc.html b/vnc.html index 5eb3af90..d5f45a3f 100644 --- a/vnc.html +++ b/vnc.html @@ -105,7 +105,7 @@ -
+
@@ -117,7 +117,7 @@ -
+

@@ -134,7 +134,7 @@ -
+
  • Encrypt
  • @@ -179,7 +179,7 @@ -
    +
    • From eeb395dc9161dcf5b1d9f08532a389fcb1cde80b Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 13:02:24 +0200 Subject: [PATCH 14/46] Remove unnecessary span:s They were probably also incorrect to have around block elements anyway. --- app/styles/base.css | 8 ++--- vnc.html | 76 +++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 46 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index bceb4f5d..f438a49d 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -258,13 +258,9 @@ html { right: 20px; position: fixed; } -#noVNC_settings_menu { - margin: 3px; - text-align: left; -} -#noVNC_settings_menu ul { +#noVNC_settings ul { list-style: none; - margin: 0px; + margin: 3px; padding: 0px; } #noVNC_setting_path { diff --git a/vnc.html b/vnc.html index d5f45a3f..0521c4e1 100644 --- a/vnc.html +++ b/vnc.html @@ -106,11 +106,9 @@ id="noVNC_toggleXvp_button" class="noVNC_status_button" title="Shutdown/Reboot..." />
      - - - - - + + +
      @@ -135,41 +133,39 @@ id="noVNC_settings_button" class="noVNC_status_button" title="Settings" />
      - -
        -
      • Encrypt
      • -
      • True Color
      • -
      • Local Cursor
      • -
      • Clip to Window
      • -
      • Shared Mode
      • -
      • View Only
      • -
        -
      • Path
      • -
      • -
      • -
      • Repeater ID
      • -
        - -
      • -
      • - -
      • -
      • -
        -
      • -
      -
      +
        +
      • Encrypt
      • +
      • True Color
      • +
      • Local Cursor
      • +
      • Clip to Window
      • +
      • Shared Mode
      • +
      • View Only
      • +
        +
      • Path
      • +
      • +
      • +
      • Repeater ID
      • +
        + +
      • +
      • + +
      • +
      • +
        +
      • +
      From 999f1d45db8008e82865b3706045220dbbf6cc91 Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 13:21:33 +0200 Subject: [PATCH 15/46] Show/hide logo in updateVisualState() We control the visibility of almost everything else in this function, so move the logo handling there as well. --- app/ui.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/ui.js b/app/ui.js index 0a94a0f8..214c6a1d 100644 --- a/app/ui.js +++ b/app/ui.js @@ -322,8 +322,6 @@ var UI; klass = "noVNC_status_normal"; break; case 'disconnected': - document.getElementById('noVNC_logo').style.display = "block"; - document.getElementById('noVNC_screen').style.display = "none"; /* falls through */ case 'loaded': klass = "noVNC_status_normal"; @@ -372,6 +370,8 @@ var UI; document.getElementById('noVNC_setting_repeaterID').disabled = connected; if (connected) { + document.getElementById('noVNC_logo').style.display = "none"; + document.getElementById('noVNC_screen').style.display = "inline"; UI.updateViewClip(); UI.setMouseButton(1); document.getElementById('noVNC_clipboard_button').style.display = "inline"; @@ -379,6 +379,8 @@ var UI; document.getElementById('noVNC_extra_keys').style.display = ""; document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "inline"; } else { + document.getElementById('noVNC_logo').style.display = "block"; + document.getElementById('noVNC_screen').style.display = "none"; UI.hideMouseButton(); document.getElementById('noVNC_clipboard_button').style.display = "none"; document.getElementById('noVNC_keyboard_button').style.display = "none"; @@ -776,8 +778,6 @@ var UI; //Close dialog. setTimeout(UI.setBarPosition, 100); - document.getElementById('noVNC_logo').style.display = "none"; - document.getElementById('noVNC_screen').style.display = "inline"; }, disconnect: function() { @@ -787,9 +787,6 @@ var UI; // Restore the callback used for initial resize UI.rfb.set_onFBUComplete(UI.initialResize); - document.getElementById('noVNC_logo').style.display = "block"; - document.getElementById('noVNC_screen').style.display = "none"; - // Don't display the connection settings until we're actually disconnected }, From 6cba147d4ead73457075bbd3ed7d63b84a96d3e3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 17:32:57 +0200 Subject: [PATCH 16/46] Simplify modifier button display --- app/styles/base.css | 11 +++++++---- app/ui.js | 11 +++-------- vnc.html | 19 +++++++++++-------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index f438a49d..855c737a 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -2,6 +2,7 @@ * noVNC base CSS * Copyright (C) 2012 Joel Martin * Copyright (C) 2016 Samuel Mannehed for Cendio AB + * Copyright (C) 2016 Pierre Ossman for Cendio AB * noVNC is licensed under the MPL 2.0 (see LICENSE.txt) * This file is licensed under the 2-Clause BSD license (see LICENSE.txt). */ @@ -151,6 +152,9 @@ html { #noVNC_sendEsc_button { display: inline; } +#noVNC_modifiers { + display: inline; +} /* Left side buttons */ .noVNC_buttons_left { @@ -430,26 +434,25 @@ html { #noVNC_toggleExtraKeys_button { display: inline; } - #noVNC_toggleCtrl_button { + #noVNC_modifiers { display: none; + } + #noVNC_toggleCtrl_button { position: absolute; top: 30px; left: 0px; } #noVNC_toggleAlt_button { - display: none; position: absolute; top: 65px; left: 0px; } #noVNC_sendTab_button { - display: none; position: absolute; top: 100px; left: 0px; } #noVNC_sendEsc_button { - display: none; position: absolute; top: 135px; left: 0px; diff --git a/app/ui.js b/app/ui.js index 214c6a1d..ee114705 100644 --- a/app/ui.js +++ b/app/ui.js @@ -2,6 +2,7 @@ * noVNC: HTML5 VNC client * Copyright (C) 2012 Joel Martin * Copyright (C) 2016 Samuel Mannehed for Cendio AB + * Copyright (C) 2016 Pierre Ossman for Cendio AB * Licensed under MPL 2.0 (see LICENSE.txt) * * See README.md for usage and integration instructions. @@ -1216,17 +1217,11 @@ var UI; toggleExtraKeys: function() { UI.keepKeyboard(); if(UI.extraKeysVisible === false) { - document.getElementById('noVNC_toggleCtrl_button').style.display = "inline"; - document.getElementById('noVNC_toggleAlt_button').style.display = "inline"; - document.getElementById('noVNC_sendTab_button').style.display = "inline"; - document.getElementById('noVNC_sendEsc_button').style.display = "inline"; + document.getElementById('noVNC_modifiers').style.display = "inline"; document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button_selected"; UI.extraKeysVisible = true; } else if(UI.extraKeysVisible === true) { - document.getElementById('noVNC_toggleCtrl_button').style.display = ""; - document.getElementById('noVNC_toggleAlt_button').style.display = ""; - document.getElementById('noVNC_sendTab_button').style.display = ""; - document.getElementById('noVNC_sendEsc_button').style.display = ""; + document.getElementById('noVNC_modifiers').style.display = ""; document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button"; UI.extraKeysVisible = false; } diff --git a/vnc.html b/vnc.html index 0521c4e1..c7cad8fb 100644 --- a/vnc.html +++ b/vnc.html @@ -6,6 +6,7 @@ noVNC example: simple example using default UI Copyright (C) 2012 Joel Martin Copyright (C) 2016 Samuel Mannehed for Cendio AB + Copyright (C) 2016 Pierre Ossman for Cendio AB noVNC is licensed under the MPL 2.0 (see LICENSE.txt) This file is licensed under the 2-Clause BSD license (see LICENSE.txt). @@ -81,14 +82,16 @@
      - - - - +
      + + + + +
    From e40978c7fcd5f9b2e4c07bd216cb225ba89a0691 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 14:22:44 +0200 Subject: [PATCH 17/46] Let CSS control what it means to be hidden/closed This avoids hard-coding layout information in the JavaScript code. It also opens up possibilities for more control in the CSS, e.g. for animation. --- app/styles/base.css | 45 +++++++------- app/ui.js | 142 ++++++++++++++++++++++++++++---------------- vnc.html | 10 ++-- 3 files changed, 121 insertions(+), 76 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 855c737a..4336375f 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -79,9 +79,13 @@ html { .noVNC_status_button:disabled { opacity: 0.4; } +.noVNC_status_button.noVNC_hidden { + display: none; +} /* Panels */ .noVNC_panel { + display: none; position: relative; padding: 15px; color: #fff; @@ -106,14 +110,15 @@ html { border-width: 40px 40px 0 0; /* vary these values to change the angle of the vertex */ border-color: transparent #E0E0E0; } - -/* Drag/Pan button */ -#noVNC_view_drag_button { - display: none; +.noVNC_panel.noVNC_open { + display: block; } /* noVNC Touch Device only buttons */ #noVNC_mobile_buttons { + display: inline; +} +#noVNC_mobile_buttons.noVNC_hidden { display: none; } @@ -140,6 +145,9 @@ html { margin: 0px; position: relative; } +#noVNC_extra_keys.noVNC_hidden { + display: none; +} #noVNC_toggleCtrl_button { display: inline; } @@ -214,14 +222,8 @@ html { padding-right: 10px; } -/* Send Ctrl+Alt+Delete */ -#noVNC_sendCtrlAltDel_button { - display: none; -} - /* XVP Shutdown/Reboot */ #noVNC_xvp { - display: none; top: 73px; right: 30px; position: fixed; @@ -235,7 +237,6 @@ html { /* Clipboard */ #noVNC_clipboard { - display: none; top: 73px; right: 30px; position: fixed; @@ -250,14 +251,8 @@ html { float: right; } -/* Toggle fullscreen */ -#noVNC_fullscreen_button { - display: none; -} - /* Settings */ #noVNC_settings { - display: none; top: 73px; right: 20px; position: fixed; @@ -276,7 +271,6 @@ html { /* Connection Controls */ #noVNC_controls { - display: none; top: 73px; right: 12px; position: fixed; @@ -308,7 +302,6 @@ html { /* Popup Status */ #noVNC_popup_status { - display: none; position: fixed; z-index: 1; @@ -327,6 +320,9 @@ html { -moz-border-radius: 10px; border-radius: 10px; } +#noVNC_popup_status.noVNC_hidden { + display: none; +} /* ---------------------------------------- * Main Area @@ -344,7 +340,6 @@ html { /* HTML5 Canvas */ #noVNC_screen { - display: none; position: absolute; margin: 0px; padding: 0px; @@ -355,6 +350,9 @@ html { width: auto; height: auto; } +#noVNC_screen.noVNC_hidden { + display: none; +} /* Do not set width/height for VNC_canvas or incorrect * scaling will occur. Canvas size depends on remote VNC @@ -392,7 +390,9 @@ html { -1px 1px 0 #000, 1px 1px 0 #000; } - +#noVNC_logo.noVNC_hidden { + display: none; +} #noVNC_logo span{ color:green; @@ -437,6 +437,9 @@ html { #noVNC_modifiers { display: none; } + #noVNC_modifiers.noVNC_open { + display: inline; + } #noVNC_toggleCtrl_button { position: absolute; top: 30px; diff --git a/app/ui.js b/app/ui.js index ee114705..a9a36b50 100644 --- a/app/ui.js +++ b/app/ui.js @@ -76,7 +76,8 @@ var UI; // Show mouse selector buttons on touch screen devices if (UI.isTouchDevice) { // Show mobile buttons - document.getElementById('noVNC_mobile_buttons').style.display = "inline"; + document.getElementById('noVNC_mobile_buttons') + .classList.remove("noVNC_hidden"); UI.hideMouseButton(); // Remove the address bar setTimeout(function() { window.scrollTo(0, 1); }, 100); @@ -187,7 +188,8 @@ var UI; document.documentElement.mozRequestFullScreen || document.documentElement.webkitRequestFullscreen || document.body.msRequestFullscreen)) { - document.getElementById('noVNC_fullscreen_button').style.display = "inline"; + document.getElementById('noVNC_fullscreen_button') + .classList.remove("noVNC_hidden"); UI.addFullscreenHandlers(); } }, @@ -371,22 +373,34 @@ var UI; document.getElementById('noVNC_setting_repeaterID').disabled = connected; if (connected) { - document.getElementById('noVNC_logo').style.display = "none"; - document.getElementById('noVNC_screen').style.display = "inline"; + document.getElementById('noVNC_logo') + .classList.add("noVNC_hidden"); + document.getElementById('noVNC_screen') + .classList.remove("noVNC_hidden"); UI.updateViewClip(); UI.setMouseButton(1); - document.getElementById('noVNC_clipboard_button').style.display = "inline"; - document.getElementById('noVNC_keyboard_button').style.display = "inline"; - document.getElementById('noVNC_extra_keys').style.display = ""; - document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "inline"; + document.getElementById('noVNC_clipboard_button') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_keyboard_button') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_extra_keys') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_sendCtrlAltDel_button') + .classList.remove("noVNC_hidden"); } else { - document.getElementById('noVNC_logo').style.display = "block"; - document.getElementById('noVNC_screen').style.display = "none"; + document.getElementById('noVNC_logo') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_screen') + .classList.add("noVNC_hidden"); UI.hideMouseButton(); - document.getElementById('noVNC_clipboard_button').style.display = "none"; - document.getElementById('noVNC_keyboard_button').style.display = "none"; - document.getElementById('noVNC_extra_keys').style.display = "none"; - document.getElementById('noVNC_sendCtrlAltDel_button').style.display = "none"; + document.getElementById('noVNC_clipboard_button') + .classList.add("noVNC_hidden"); + document.getElementById('noVNC_keyboard_button') + .classList.add("noVNC_hidden"); + document.getElementById('noVNC_extra_keys') + .classList.add("noVNC_hidden"); + document.getElementById('noVNC_sendCtrlAltDel_button') + .classList.add("noVNC_hidden"); UI.updateXvpButton(0); } @@ -398,18 +412,24 @@ var UI; case 'fatal': case 'failed': case 'disconnected': - document.getElementById('noVNC_connectPanel_button').style.display = ""; - document.getElementById('noVNC_disconnect_button').style.display = "none"; + document.getElementById('noVNC_connectPanel_button') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_disconnect_button') + .classList.add("noVNC_hidden"); UI.connSettingsOpen = false; UI.toggleConnectPanel(); break; case 'loaded': - document.getElementById('noVNC_connectPanel_button').style.display = ""; - document.getElementById('noVNC_disconnect_button').style.display = "none"; + document.getElementById('noVNC_connectPanel_button') + .classList.remove("noVNC_hidden"); + document.getElementById('noVNC_disconnect_button') + .classList.add("noVNC_hidden"); break; default: - document.getElementById('noVNC_connectPanel_button').style.display = "none"; - document.getElementById('noVNC_disconnect_button').style.display = ""; + document.getElementById('noVNC_connectPanel_button') + .classList.add("noVNC_hidden"); + document.getElementById('noVNC_disconnect_button') + .classList.remove("noVNC_hidden"); break; } @@ -426,7 +446,7 @@ var UI; } else { psp.innerHTML = document.getElementById('noVNC_status').innerHTML; } - psp.style.display = "block"; + psp.classList.remove("noVNC_hidden"); psp.style.left = window.innerWidth/2 - parseInt(window.getComputedStyle(psp).width)/2 -30 + "px"; @@ -436,7 +456,7 @@ var UI; closePopup: function() { clearTimeout(UI.popupStatusTimeout); - document.getElementById('noVNC_popup_status').style.display = "none"; + document.getElementById('noVNC_popup_status').classList.add("noVNC_hidden"); }, /* ------^------- @@ -569,15 +589,19 @@ var UI; if (UI.xvpOpen === true) { UI.toggleXvpPanel(); } - document.getElementById('noVNC_settings').style.display = "block"; - document.getElementById('noVNC_settings_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_settings') + .classList.add("noVNC_open"); + document.getElementById('noVNC_settings_button') + .className = "noVNC_status_button_selected"; UI.settingsOpen = true; }, // Close menu (without applying settings) closeSettingsMenu: function() { - document.getElementById('noVNC_settings').style.display = "none"; - document.getElementById('noVNC_settings_button').className = "noVNC_status_button"; + document.getElementById('noVNC_settings') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_settings_button') + .className = "noVNC_status_button"; UI.settingsOpen = false; }, @@ -633,12 +657,16 @@ var UI; } // Toggle XVP panel if (UI.xvpOpen === true) { - document.getElementById('noVNC_xvp').style.display = "none"; - document.getElementById('noVNC_toggleXvp_button').className = "noVNC_status_button"; + document.getElementById('noVNC_xvp') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_toggleXvp_button') + .className = "noVNC_status_button"; UI.xvpOpen = false; } else { - document.getElementById('noVNC_xvp').style.display = "block"; - document.getElementById('noVNC_toggleXvp_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_xvp') + .classList.add("noVNC_open"); + document.getElementById('noVNC_toggleXvp_button') + .className = "noVNC_status_button_selected"; UI.xvpOpen = true; } }, @@ -646,9 +674,11 @@ var UI; // Disable/enable XVP button updateXvpButton: function(ver) { if (ver >= 1) { - document.getElementById('noVNC_toggleXvp_button').style.display = 'inline'; + document.getElementById('noVNC_toggleXvp_button') + .classList.remove("noVNC_hidden"); } else { - document.getElementById('noVNC_toggleXvp_button').style.display = 'none'; + document.getElementById('noVNC_toggleXvp_button') + .classList.add("noVNC_hidden"); // Close XVP panel if open if (UI.xvpOpen === true) { UI.toggleXvpPanel(); @@ -679,12 +709,16 @@ var UI; } // Toggle Clipboard Panel if (UI.clipboardOpen === true) { - document.getElementById('noVNC_clipboard').style.display = "none"; - document.getElementById('noVNC_clipboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_clipboard') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_clipboard_button') + .className = "noVNC_status_button"; UI.clipboardOpen = false; } else { - document.getElementById('noVNC_clipboard').style.display = "block"; - document.getElementById('noVNC_clipboard_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_clipboard') + .classList.add("noVNC_open"); + document.getElementById('noVNC_clipboard_button') + .className = "noVNC_status_button_selected"; UI.clipboardOpen = true; } }, @@ -732,16 +766,20 @@ var UI; // Toggle Connection Panel if (UI.connSettingsOpen === true) { - document.getElementById('noVNC_controls').style.display = "none"; - document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button"; + document.getElementById('noVNC_controls') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_connectPanel_button') + .className = "noVNC_status_button"; UI.connSettingsOpen = false; UI.saveSetting('host'); UI.saveSetting('port'); UI.saveSetting('token'); //UI.saveSetting('password'); } else { - document.getElementById('noVNC_controls').style.display = "block"; - document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_controls') + .classList.add("noVNC_open"); + document.getElementById('noVNC_connectPanel_button') + .className = "noVNC_status_button_selected"; UI.connSettingsOpen = true; document.getElementById('noVNC_setting_host').focus(); } @@ -1054,7 +1092,7 @@ var UI; if (UI.rfb_state !== 'normal') { // Always hide when not connected - viewDragButton.style.display = "none"; + viewDragButton.classList.add("noVNC_hidden"); } else { if (!clipping && UI.rfb.get_viewportDrag()) { @@ -1073,7 +1111,7 @@ var UI; // Different behaviour for touch vs non-touch // The button is disabled instead of hidden on touch devices if (UI.isTouchDevice) { - viewDragButton.style.display = "inline"; + viewDragButton.classList.remove("noVNC_hidden"); if (clipping) { viewDragButton.disabled = false; @@ -1084,9 +1122,9 @@ var UI; viewDragButton.disabled = false; if (clipping) { - viewDragButton.style.display = "inline"; + viewDragButton.classList.remove("noVNC_hidden"); } else { - viewDragButton.style.display = "none"; + viewDragButton.classList.add("noVNC_hidden"); } } } @@ -1217,12 +1255,16 @@ var UI; toggleExtraKeys: function() { UI.keepKeyboard(); if(UI.extraKeysVisible === false) { - document.getElementById('noVNC_modifiers').style.display = "inline"; - document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_modifiers') + .classList.add("noVNC_open"); + document.getElementById('noVNC_toggleExtraKeys_button') + .className = "noVNC_status_button_selected"; UI.extraKeysVisible = true; } else if(UI.extraKeysVisible === true) { - document.getElementById('noVNC_modifiers').style.display = ""; - document.getElementById('noVNC_toggleExtraKeys_button').className = "noVNC_status_button"; + document.getElementById('noVNC_modifiers') + .classList.remove("noVNC_open"); + document.getElementById('noVNC_toggleExtraKeys_button') + .className = "noVNC_status_button"; UI.extraKeysVisible = false; } }, @@ -1286,9 +1328,9 @@ var UI; for (var b = 0; b < blist.length; b++) { var button = document.getElementById('noVNC_mouse_button' + blist[b]); if (blist[b] === num) { - button.style.display = ""; + button.classList.remove("noVNC_hidden"); } else { - button.style.display = "none"; + button.classList.add("noVNC_hidden"); } } }, diff --git a/vnc.html b/vnc.html index c7cad8fb..b4d0a373 100644 --- a/vnc.html +++ b/vnc.html @@ -56,11 +56,11 @@ -
    +
    @@ -190,7 +190,7 @@
    -
    +
    @@ -199,7 +199,7 @@

    no
    VNC

    -
    +
    Canvas not supported. From a49d92984608959620dc9c35d3c4739a0929715d Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 14:41:53 +0200 Subject: [PATCH 18/46] Harmonise CSS names Follow the same naming convention for all CSS ids and classes. --- app/styles/base.css | 40 ++++++++-------- app/styles/black.css | 4 +- app/ui.js | 110 +++++++++++++++++++++++-------------------- vnc.html | 44 ++++++++--------- 4 files changed, 104 insertions(+), 94 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 4336375f..d1d83a3b 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -42,7 +42,7 @@ html { } /* General button style */ -.noVNC_status_button { +.noVNC_button { padding: 4px 4px; vertical-align: middle; border:1px solid #869dbc; @@ -60,7 +60,7 @@ html { /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ font-size: 12px; } -.noVNC_status_button_selected { +.noVNC_button_selected { padding: 4px 4px; vertical-align: middle; border:1px solid #4366a9; @@ -76,10 +76,10 @@ html { background: linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* W3C */ /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ } -.noVNC_status_button:disabled { +.noVNC_button:disabled { opacity: 0.4; } -.noVNC_status_button.noVNC_hidden { +.noVNC_button.noVNC_hidden { display: none; } @@ -134,7 +134,7 @@ html { ime-mode: disabled; } -#noVNC_toggleExtraKeys_button { +#noVNC_toggle_extra_keys_button { display: none; } @@ -148,16 +148,16 @@ html { #noVNC_extra_keys.noVNC_hidden { display: none; } -#noVNC_toggleCtrl_button { +#noVNC_toggle_ctrl_button { display: inline; } -#noVNC_toggleAlt_button { +#noVNC_toggle_alt_button { display: inline; } -#noVNC_sendTab_button { +#noVNC_send_tab_button { display: inline; } -#noVNC_sendEsc_button { +#noVNC_send_esc_button { display: inline; } #noVNC_modifiers { @@ -270,20 +270,20 @@ html { } /* Connection Controls */ -#noVNC_controls { +#noVNC_connect_controls { top: 73px; right: 12px; position: fixed; } -#noVNC_controls:after { +#noVNC_connect_controls:after { right:15px; } -#noVNC_controls ul { +#noVNC_connect_controls ul { list-style: none; margin: 0px; padding: 0px; } -#noVNC_controls li { +#noVNC_connect_controls li { padding-bottom:8px; } #noVNC_setting_host { @@ -421,7 +421,7 @@ html { #noVNC_logo { font-size: 150px; } - .noVNC_status_button { + .noVNC_button { font-size: 10px; } .noVNC_buttons_left { @@ -431,7 +431,7 @@ html { padding-right: 0px; } /* collapse the extra keys on lower resolutions */ - #noVNC_toggleExtraKeys_button { + #noVNC_toggle_extra_keys_button { display: inline; } #noVNC_modifiers { @@ -440,22 +440,22 @@ html { #noVNC_modifiers.noVNC_open { display: inline; } - #noVNC_toggleCtrl_button { + #noVNC_toggle_ctrl_button { position: absolute; top: 30px; left: 0px; } - #noVNC_toggleAlt_button { + #noVNC_toggle_alt_button { position: absolute; top: 65px; left: 0px; } - #noVNC_sendTab_button { + #noVNC_send_tab_button { position: absolute; top: 100px; left: 0px; } - #noVNC_sendEsc_button { + #noVNC_send_esc_button { position: absolute; top: 135px; left: 0px; @@ -472,7 +472,7 @@ html { } @media screen and (max-width: 320px) { - .noVNC_status_button { + .noVNC_button { font-size: 9px; } #noVNC_clipboard_text { diff --git a/app/styles/black.css b/app/styles/black.css index 7788f7d0..9a3d5d2e 100644 --- a/app/styles/black.css +++ b/app/styles/black.css @@ -44,7 +44,7 @@ color:#fff; } -.noVNC_status_button { +.noVNC_button { font-size: 12px; vertical-align: middle; border:1px solid #4c4c4c; @@ -59,7 +59,7 @@ background: linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */ } -.noVNC_status_button_selected { +.noVNC_button_selected { background: #9dd53a; /* Old browsers */ background: -moz-linear-gradient(top, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#9dd53a), color-stop(50%,#a1d54f), color-stop(51%,#80c217), color-stop(100%,#7cbc0a)); /* Chrome,Safari4+ */ diff --git a/app/ui.js b/app/ui.js index a9a36b50..907e41da 100644 --- a/app/ui.js +++ b/app/ui.js @@ -197,7 +197,7 @@ var UI; addControlbarHandlers: function() { document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); - document.getElementById("noVNC_sendCtrlAltDel_button") + document.getElementById("noVNC_send_ctrl_alt_del_button") .addEventListener('click', UI.sendCtrlAltDel); document.getElementById("noVNC_status") .addEventListener('click', UI.popupStatus); @@ -226,31 +226,31 @@ var UI; window.addEventListener('load', UI.keyboardinputReset); - document.getElementById("noVNC_toggleExtraKeys_button") + document.getElementById("noVNC_toggle_extra_keys_button") .addEventListener('click', UI.toggleExtraKeys); - document.getElementById("noVNC_toggleCtrl_button") + document.getElementById("noVNC_toggle_ctrl_button") .addEventListener('click', UI.toggleCtrl); - document.getElementById("noVNC_toggleAlt_button") + document.getElementById("noVNC_toggle_alt_button") .addEventListener('click', UI.toggleAlt); - document.getElementById("noVNC_sendTab_button") + document.getElementById("noVNC_send_tab_button") .addEventListener('click', UI.sendTab); - document.getElementById("noVNC_sendEsc_button") + document.getElementById("noVNC_send_esc_button") .addEventListener('click', UI.sendEsc); }, addXvpHandlers: function() { - document.getElementById("noVNC_xvpShutdown_button") + document.getElementById("noVNC_xvp_shutdown_button") .addEventListener('click', function() { UI.rfb.xvpShutdown(); }); - document.getElementById("noVNC_xvpReboot_button") + document.getElementById("noVNC_xvp_reboot_button") .addEventListener('click', function() { UI.rfb.xvpReboot(); }); - document.getElementById("noVNC_xvpReset_button") + document.getElementById("noVNC_xvp_reset_button") .addEventListener('click', function() { UI.rfb.xvpReset(); }); - document.getElementById("noVNC_toggleXvp_button") + document.getElementById("noVNC_xvp_button") .addEventListener('click', UI.toggleXvpPanel); }, addConnectionControlHandlers: function() { - document.getElementById("noVNC_connectPanel_button") + document.getElementById("noVNC_connect_controls_button") .addEventListener('click', UI.toggleConnectPanel); document.getElementById("noVNC_disconnect_button") .addEventListener('click', UI.disconnect); @@ -385,7 +385,7 @@ var UI; .classList.remove("noVNC_hidden"); document.getElementById('noVNC_extra_keys') .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_sendCtrlAltDel_button') + document.getElementById('noVNC_send_ctrl_alt_del_button') .classList.remove("noVNC_hidden"); } else { document.getElementById('noVNC_logo') @@ -399,7 +399,7 @@ var UI; .classList.add("noVNC_hidden"); document.getElementById('noVNC_extra_keys') .classList.add("noVNC_hidden"); - document.getElementById('noVNC_sendCtrlAltDel_button') + document.getElementById('noVNC_send_ctrl_alt_del_button') .classList.add("noVNC_hidden"); UI.updateXvpButton(0); } @@ -412,7 +412,7 @@ var UI; case 'fatal': case 'failed': case 'disconnected': - document.getElementById('noVNC_connectPanel_button') + document.getElementById('noVNC_connect_controls_button') .classList.remove("noVNC_hidden"); document.getElementById('noVNC_disconnect_button') .classList.add("noVNC_hidden"); @@ -420,13 +420,13 @@ var UI; UI.toggleConnectPanel(); break; case 'loaded': - document.getElementById('noVNC_connectPanel_button') + document.getElementById('noVNC_connect_controls_button') .classList.remove("noVNC_hidden"); document.getElementById('noVNC_disconnect_button') .classList.add("noVNC_hidden"); break; default: - document.getElementById('noVNC_connectPanel_button') + document.getElementById('noVNC_connect_controls_button') .classList.add("noVNC_hidden"); document.getElementById('noVNC_disconnect_button') .classList.remove("noVNC_hidden"); @@ -592,7 +592,7 @@ var UI; document.getElementById('noVNC_settings') .classList.add("noVNC_open"); document.getElementById('noVNC_settings_button') - .className = "noVNC_status_button_selected"; + .className = "noVNC_button_selected"; UI.settingsOpen = true; }, @@ -601,7 +601,7 @@ var UI; document.getElementById('noVNC_settings') .classList.remove("noVNC_open"); document.getElementById('noVNC_settings_button') - .className = "noVNC_status_button"; + .className = "noVNC_button"; UI.settingsOpen = false; }, @@ -659,14 +659,14 @@ var UI; if (UI.xvpOpen === true) { document.getElementById('noVNC_xvp') .classList.remove("noVNC_open"); - document.getElementById('noVNC_toggleXvp_button') - .className = "noVNC_status_button"; + document.getElementById('noVNC_xvp_button') + .className = "noVNC_button"; UI.xvpOpen = false; } else { document.getElementById('noVNC_xvp') .classList.add("noVNC_open"); - document.getElementById('noVNC_toggleXvp_button') - .className = "noVNC_status_button_selected"; + document.getElementById('noVNC_xvp_button') + .className = "noVNC_button_selected"; UI.xvpOpen = true; } }, @@ -674,10 +674,10 @@ var UI; // Disable/enable XVP button updateXvpButton: function(ver) { if (ver >= 1) { - document.getElementById('noVNC_toggleXvp_button') + document.getElementById('noVNC_xvp_button') .classList.remove("noVNC_hidden"); } else { - document.getElementById('noVNC_toggleXvp_button') + document.getElementById('noVNC_xvp_button') .classList.add("noVNC_hidden"); // Close XVP panel if open if (UI.xvpOpen === true) { @@ -712,13 +712,13 @@ var UI; document.getElementById('noVNC_clipboard') .classList.remove("noVNC_open"); document.getElementById('noVNC_clipboard_button') - .className = "noVNC_status_button"; + .className = "noVNC_button"; UI.clipboardOpen = false; } else { document.getElementById('noVNC_clipboard') .classList.add("noVNC_open"); document.getElementById('noVNC_clipboard_button') - .className = "noVNC_status_button_selected"; + .className = "noVNC_button_selected"; UI.clipboardOpen = true; } }, @@ -753,7 +753,8 @@ var UI; if (UI.settingsOpen === true) { UI.settingsApply(); UI.closeSettingsMenu(); - document.getElementById('noVNC_connectPanel_button').className = "noVNC_status_button"; + document.getElementById('noVNC_connect_controls_button') + .className = "noVNC_button"; } // Close clipboard panel if open if (UI.clipboardOpen === true) { @@ -766,20 +767,20 @@ var UI; // Toggle Connection Panel if (UI.connSettingsOpen === true) { - document.getElementById('noVNC_controls') + document.getElementById('noVNC_connect_controls') .classList.remove("noVNC_open"); - document.getElementById('noVNC_connectPanel_button') - .className = "noVNC_status_button"; + document.getElementById('noVNC_connect_controls_button') + .className = "noVNC_button"; UI.connSettingsOpen = false; UI.saveSetting('host'); UI.saveSetting('port'); UI.saveSetting('token'); //UI.saveSetting('password'); } else { - document.getElementById('noVNC_controls') + document.getElementById('noVNC_connect_controls') .classList.add("noVNC_open"); - document.getElementById('noVNC_connectPanel_button') - .className = "noVNC_status_button_selected"; + document.getElementById('noVNC_connect_controls_button') + .className = "noVNC_button_selected"; UI.connSettingsOpen = true; document.getElementById('noVNC_setting_host').focus(); } @@ -879,9 +880,11 @@ var UI; document.mozFullScreenElement || // currently working methods document.webkitFullscreenElement || document.msFullscreenElement ) { - document.getElementById('noVNC_fullscreen_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_fullscreen_button') + .className = "noVNC_button_selected"; } else { - document.getElementById('noVNC_fullscreen_button').className = "noVNC_status_button"; + document.getElementById('noVNC_fullscreen_button') + .className = "noVNC_button"; } }, @@ -1103,9 +1106,9 @@ var UI; } if (UI.rfb.get_viewportDrag()) { - viewDragButton.className = "noVNC_status_button_selected"; + viewDragButton.className = "noVNC_button_selected"; } else { - viewDragButton.className = "noVNC_status_button"; + viewDragButton.className = "noVNC_button"; } // Different behaviour for touch vs non-touch @@ -1146,16 +1149,17 @@ var UI; try { kbi.setSelectionRange(l, l); } // Move the caret to the end catch (err) {} // setSelectionRange is undefined in Google Chrome UI.keyboardVisible = true; - skb.className = "noVNC_status_button_selected"; + skb.className = "noVNC_button_selected"; } else if(UI.keyboardVisible === true) { kbi.blur(); - skb.className = "noVNC_status_button"; + skb.className = "noVNC_button"; UI.keyboardVisible = false; } }, hideKeyboard: function() { - document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_keyboard_button') + .className = "noVNC_button"; //Weird bug in iOS if you change keyboardVisible //here it does not actually occur so next time //you click keyboard icon it doesnt work. @@ -1168,10 +1172,12 @@ var UI; clearTimeout(UI.hideKeyboardTimeout); if(UI.keyboardVisible === true) { document.getElementById('noVNC_keyboardinput').focus(); - document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_keyboard_button') + .className = "noVNC_button_selected"; } else if(UI.keyboardVisible === false) { document.getElementById('noVNC_keyboardinput').blur(); - document.getElementById('noVNC_keyboard_button').className = "noVNC_status_button"; + document.getElementById('noVNC_keyboard_button') + .className = "noVNC_button"; } }, @@ -1257,14 +1263,14 @@ var UI; if(UI.extraKeysVisible === false) { document.getElementById('noVNC_modifiers') .classList.add("noVNC_open"); - document.getElementById('noVNC_toggleExtraKeys_button') - .className = "noVNC_status_button_selected"; + document.getElementById('noVNC_toggle_extra_keys_button') + .className = "noVNC_button_selected"; UI.extraKeysVisible = true; } else if(UI.extraKeysVisible === true) { document.getElementById('noVNC_modifiers') .classList.remove("noVNC_open"); - document.getElementById('noVNC_toggleExtraKeys_button') - .className = "noVNC_status_button"; + document.getElementById('noVNC_toggle_extra_keys_button') + .className = "noVNC_button"; UI.extraKeysVisible = false; } }, @@ -1283,11 +1289,13 @@ var UI; UI.keepKeyboard(); if(UI.ctrlOn === false) { UI.rfb.sendKey(KeyTable.XK_Control_L, true); - document.getElementById('noVNC_toggleCtrl_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_toggle_ctrl_button') + .className = "noVNC_button_selected"; UI.ctrlOn = true; } else if(UI.ctrlOn === true) { UI.rfb.sendKey(KeyTable.XK_Control_L, false); - document.getElementById('noVNC_toggleCtrl_button').className = "noVNC_status_button"; + document.getElementById('noVNC_toggle_ctrl_button') + .className = "noVNC_button"; UI.ctrlOn = false; } }, @@ -1296,11 +1304,13 @@ var UI; UI.keepKeyboard(); if(UI.altOn === false) { UI.rfb.sendKey(KeyTable.XK_Alt_L, true); - document.getElementById('noVNC_toggleAlt_button').className = "noVNC_status_button_selected"; + document.getElementById('noVNC_toggle_alt_button') + .className = "noVNC_button_selected"; UI.altOn = true; } else if(UI.altOn === true) { UI.rfb.sendKey(KeyTable.XK_Alt_L, false); - document.getElementById('noVNC_toggleAlt_button').className = "noVNC_status_button"; + document.getElementById('noVNC_toggle_alt_button') + .className = "noVNC_button"; UI.altOn = false; } }, diff --git a/vnc.html b/vnc.html index b4d0a373..9d9fcaf3 100644 --- a/vnc.html +++ b/vnc.html @@ -56,21 +56,21 @@
    + id="noVNC_mouse_button0" class="noVNC_button" /> + id="noVNC_mouse_button1" class="noVNC_button" /> + id="noVNC_mouse_button2" class="noVNC_button" /> + id="noVNC_mouse_button4" class="noVNC_button" />
    - - - + + +
    -
    - - - -
    @@ -98,12 +98,12 @@
    - -
    @@ -113,7 +113,7 @@
    -
    @@ -125,12 +125,12 @@
    - -
    @@ -170,10 +170,10 @@
    - -
    From b0c6d3c6aa15e90642048c2f789c5e19bfbb7a63 Mon Sep 17 00:00:00 2001 From: samhed Date: Thu, 25 Aug 2016 16:55:55 +0200 Subject: [PATCH 23/46] Remove redundant modifier state variables --- app/ui.js | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/app/ui.js b/app/ui.js index 234af0aa..21f28cbb 100644 --- a/app/ui.js +++ b/app/ui.js @@ -50,9 +50,6 @@ var UI; lastKeyboardinput: null, defaultKeyboardinputLen: 100, - ctrlOn: false, - altOn: false, - // Setup rfb object, load settings from browser storage, then call // UI.init to setup the UI/menus load: function(callback) { @@ -1280,31 +1277,25 @@ var UI; toggleCtrl: function() { UI.keepKeyboard(); - if(UI.ctrlOn === false) { - UI.rfb.sendKey(KeyTable.XK_Control_L, true); - document.getElementById('noVNC_toggle_ctrl_button') - .classList.add("noVNC_selected"); - UI.ctrlOn = true; - } else if(UI.ctrlOn === true) { + var btn = document.getElementById('noVNC_toggle_ctrl_button'); + if (btn.classList.contains("noVNC_selected")) { UI.rfb.sendKey(KeyTable.XK_Control_L, false); - document.getElementById('noVNC_toggle_ctrl_button') - .classList.remove("noVNC_selected"); - UI.ctrlOn = false; + btn.classList.remove("noVNC_selected"); + } else { + UI.rfb.sendKey(KeyTable.XK_Control_L, true); + btn.classList.add("noVNC_selected"); } }, toggleAlt: function() { UI.keepKeyboard(); - if(UI.altOn === false) { - UI.rfb.sendKey(KeyTable.XK_Alt_L, true); - document.getElementById('noVNC_toggle_alt_button') - .classList.add("noVNC_selected"); - UI.altOn = true; - } else if(UI.altOn === true) { + var btn = document.getElementById('noVNC_toggle_alt_button'); + if (btn.classList.contains("noVNC_selected")) { UI.rfb.sendKey(KeyTable.XK_Alt_L, false); - document.getElementById('noVNC_toggle_alt_button') - .classList.remove("noVNC_selected"); - UI.altOn = false; + btn.classList.remove("noVNC_selected"); + } else { + UI.rfb.sendKey(KeyTable.XK_Alt_L, true); + btn.classList.add("noVNC_selected"); } }, From 24d8b311ca3442b26dd0f0e0fce8dd0ba4763e81 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 20:11:11 +0200 Subject: [PATCH 24/46] Bling up popups Make the popups a bit more prominent by adding shadows and animations. --- app/styles/base.css | 68 +++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index e838b1de..c0d7fceb 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -88,33 +88,30 @@ html { /* Panels */ .noVNC_panel { - display: none; - position: relative; + position: fixed; + top: 46px; + right: 15px; + transform: translate(0, -50px); + + transition: 0.5s ease-in-out; + + visibility: hidden; + opacity: 0; + padding: 15px; - color: #fff; - background: #fff; /* default background for browsers without gradient support */ - /* css3 */ - /*background: -webkit-gradient(linear, 0 0, 0 100%, from(#2e88c4), to(#075698)); - background: -moz-linear-gradient(#2e88c4, #075698); - background: -o-linear-gradient(#2e88c4, #075698); - background: linear-gradient(#2e88c4, #075698);*/ + + background: #fff; -webkit-border-radius: 10px; -moz-border-radius: 10px; border-radius: 10px; color: #000; border: 2px solid #E0E0E0; -} -.noVNC_panel:after { - content: ""; - position: absolute; - top: -40px; /* value = - border-top-width - border-bottom-width */ - right: 50px; /* controls horizontal position */ - border-style: solid; - border-width: 40px 40px 0 0; /* vary these values to change the angle of the vertex */ - border-color: transparent #E0E0E0; + box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); } .noVNC_panel.noVNC_open { - display: block; + visibility: visible; + opacity: 1; + transform: translate(0, 0); } /* noVNC Touch Device only buttons */ @@ -186,12 +183,6 @@ html { /* XVP Shutdown/Reboot */ #noVNC_xvp { - top: 73px; - right: 30px; - position: fixed; -} -#noVNC_xvp:after { - right: 125px; } #noVNC_xvp_buttons { display: none; @@ -199,12 +190,6 @@ html { /* Clipboard */ #noVNC_clipboard { - top: 73px; - right: 30px; - position: fixed; -} -#noVNC_clipboard:after { - right: 85px; } #noVNC_clipboard_text { width: 500px; @@ -215,9 +200,6 @@ html { /* Settings */ #noVNC_settings { - top: 73px; - right: 20px; - position: fixed; } #noVNC_settings ul { list-style: none; @@ -233,12 +215,6 @@ html { /* Connection Controls */ #noVNC_connect_controls { - top: 73px; - right: 12px; - position: fixed; -} -#noVNC_connect_controls:after { - right:15px; } #noVNC_connect_controls ul { list-style: none; @@ -268,15 +244,21 @@ html { */ #noVNC_status { - display: none; position: fixed; top: 0; left: 0; width: 100%; z-index: 3; + transform: translateY(-100%); + + transition: 0.5s ease-in-out; + + visibility: hidden; + opacity: 0; padding: 5px; + display: flex; flex-direction: row; justify-content: center; align-content: center; @@ -288,7 +270,9 @@ html { border-bottom: 1px solid rgba(0, 0, 0, 0.9); } #noVNC_status.noVNC_open { - display: flex; + transform: translateY(0); + visibility: visible; + opacity: 1; } #noVNC_status::before { From 79fd3b1fcff7204b836928e64a9f634fe5e179ec Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 30 Aug 2016 15:23:20 +0200 Subject: [PATCH 25/46] Apply CSS style to input elements Different browsers have wildly different defaults for input elements. Try to get a consistent interface by applying our own style. --- app/styles/base.css | 85 +++++++++++++++++++++++++++++++++++++++------ vnc.html | 6 ++-- 2 files changed, 78 insertions(+), 13 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index c0d7fceb..81c45169 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -26,6 +26,77 @@ html { white-space: nowrap; } +/* ---------------------------------------- + * Input Elements + * ---------------------------------------- + */ + +input[type=input], input[type=password], input:not([type]), textarea { + /* Disable default rendering */ + -webkit-appearance: none; + -moz-appearance: none; + background: none; + + margin: 2px; + padding: 2px; + border: 1px solid rgb(192, 192, 192); + border-radius: 5px; + color: black; + background: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240)); +} + +input[type=button], select { + /* Disable default rendering */ + -webkit-appearance: none; + -moz-appearance: none; + background: none; + + margin: 2px; + padding: 2px; + border: 1px solid rgb(192, 192, 192); + border-bottom-width: 2px; + border-radius: 5px; + color: black; + background: linear-gradient(to top, rgb(255, 255, 255), rgb(240, 240, 240)); + + /* This avoids it jumping around when :active */ + vertical-align: middle; +} + +input[type=button] { + padding-left: 20px; + padding-right: 20px; +} + +option { + color: black; + background: white; +} + +input[type=input]:focus, input[type=password]:focus, +input:not([type]):focus, input[type=button]:focus, +textarea:focus, select: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 { + border: none; +} + +input[type=input]:disabled, input[type=password]:disabled, +input:not([type]):disabled, input[type=button]:disabled, +textarea:disabled, select:disabled { + color: rgb(128, 128, 128); + background: rgb(240, 240, 240); +} + +input[type=button]:active, select:active { + border-bottom-width: 1px; + margin-top: 3px; +} + /* ---------------------------------------- * Control Bar * ---------------------------------------- @@ -114,6 +185,10 @@ html { transform: translate(0, 0); } +.noVNC_submit { + float: right; +} + /* noVNC Touch Device only buttons */ #noVNC_mobile_buttons { display: inline; @@ -194,9 +269,6 @@ html { #noVNC_clipboard_text { width: 500px; } -#noVNC_clipboard_clear_button { - float: right; -} /* Settings */ #noVNC_settings { @@ -209,9 +281,6 @@ html { #noVNC_setting_path { width: 100px; } -#noVNC_settings_apply { - float: right; -} /* Connection Controls */ #noVNC_connect_controls { @@ -233,10 +302,6 @@ html { #noVNC_setting_password { width: 150px; } -#noVNC_connect_button { - width: 110px; - float: right; -} /* ---------------------------------------- * Status Dialog diff --git a/vnc.html b/vnc.html index b5bd2822..6c2b9d65 100644 --- a/vnc.html +++ b/vnc.html @@ -121,7 +121,7 @@
    + value="Clear" class="noVNC_submit" />
    @@ -165,7 +165,7 @@
    -
  • +
@@ -182,7 +182,7 @@
  • -
  • +
  • From c8d4402f582e4d4fb62ca75aae3241f9e0917190 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 20:45:52 +0200 Subject: [PATCH 26/46] Move touch text input out of control bar It has nothing to do with the control bar, so hide it somewhere more sensible. --- vnc.html | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/vnc.html b/vnc.html index 6c2b9d65..a660988b 100644 --- a/vnc.html +++ b/vnc.html @@ -72,13 +72,6 @@ - -
    @@ -197,6 +190,14 @@
    + + + Canvas not supported. From 8d7708c82edc9c0d3dc22a28ded5a563ce786bb2 Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Mon, 29 Aug 2016 14:42:03 +0200 Subject: [PATCH 27/46] Abstract status dialog CSS class handling --- app/ui.js | 85 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/app/ui.js b/app/ui.js index 21f28cbb..9689852a 100644 --- a/app/ui.js +++ b/app/ui.js @@ -308,43 +308,33 @@ var UI; updateState: function(rfb, state, oldstate, msg) { UI.rfb_state = state; - var klass; - var timeout; - switch (state) { - case 'failed': - case 'fatal': - klass = "noVNC_status_error"; - timeout = 0; // zero means no timeout - break; - case 'normal': - klass = "noVNC_status_normal"; - break; - case 'disconnected': - /* falls through */ - case 'loaded': - klass = "noVNC_status_normal"; - break; - case 'password': - UI.toggleConnectPanel(); - - document.getElementById('noVNC_connect_button').value = "Send Password"; - document.getElementById('noVNC_connect_button').onclick = UI.setPassword; - document.getElementById('noVNC_setting_password').focus(); - - klass = "noVNC_status_warn"; - break; - default: - klass = "noVNC_status_warn"; - break; - } if (typeof(msg) !== 'undefined') { - document.getElementById('noVNC_status') - .classList.remove("noVNC_status_normal", - "noVNC_status_warn", - "noVNC_status_error"); - document.getElementById('noVNC_status').classList.add(klass); - UI.showStatus(msg, timeout); + switch (state) { + case 'failed': + case 'fatal': + // zero means no timeout + UI.showStatus(msg, 'error', 0); + break; + case 'normal': + /* falls through */ + case 'disconnected': + case 'loaded': + UI.showStatus(msg, 'normal'); + break; + case 'password': + UI.toggleConnectPanel(); + + document.getElementById('noVNC_connect_button').value = "Send Password"; + document.getElementById('noVNC_connect_button').onclick = UI.setPassword; + document.getElementById('noVNC_setting_password').focus(); + + UI.showStatus(msg, 'warn'); + break; + default: + UI.showStatus(msg, 'warn'); + break; + } } UI.updateVisualState(); @@ -434,11 +424,34 @@ var UI; //Util.Debug("<< updateVisualState"); }, - showStatus: function(text, time) { + showStatus: function(text, status_type, time) { var statusElem = document.getElementById('noVNC_status'); clearTimeout(UI.statusTimeout); + if (typeof status_type === 'undefined') { + status_type = 'normal'; + } + + statusElem.classList.remove("noVNC_status_normal", + "noVNC_status_warn", + "noVNC_status_error"); + + switch (status_type) { + case 'warning': + case 'warn': + statusElem.classList.add("noVNC_status_warn"); + break; + case 'error': + statusElem.classList.add("noVNC_status_error"); + break; + case 'normal': + case 'info': + default: + statusElem.classList.add("noVNC_status_normal"); + break; + } + statusElem.innerHTML = text; statusElem.classList.add("noVNC_open"); From 8a7ec6ea1919741035e35d111a5680eb396a0bdc Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Mon, 29 Aug 2016 14:46:58 +0200 Subject: [PATCH 28/46] Add a separate dialog for the password prompt The user might be queried for the password during the connect stage if no password was previously provided. Add a separate dialog for this rather than abusing the connect dialog. --- app/styles/base.css | 49 +++++++++++++++++++++++++++++++++++++++++++++ app/ui.js | 26 ++++++++++++++---------- vnc.html | 10 +++++++++ 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 81c45169..96f830bb 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -97,6 +97,32 @@ input[type=button]:active, select:active { margin-top: 3px; } +/* ---------------------------------------- + * WebKit centering hacks + * ---------------------------------------- + */ + +.noVNC_center { + /* + * This is a workaround because webkit misrenders transforms and + * uses non-integer coordinates, resulting in blurry content. + * Ideally we'd use "top: 50%; transform: translateY(-50%);" on + * the objects instead. + */ + display: flex; + align-items: center; + justify-content: center; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; +} +.noVNC_center > * { + pointer-events: auto; +} + /* ---------------------------------------- * Control Bar * ---------------------------------------- @@ -367,6 +393,29 @@ input[type=button]:active, select:active { content: url("../images/warning.svg") " "; } +/* ---------------------------------------- + * Password Dialog + * ---------------------------------------- + */ + +#noVNC_password_dlg { + transform: translateY(-50px); +} +#noVNC_password_dlg.noVNC_open { + transform: translateY(0); +} +#noVNC_password_dlg ul { + list-style: none; + margin: 0px; + padding: 0px; +} +#noVNC_password_dlg li { + padding-bottom:8px; +} +#noVNC_password_input { + width: 150px; +} + /* ---------------------------------------- * Main Area * ---------------------------------------- diff --git a/app/ui.js b/app/ui.js index 9689852a..33e0e997 100644 --- a/app/ui.js +++ b/app/ui.js @@ -249,6 +249,9 @@ var UI; .addEventListener('click', UI.disconnect); document.getElementById("noVNC_connect_button") .addEventListener('click', UI.connect); + + document.getElementById("noVNC_password_button") + .addEventListener('click', UI.setPassword); }, addClipboardHandlers: function() { @@ -323,11 +326,11 @@ var UI; UI.showStatus(msg, 'normal'); break; case 'password': - UI.toggleConnectPanel(); - - document.getElementById('noVNC_connect_button').value = "Send Password"; - document.getElementById('noVNC_connect_button').onclick = UI.setPassword; - document.getElementById('noVNC_setting_password').focus(); + document.getElementById('noVNC_password_dlg') + .classList.add('noVNC_open'); + setTimeout(function () { + document.getElementById(('noVNC_password_input').focus()); + }, 100); UI.showStatus(msg, 'warn'); break; @@ -397,6 +400,10 @@ var UI; // It is enabled (toggled) by direct click on the button UI.setViewDrag(false); + // State change also closes the password dialog + document.getElementById('noVNC_password_dlg') + .classList.remove('noVNC_open'); + switch (UI.rfb_state) { case 'fatal': case 'failed': @@ -827,12 +834,9 @@ var UI; }, setPassword: function() { - UI.rfb.sendPassword(document.getElementById('noVNC_setting_password').value); - //Reset connect button. - document.getElementById('noVNC_connect_button').value = "Connect"; - document.getElementById('noVNC_connect_button').onclick = UI.connect; - //Hide connection panel. - UI.toggleConnectPanel(); + UI.rfb.sendPassword(document.getElementById('noVNC_password_input').value); + document.getElementById('noVNC_password_dlg') + .classList.remove('noVNC_open'); return false; }, diff --git a/vnc.html b/vnc.html index a660988b..9c677eec 100644 --- a/vnc.html +++ b/vnc.html @@ -185,6 +185,16 @@
    + +
    +
    +
      +
    • +
    • +
    +
    +
    +

    no
    VNC

    From d616c9226cb06b82e68d1d8cbedcb7ea41b0fe2c Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 20:49:52 +0200 Subject: [PATCH 29/46] Merge control bar sections There is no status information in the centre anymore, so merge the left and right sections of the control bar. --- app/styles/base.css | 15 +++------------ vnc.html | 4 +--- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 96f830bb..3edd2adc 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -265,21 +265,12 @@ input[type=button]:active, select:active { display: inline; } -/* Left side buttons */ -.noVNC_buttons_left { - float: left; +.noVNC_buttons { + float: right; z-index: 1; position: relative; - padding-left: 10px; -} - -/* Right side buttons */ -.noVNC_buttons_right { - float: right; - right: 0px; - z-index: 2; - position: absolute; padding-right: 10px; + padding-left: 10px; } /* XVP Shutdown/Reboot */ diff --git a/vnc.html b/vnc.html index 9c677eec..f20b00c3 100644 --- a/vnc.html +++ b/vnc.html @@ -52,7 +52,7 @@
    -
    +
    -
    -
    Date: Thu, 25 Aug 2016 20:52:46 +0200 Subject: [PATCH 30/46] Enable extra keys for all devices Manual special keys can be useful on all devices, so stop restricting it to just touch devices. --- app/ui.js | 3 +++ vnc.html | 28 +++++++++++++++------------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/app/ui.js b/app/ui.js index 33e0e997..4b34e243 100644 --- a/app/ui.js +++ b/app/ui.js @@ -84,6 +84,7 @@ var UI; UI.setupFullscreen(); UI.addControlbarHandlers(); UI.addTouchSpecificHandlers(); + UI.addExtraKeysHandlers(); UI.addXvpHandlers(); UI.addConnectionControlHandlers(); UI.addClipboardHandlers(); @@ -218,7 +219,9 @@ var UI; .addEventListener('submit', function () { return false; }); window.addEventListener('load', UI.keyboardinputReset); + }, + addExtraKeysHandlers: function() { document.getElementById("noVNC_toggle_extra_keys_button") .addEventListener('click', UI.toggleExtraKeys); document.getElementById("noVNC_toggle_ctrl_button") diff --git a/vnc.html b/vnc.html index f20b00c3..8676e83d 100644 --- a/vnc.html +++ b/vnc.html @@ -72,19 +72,21 @@ -
    - -
    - - - - -
    +
    + + +
    + +
    + + + +
    From f7c725cecfd591b7f221863da74a9965fa297504 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 25 Aug 2016 21:02:49 +0200 Subject: [PATCH 31/46] Improve active button visual response --- app/styles/base.css | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/styles/base.css b/app/styles/base.css index 3edd2adc..a462eae6 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -179,6 +179,13 @@ input[type=button]:active, select:active { .noVNC_button:disabled { opacity: 0.4; } +.noVNC_button:focus { + outline: none; +} +.noVNC_button:active { + padding-top: 5px; + padding-bottom: 3px; +} .noVNC_button.noVNC_hidden { display: none; } From 8434cc81b39fb6a64854d8844798e6307995e735 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 10:46:20 +0200 Subject: [PATCH 32/46] Make status dialog independent of control bar --- vnc.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vnc.html b/vnc.html index 8676e83d..9a6aa29b 100644 --- a/vnc.html +++ b/vnc.html @@ -180,11 +180,11 @@
    - -
    -
    + +
    +
    From 6244e383e49855772713df97e0bad1560b0424f7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 14 Sep 2016 16:10:24 +0200 Subject: [PATCH 33/46] Let CSS update UI for touch and connected state Avoid a lot of JavaScript code that can easily be handed using style sheets instead, specifically items that should only be shown when on a touch device, or items that depend on the connected state. --- app/styles/base.css | 32 +++++++++++-- app/ui.js | 112 +++++++++++++------------------------------- vnc.html | 4 +- 3 files changed, 62 insertions(+), 86 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index a462eae6..ed77c6b9 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -222,11 +222,18 @@ input[type=button]:active, select:active { float: right; } +:root:not(.noVNC_connected) #noVNC_view_drag_button { + display: none; +} + /* noVNC Touch Device only buttons */ #noVNC_mobile_buttons { display: inline; } -#noVNC_mobile_buttons.noVNC_hidden { +:root:not(.noVNC_connected) #noVNC_mobile_buttons { + display: none; +} +:root:not(.noVNC_touch) #noVNC_mobile_buttons { display: none; } @@ -242,7 +249,7 @@ input[type=button]:active, select:active { ime-mode: disabled; } -#noVNC_toggle_extra_keys_button { +:root:not(.noVNC_connected) #noVNC_extra_keys { display: none; } @@ -280,7 +287,15 @@ input[type=button]:active, select:active { padding-left: 10px; } +/* Send Ctrl+Alt+Delete */ +:root:not(.noVNC_connected) #noVNC_send_ctrl_alt_del_button { + display: none; +} + /* XVP Shutdown/Reboot */ +:root:not(.noVNC_connected) #noVNC_xvp_button { + display: none; +} #noVNC_xvp { } #noVNC_xvp_buttons { @@ -288,6 +303,9 @@ input[type=button]:active, select:active { } /* Clipboard */ +:root:not(.noVNC_connected) #noVNC_clipboard_button { + display: none; +} #noVNC_clipboard { } #noVNC_clipboard_text { @@ -307,7 +325,11 @@ input[type=button]:active, select:active { } /* Connection Controls */ -#noVNC_connect_controls { +:root.noVNC_connected #noVNC_connect_controls_button { + display: none; +} +:root:not(.noVNC_connected) #noVNC_disconnect_button { + display: none; } #noVNC_connect_controls ul { list-style: none; @@ -440,7 +462,7 @@ input[type=button]:active, select:active { width: auto; height: auto; } -#noVNC_screen.noVNC_hidden { +:root:not(.noVNC_connected) #noVNC_screen { display: none; } @@ -480,7 +502,7 @@ input[type=button]:active, select:active { -1px 1px 0 #000, 1px 1px 0 #000; } -#noVNC_logo.noVNC_hidden { +:root.noVNC_connected #noVNC_logo { display: none; } diff --git a/app/ui.js b/app/ui.js index 4b34e243..6c09e150 100644 --- a/app/ui.js +++ b/app/ui.js @@ -66,12 +66,9 @@ var UI; UI.initSettings(); - // Show mouse selector buttons on touch screen devices + // Adapt the interface for touch screen devices if (UI.isTouchDevice) { - // Show mobile buttons - document.getElementById('noVNC_mobile_buttons') - .classList.remove("noVNC_hidden"); - UI.hideMouseButton(); + document.documentElement.classList.add("noVNC_touch"); // Remove the address bar setTimeout(function() { window.scrollTo(0, 1); }, 100); UI.forceSetting('clip', true); @@ -368,34 +365,11 @@ var UI; document.getElementById('noVNC_setting_repeaterID').disabled = connected; if (connected) { - document.getElementById('noVNC_logo') - .classList.add("noVNC_hidden"); - document.getElementById('noVNC_screen') - .classList.remove("noVNC_hidden"); + document.documentElement.classList.add("noVNC_connected"); UI.updateViewClip(); UI.setMouseButton(1); - document.getElementById('noVNC_clipboard_button') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_keyboard_button') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_extra_keys') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_send_ctrl_alt_del_button') - .classList.remove("noVNC_hidden"); } else { - document.getElementById('noVNC_logo') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_screen') - .classList.add("noVNC_hidden"); - UI.hideMouseButton(); - document.getElementById('noVNC_clipboard_button') - .classList.add("noVNC_hidden"); - document.getElementById('noVNC_keyboard_button') - .classList.add("noVNC_hidden"); - document.getElementById('noVNC_extra_keys') - .classList.add("noVNC_hidden"); - document.getElementById('noVNC_send_ctrl_alt_del_button') - .classList.add("noVNC_hidden"); + document.documentElement.classList.remove("noVNC_connected"); UI.updateXvpButton(0); } @@ -411,23 +385,11 @@ var UI; case 'fatal': case 'failed': case 'disconnected': - document.getElementById('noVNC_connect_controls_button') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_disconnect_button') - .classList.add("noVNC_hidden"); UI.openConnectPanel(); break; case 'loaded': - document.getElementById('noVNC_connect_controls_button') - .classList.remove("noVNC_hidden"); - document.getElementById('noVNC_disconnect_button') - .classList.add("noVNC_hidden"); break; default: - document.getElementById('noVNC_connect_controls_button') - .classList.add("noVNC_hidden"); - document.getElementById('noVNC_disconnect_button') - .classList.remove("noVNC_hidden"); break; } @@ -1086,52 +1048,48 @@ var UI; updateViewDrag: function() { var clipping = false; + if (UI.rfb_state !== 'normal') return; + // Check if viewport drag is possible. It is only possible // if the remote display is clipping the client display. - if (UI.rfb_state === 'normal' && - UI.rfb.get_display().get_viewport() && + if (UI.rfb.get_display().get_viewport() && UI.rfb.get_display().clippingDisplay()) { clipping = true; } var viewDragButton = document.getElementById('noVNC_view_drag_button'); - if (UI.rfb_state !== 'normal') { - // Always hide when not connected - viewDragButton.classList.add("noVNC_hidden"); + if (!clipping && + UI.rfb.get_viewportDrag()) { + // The size of the remote display is the same or smaller + // than the client display. Make sure viewport drag isn't + // active when it can't be used. + UI.rfb.set_viewportDrag(false); + } + + if (UI.rfb.get_viewportDrag()) { + viewDragButton.classList.add("noVNC_selected"); } else { - if (!clipping && - UI.rfb.get_viewportDrag()) { - // The size of the remote display is the same or smaller - // than the client display. Make sure viewport drag isn't - // active when it can't be used. - UI.rfb.set_viewportDrag(false); - } + viewDragButton.classList.remove("noVNC_selected"); + } - if (UI.rfb.get_viewportDrag()) { - viewDragButton.classList.add("noVNC_selected"); - } else { - viewDragButton.classList.remove("noVNC_selected"); - } + // Different behaviour for touch vs non-touch + // The button is disabled instead of hidden on touch devices + if (UI.isTouchDevice) { + viewDragButton.classList.remove("noVNC_hidden"); - // Different behaviour for touch vs non-touch - // The button is disabled instead of hidden on touch devices - if (UI.isTouchDevice) { - viewDragButton.classList.remove("noVNC_hidden"); - - if (clipping) { - viewDragButton.disabled = false; - } else { - viewDragButton.disabled = true; - } - } else { + if (clipping) { viewDragButton.disabled = false; + } else { + viewDragButton.disabled = true; + } + } else { + viewDragButton.disabled = false; - if (clipping) { - viewDragButton.classList.remove("noVNC_hidden"); - } else { - viewDragButton.classList.add("noVNC_hidden"); - } + if (clipping) { + viewDragButton.classList.remove("noVNC_hidden"); + } else { + viewDragButton.classList.add("noVNC_hidden"); } } }, @@ -1329,10 +1287,6 @@ var UI; * MISC * ------v------*/ - hideMouseButton: function() { - UI.setMouseButton(-1); - }, - setMouseButton: function(num) { if (UI.rfb) { UI.rfb.get_mouse().set_touchButton(num); diff --git a/vnc.html b/vnc.html index 9a6aa29b..8b68ff50 100644 --- a/vnc.html +++ b/vnc.html @@ -60,7 +60,7 @@ title="Move/Drag Viewport" /> -
    +
    no
    VNC -
    +
    -
    - -
    +
    +
    -
    +
    +
    +
    @@ -99,16 +100,19 @@ +
    +
    +
    @@ -116,6 +120,7 @@
    +
    +
    • Encrypt
    • @@ -161,6 +167,7 @@
    +
    +
    • @@ -178,7 +186,8 @@
    -
    +
    +
    From 4d3aa0ef9d3cc5baab835ad2b545cf80b77c7ae7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 12:24:57 +0200 Subject: [PATCH 35/46] Add logo to control bar --- app/styles/base.css | 20 ++++++++++++-------- vnc.html | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 3f6ccdf8..df10c7df 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -468,14 +468,22 @@ input[type=button]:active, select:active { url('Orbitron700.ttf') format('truetype'); } -#noVNC_logo { - margin-top: 60px; - margin-left: 60px; +.noVNC_logo { color:yellow; text-align:left; font-family: 'Orbitron', 'OrbitronTTF', sans-serif; - font-size: 180px; + font-size: 13px; line-height:90%; + text-shadow: 1px 1px 0 #000; +} +.noVNC_logo span{ + color:green; +} + +#noVNC_logo { + margin-top: 60px; + margin-left: 60px; + font-size: 180px; text-shadow: 5px 5px 0 #000, -1px -1px 0 #000, @@ -487,10 +495,6 @@ input[type=button]:active, select:active { display: none; } -#noVNC_logo span{ - color:green; -} - /* ---------------------------------------- * Media sizing * ---------------------------------------- diff --git a/vnc.html b/vnc.html index 4f6aa876..aeb63f8d 100644 --- a/vnc.html +++ b/vnc.html @@ -53,6 +53,8 @@
    +

    no
    VNC

    +
    -

    no
    VNC

    +

    no
    VNC

    From 728b5d9e1a32c16adef006fc25235bbb27d36172 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 12:37:09 +0200 Subject: [PATCH 36/46] Make control bar transparent when idle --- app/styles/base.css | 5 +++++ app/ui.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/app/styles/base.css b/app/styles/base.css index df10c7df..179a20b7 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -142,9 +142,14 @@ input[type=button]:active, select:active { position: fixed; z-index: 2; + transition: 0.5s ease-in-out; + /* Edge misrenders animations wihthout this */ transform: translateX(0); } +:root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle { + opacity: 0.8; +} #noVNC_control_bar { position: relative; diff --git a/app/ui.js b/app/ui.js index 27187fb1..6e2ff03f 100644 --- a/app/ui.js +++ b/app/ui.js @@ -41,6 +41,7 @@ var UI; resizeTimeout: null, statusTimeout: null, hideKeyboardTimeout: null, + controlbarTimeout: null, keyboardVisible: false, @@ -188,6 +189,15 @@ var UI; }, addControlbarHandlers: function() { + document.getElementById("noVNC_control_bar") + .addEventListener('mousemove', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mouseup', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mousedown', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('keypress', UI.activateControlbar); + document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); document.getElementById("noVNC_send_ctrl_alt_del_button") @@ -213,6 +223,15 @@ var UI; document.getElementById("noVNC_keyboardinput") .addEventListener('submit', function () { return false; }); + document.getElementById("noVNC_control_bar") + .addEventListener('touchstart', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchmove', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchend', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('input', UI.activateControlbar); + window.addEventListener('load', UI.keyboardinputReset); }, @@ -441,6 +460,20 @@ var UI; document.getElementById('noVNC_status').classList.remove("noVNC_open"); }, + activateControlbar: function() { + clearTimeout(UI.controlbarTimeout); + // We manipulate the anchor instead of the actual control + // bar in order to avoid creating new a stacking group + document.getElementById('noVNC_control_bar_anchor') + .classList.remove("noVNC_idle"); + UI.controlbarTimeout = window.setTimeout(UI.idleControlbar, 2000); + }, + + idleControlbar: function() { + document.getElementById('noVNC_control_bar_anchor') + .classList.add("noVNC_idle"); + }, + /* ------^------- * /VISUAL * ============== From 38323d4d92df7fd5f6e95a2adc2d7d91a32c9039 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 13:24:25 +0200 Subject: [PATCH 37/46] Add handle to open and close the control bar --- app/images/handle.svg | 82 +++++++++++++++++++ app/images/handle_bg.svg | 172 +++++++++++++++++++++++++++++++++++++++ app/styles/base.css | 43 +++++++++- app/styles/black.css | 2 +- app/styles/blue.css | 2 +- app/ui.js | 29 +++++++ vnc.html | 10 ++- 7 files changed, 333 insertions(+), 7 deletions(-) create mode 100644 app/images/handle.svg create mode 100644 app/images/handle_bg.svg diff --git a/app/images/handle.svg b/app/images/handle.svg new file mode 100644 index 00000000..4a7a126f --- /dev/null +++ b/app/images/handle.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/images/handle_bg.svg b/app/images/handle_bg.svg new file mode 100644 index 00000000..b4c4d131 --- /dev/null +++ b/app/images/handle_bg.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/styles/base.css b/app/styles/base.css index 179a20b7..ec682c46 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -153,18 +153,55 @@ input[type=button]:active, select:active { #noVNC_control_bar { position: relative; - left: -30px; + /* left: calc(-35px - 10px - 5px - 30px), but IE doesn't animate calc */ + left: -80px; + + transition: 0.5s ease-in-out; background-color: rgb(110, 132, 163); border-radius: 0 10px 10px 0; - box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); - /* The extra border is to get a proper shadow */ border-color: rgb(110, 132, 163); border-style: solid; border-width: 0 0 0 30px; } +#noVNC_control_bar.noVNC_open { + box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5); + left: -30px; +} + +#noVNC_control_bar_handle { + position: absolute; + right: -15px; + top: 10%; + width: 50px; + height: 50px; + z-index: -2; + cursor: pointer; + border-radius: 0 5px 5px 0; + background-color: rgb(83, 99, 122); + background-image: url("../images/handle_bg.svg"); + background-repeat: no-repeat; + background-position: right; + box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5); +} +#noVNC_control_bar_handle:after { + content: ""; + transition: 0.5s ease-in-out; + background: url("../images/handle.svg"); + position: absolute; + top: 22px; /* (50px-6px)/2 */ + right: 5px; + width: 5px; + height: 6px; +} +#noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after { + transform: translateX(1px) rotate(180deg); +} +:root:not(.noVNC_connected) #noVNC_control_bar_handle { + display: none; +} #noVNC_control_bar .noVNC_scroll { max-height: 100vh; /* Chrome is buggy with 100% */ diff --git a/app/styles/black.css b/app/styles/black.css index e3ad2493..d982a813 100644 --- a/app/styles/black.css +++ b/app/styles/black.css @@ -12,7 +12,7 @@ color:#fff; } -#noVNC_control_bar { +#noVNC_control_bar, #noVNC_control_bar_handle { background: #4c4c4c; } diff --git a/app/styles/blue.css b/app/styles/blue.css index 3db77270..e36e6d1d 100644 --- a/app/styles/blue.css +++ b/app/styles/blue.css @@ -12,6 +12,6 @@ color:#fff; } -#noVNC_control_bar { +#noVNC_control_bar, #noVNC_control_bar_handle { background: #080F80; } diff --git a/app/ui.js b/app/ui.js index 6e2ff03f..0c7cf1ec 100644 --- a/app/ui.js +++ b/app/ui.js @@ -198,6 +198,9 @@ var UI; document.getElementById("noVNC_control_bar") .addEventListener('keypress', UI.activateControlbar); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('click', UI.toggleControlbar); + document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); document.getElementById("noVNC_send_ctrl_alt_del_button") @@ -474,6 +477,26 @@ var UI; .classList.add("noVNC_idle"); }, + openControlbar: function() { + document.getElementById('noVNC_control_bar') + .classList.add("noVNC_open"); + }, + + closeControlbar: function() { + UI.closeAllPanels(); + document.getElementById('noVNC_control_bar') + .classList.remove("noVNC_open"); + }, + + toggleControlbar: function() { + if (document.getElementById('noVNC_control_bar') + .classList.contains("noVNC_open")) { + UI.closeControlbar(); + } else { + UI.openControlbar(); + } + }, + /* ------^------- * /VISUAL * ============== @@ -612,6 +635,7 @@ var UI; openSettingsPanel: function() { UI.closeAllPanels(); + UI.openControlbar(); UI.updateSetting('encrypt'); UI.updateSetting('true_color'); @@ -664,6 +688,7 @@ var UI; openXvpPanel: function() { UI.closeAllPanels(); + UI.openControlbar(); document.getElementById('noVNC_xvp') .classList.add("noVNC_open"); @@ -708,6 +733,7 @@ var UI; openClipboardPanel: function() { UI.closeAllPanels(); + UI.openControlbar(); document.getElementById('noVNC_clipboard') .classList.add("noVNC_open"); @@ -757,6 +783,7 @@ var UI; openConnectPanel: function() { UI.closeAllPanels(); + UI.openControlbar(); document.getElementById('noVNC_connect_controls') .classList.add("noVNC_open"); @@ -789,6 +816,7 @@ var UI; connect: function() { UI.closeAllPanels(); + UI.closeControlbar(); var host = document.getElementById('noVNC_setting_host').value; var port = document.getElementById('noVNC_setting_port').value; @@ -1250,6 +1278,7 @@ var UI; openExtraKeys: function() { UI.closeAllPanels(); + UI.openControlbar(); document.getElementById('noVNC_modifiers') .classList.add("noVNC_open"); diff --git a/vnc.html b/vnc.html index aeb63f8d..29d82521 100644 --- a/vnc.html +++ b/vnc.html @@ -52,7 +52,11 @@
    -
    +
    +
    + +
    +

    no
    VNC

    @@ -189,7 +193,9 @@
    -
    + +
    +
    From 65e3d7d6a66176c0edb0d298b905f25cf48cd1c2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 16:12:51 +0200 Subject: [PATCH 38/46] Make control bar handle easier to hit on mobile --- app/styles/base.css | 14 ++++++++++++++ vnc.html | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/styles/base.css b/app/styles/base.css index ec682c46..78f97dff 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -22,6 +22,10 @@ html { height:100%; } +.noVNC_only_touch.noVNC_hidden { + display: none; +} + /* ---------------------------------------- * Input Elements * ---------------------------------------- @@ -202,6 +206,16 @@ input[type=button]:active, select:active { :root:not(.noVNC_connected) #noVNC_control_bar_handle { display: none; } +#noVNC_control_bar_handle div { + position: absolute; + right: -35px; + top: 0; + width: 50px; + height: 50px; +} +:root:not(.noVNC_touch) #noVNC_control_bar_handle div { + display: none; +} #noVNC_control_bar .noVNC_scroll { max-height: 100vh; /* Chrome is buggy with 100% */ diff --git a/vnc.html b/vnc.html index 29d82521..5019bfd9 100644 --- a/vnc.html +++ b/vnc.html @@ -53,7 +53,7 @@
    -
    +
    From 04b399e27d3eaa9ba55d46c05c1d3760dc22d1e6 Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Wed, 14 Sep 2016 13:09:12 +0200 Subject: [PATCH 39/46] Allow moving the controlbar handle This also adds emulation of Element.setCapture() as only Firefox and Internet Explorer/Edge currently supports it. --- app/styles/base.css | 3 +- app/ui.js | 113 ++++++++++++++++++++++++++++++++++++++++++-- app/webutil.js | 93 ++++++++++++++++++++++++++++++++++++ core/util.js | 10 ++-- 4 files changed, 212 insertions(+), 7 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 78f97dff..8fbcb282 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -178,7 +178,8 @@ input[type=button]:active, select:active { #noVNC_control_bar_handle { position: absolute; right: -15px; - top: 10%; + top: 0; + transform: translateY(35px); width: 50px; height: 50px; z-index: -2; diff --git a/app/ui.js b/app/ui.js index 0c7cf1ec..cdf20a96 100644 --- a/app/ui.js +++ b/app/ui.js @@ -43,6 +43,10 @@ var UI; hideKeyboardTimeout: null, controlbarTimeout: null, + controlbarGrabbed: false, + controlbarDrag: false, + controlbarMouseDownClientY: 0, + controlbarMouseDownOffsetY: 0, keyboardVisible: false, isTouchDevice: false, @@ -198,13 +202,19 @@ var UI; document.getElementById("noVNC_control_bar") .addEventListener('keypress', UI.activateControlbar); - document.getElementById("noVNC_control_bar_handle") - .addEventListener('click', UI.toggleControlbar); - document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); document.getElementById("noVNC_send_ctrl_alt_del_button") .addEventListener('click', UI.sendCtrlAltDel); + + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mousedown', UI.controlbarHandleMouseDown); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mouseup', UI.controlbarHandleMouseUp); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('mousemove', UI.dragControlbarHandle); + // resize events aren't available for elements + window.addEventListener('resize', UI.updateControlbarHandle); }, addTouchSpecificHandlers: function() { @@ -235,6 +245,13 @@ var UI; document.getElementById("noVNC_control_bar") .addEventListener('input', UI.activateControlbar); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchstart', UI.controlbarHandleMouseDown); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchend', UI.controlbarHandleMouseUp); + document.getElementById("noVNC_control_bar_handle") + .addEventListener('touchmove', UI.dragControlbarHandle); + window.addEventListener('load', UI.keyboardinputReset); }, @@ -497,6 +514,96 @@ var UI; } }, + dragControlbarHandle: function (e) { + if (!UI.controlbarGrabbed) return; + + var ptr = Util.getPointerEvent(e); + + if (!UI.controlbarDrag) { + // The goal is to trigger on a certain physical width, the + // devicePixelRatio brings us a bit closer but is not optimal. + var dragThreshold = 10 * (window.devicePixelRatio || 1); + var dragDistance = Math.abs(ptr.clientY - UI.controlbarMouseDownClientY); + + if (dragDistance < dragThreshold) return; + + UI.controlbarDrag = true; + } + + var eventY = ptr.clientY - UI.controlbarMouseDownOffsetY; + + UI.moveControlbarHandle(eventY); + + e.preventDefault(); + e.stopPropagation(); + }, + + // Move the handle but don't allow any position outside the bounds + moveControlbarHandle: function (posY) { + var handle = document.getElementById("noVNC_control_bar_handle"); + var handleHeight = Util.getPosition(handle).height; + var controlbar = document.getElementById("noVNC_control_bar"); + var controlbarBounds = Util.getPosition(controlbar); + var controlbarTop = controlbarBounds.y; + var controlbarBottom = controlbarBounds.y + controlbarBounds.height; + var margin = 10; + + var viewportY = posY; + + // Refuse coordinates outside the control bar + if (viewportY < controlbarTop + margin) { + viewportY = controlbarTop + margin; + } else if (viewportY > controlbarBottom - handleHeight - margin) { + viewportY = controlbarBottom - handleHeight - margin; + } + + // Corner case: control bar too small for stable position + if (controlbarBounds.height < (handleHeight + margin * 2)) { + viewportY = controlbarTop + (controlbarBounds.height - handleHeight) / 2; + } + + var relativeY = viewportY - controlbarTop; + handle.style.transform = "translateY(" + relativeY + "px)"; + }, + + updateControlbarHandle: function () { + var handle = document.getElementById("noVNC_control_bar_handle"); + var pos = Util.getPosition(handle); + UI.moveControlbarHandle(pos.y); + }, + + controlbarHandleMouseUp: function(e) { + if ((e.type == "mouseup") && (e.button != 0)) + return; + + // mouseup and mousedown on the same place toggles the controlbar + if (UI.controlbarGrabbed && !UI.controlbarDrag) { + UI.toggleControlbar(); + e.preventDefault(); + e.stopPropagation(); + } + UI.controlbarGrabbed = false; + }, + + controlbarHandleMouseDown: function(e) { + if ((e.type == "mousedown") && (e.button != 0)) + return; + + var ptr = Util.getPointerEvent(e); + + var handle = document.getElementById("noVNC_control_bar_handle"); + var bounds = handle.getBoundingClientRect(); + + WebUtil.setCapture(handle); + UI.controlbarGrabbed = true; + UI.controlbarDrag = false; + + UI.controlbarMouseDownClientY = ptr.clientY; + UI.controlbarMouseDownOffsetY = ptr.clientY - bounds.top; + e.preventDefault(); + e.stopPropagation(); + }, + /* ------^------- * /VISUAL * ============== diff --git a/app/webutil.js b/app/webutil.js index 7f234dbf..38bb3967 100644 --- a/app/webutil.js +++ b/app/webutil.js @@ -278,6 +278,99 @@ WebUtil.injectParamIfMissing = function (path, param, value) { } }; +// Emulate Element.setCapture() when not supported + +WebUtil._captureRecursion = false; +WebUtil._captureProxy = function (e) { + // Recursion protection as we'll see our own event + if (WebUtil._captureRecursion) return; + + // Clone the event as we cannot dispatch an already dispatched event + var newEv = new e.constructor(e.type, e); + + WebUtil._captureRecursion = true; + WebUtil._captureElem.dispatchEvent(newEv); + WebUtil._captureRecursion = false; + + // Implicitly release the capture on button release + if ((e.type === "mouseup") || (e.type === "touchend")) { + WebUtil.releaseCapture(); + } +}; + +WebUtil.setCapture = function (elem) { + if (elem.setCapture) { + + elem.setCapture(); + + // IE releases capture on 'click' events which might not trigger + elem.addEventListener('mouseup', WebUtil.releaseCapture); + elem.addEventListener('touchend', WebUtil.releaseCapture); + + } else { + // Safari on iOS 9 has a broken constructor for TouchEvent. + // We are fine in this case however, since Safari seems to + // have some sort of implicit setCapture magic anyway. + if (window.TouchEvent !== undefined) { + try { + new TouchEvent("touchstart"); + } catch (TypeError) { + return; + } + } + + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + + if (captureElem === null) { + captureElem = document.createElement("div"); + captureElem.id = "noVNC_mouse_capture_elem"; + captureElem.style.position = "fixed"; + captureElem.style.top = "0px"; + captureElem.style.left = "0px"; + captureElem.style.width = "100%"; + captureElem.style.height = "100%"; + captureElem.style.zIndex = 10000; + captureElem.style.display = "none"; + document.body.appendChild(captureElem); + + captureElem.addEventListener('mousemove', WebUtil._captureProxy); + captureElem.addEventListener('mouseup', WebUtil._captureProxy); + + captureElem.addEventListener('touchmove', WebUtil._captureProxy); + captureElem.addEventListener('touchend', WebUtil._captureProxy); + } + + WebUtil._captureElem = elem; + captureElem.style.display = null; + + // We listen to events on window in order to keep tracking if it + // happens to leave the viewport + window.addEventListener('mousemove', WebUtil._captureProxy); + window.addEventListener('mouseup', WebUtil._captureProxy); + + window.addEventListener('touchmove', WebUtil._captureProxy); + window.addEventListener('touchend', WebUtil._captureProxy); + } +}; + +WebUtil.releaseCapture = function () { + if (document.releaseCapture) { + + document.releaseCapture(); + + } else { + var captureElem = document.getElementById("noVNC_mouse_capture_elem"); + WebUtil._captureElem = null; + captureElem.style.display = "none"; + + window.removeEventListener('mousemove', WebUtil._captureProxy); + window.removeEventListener('mouseup', WebUtil._captureProxy); + + window.removeEventListener('touchmove', WebUtil._captureProxy); + window.removeEventListener('touchend', WebUtil._captureProxy); + } +}; + // Dynamically load scripts without using document.write() // Reference: http://unixpapa.com/js/dyna.html // diff --git a/core/util.js b/core/util.js index d6a01932..3cc1e876 100644 --- a/core/util.js +++ b/core/util.js @@ -204,14 +204,18 @@ Util.getPosition = function(obj) { 'width': objPosition.width, 'height': objPosition.height}; }; +Util.getPointerEvent = function (e) { + var evt; + evt = (e ? e : window.event); + evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt); + return evt; +}; // Get mouse event position in DOM element Util.getEventPosition = function (e, obj, scale) { "use strict"; var evt, docX, docY, pos; - //if (!e) evt = window.event; - evt = (e ? e : window.event); - evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt); + evt = Util.getPointerEvent(e); if (evt.pageX || evt.pageY) { docX = evt.pageX; docY = evt.pageY; From 3f93a385a273299ec4662b89c8f99752d5e392f1 Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Wed, 31 Aug 2016 11:57:38 +0200 Subject: [PATCH 40/46] Auto-close the toolbar on connect after a delay --- app/ui.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/app/ui.js b/app/ui.js index cdf20a96..0ccffadc 100644 --- a/app/ui.js +++ b/app/ui.js @@ -41,7 +41,8 @@ var UI; resizeTimeout: null, statusTimeout: null, hideKeyboardTimeout: null, - controlbarTimeout: null, + idleControlbarTimeout: null, + closeControlbarTimeout: null, controlbarGrabbed: false, controlbarDrag: false, @@ -202,6 +203,11 @@ var UI; document.getElementById("noVNC_control_bar") .addEventListener('keypress', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('mousedown', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('keypress', UI.keepControlbar); + document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); document.getElementById("noVNC_send_ctrl_alt_del_button") @@ -245,6 +251,11 @@ var UI; document.getElementById("noVNC_control_bar") .addEventListener('input', UI.activateControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('touchstart', UI.keepControlbar); + document.getElementById("noVNC_control_bar") + .addEventListener('input', UI.keepControlbar); + document.getElementById("noVNC_control_bar_handle") .addEventListener('touchstart', UI.controlbarHandleMouseDown); document.getElementById("noVNC_control_bar_handle") @@ -405,6 +416,9 @@ var UI; document.documentElement.classList.add("noVNC_connected"); UI.updateViewClip(); UI.setMouseButton(1); + + // Hide the controlbar after 2 seconds + UI.closeControlbarTimeout = setTimeout(UI.closeControlbar, 2000); } else { document.documentElement.classList.remove("noVNC_connected"); UI.updateXvpButton(0); @@ -480,13 +494,13 @@ var UI; document.getElementById('noVNC_status').classList.remove("noVNC_open"); }, - activateControlbar: function() { - clearTimeout(UI.controlbarTimeout); + activateControlbar: function(event) { + clearTimeout(UI.idleControlbarTimeout); // We manipulate the anchor instead of the actual control // bar in order to avoid creating new a stacking group document.getElementById('noVNC_control_bar_anchor') .classList.remove("noVNC_idle"); - UI.controlbarTimeout = window.setTimeout(UI.idleControlbar, 2000); + UI.idleControlbarTimeout = window.setTimeout(UI.idleControlbar, 2000); }, idleControlbar: function() { @@ -494,6 +508,10 @@ var UI; .classList.add("noVNC_idle"); }, + keepControlbar: function() { + clearTimeout(UI.closeControlbarTimeout); + }, + openControlbar: function() { document.getElementById('noVNC_control_bar') .classList.add("noVNC_open"); @@ -923,7 +941,6 @@ var UI; connect: function() { UI.closeAllPanels(); - UI.closeControlbar(); var host = document.getElementById('noVNC_setting_host').value; var port = document.getElementById('noVNC_setting_port').value; From cd5a035d901e536d726400708c7929e5df0fa7b2 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 13:30:28 +0200 Subject: [PATCH 41/46] Make sure all buttons have a tooltip --- vnc.html | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/vnc.html b/vnc.html index 5019bfd9..b7074237 100644 --- a/vnc.html +++ b/vnc.html @@ -67,13 +67,17 @@
    + id="noVNC_mouse_button0" class="noVNC_button" + title="Active Mouse Button"/> + id="noVNC_mouse_button1" class="noVNC_button" + title="Active Mouse Button"/> + id="noVNC_mouse_button2" class="noVNC_button" + title="Active Mouse Button"/> + id="noVNC_mouse_button4" class="noVNC_button" + title="Active Mouse Button"/> @@ -82,17 +86,22 @@
    + id="noVNC_toggle_extra_keys_button" class="noVNC_button" + title="Show Extra Keys"/>
    + id="noVNC_toggle_ctrl_button" class="noVNC_button" + title="Toggle Ctrl"/> + id="noVNC_toggle_alt_button" class="noVNC_button" + title="Toggle Alt"/> + id="noVNC_send_tab_button" class="noVNC_button" + title="Send Tab"/> + id="noVNC_send_esc_button" class="noVNC_button" + title="Send Escape"/>
    From ca25d2ae26ffb22a2b7f9a4c56393165ca70052b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 26 Aug 2016 13:34:01 +0200 Subject: [PATCH 42/46] Move Ctrl+Alt+Del to extra keys menu The extra keys menu is now present for all devices, so avoid clutter by moving the Ctrl+Alt+Del button there as well. --- app/styles/base.css | 5 ----- app/ui.js | 5 +++-- vnc.html | 8 +++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index 8fbcb282..b87c52e8 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -316,11 +316,6 @@ input[type=button]:active, select:active { display: none; } -/* Send Ctrl+Alt+Delete */ -:root:not(.noVNC_connected) #noVNC_send_ctrl_alt_del_button { - display: none; -} - #noVNC_modifiers { background-color: rgb(92, 92, 92); border: none; diff --git a/app/ui.js b/app/ui.js index 0ccffadc..f78b74c5 100644 --- a/app/ui.js +++ b/app/ui.js @@ -210,8 +210,6 @@ var UI; document.getElementById("noVNC_view_drag_button") .addEventListener('click', UI.toggleViewDrag); - document.getElementById("noVNC_send_ctrl_alt_del_button") - .addEventListener('click', UI.sendCtrlAltDel); document.getElementById("noVNC_control_bar_handle") .addEventListener('mousedown', UI.controlbarHandleMouseDown); @@ -277,6 +275,8 @@ var UI; .addEventListener('click', UI.sendTab); document.getElementById("noVNC_send_esc_button") .addEventListener('click', UI.sendEsc); + document.getElementById("noVNC_send_ctrl_alt_del_button") + .addEventListener('click', UI.sendCtrlAltDel); }, addXvpHandlers: function() { @@ -1462,6 +1462,7 @@ var UI; }, sendCtrlAltDel: function() { + UI.keepKeyboard(); UI.rfb.sendCtrlAltDel(); }, diff --git a/vnc.html b/vnc.html index b7074237..8a68ba6f 100644 --- a/vnc.html +++ b/vnc.html @@ -102,15 +102,13 @@ +
    - - - Date: Tue, 30 Aug 2016 16:38:09 +0200 Subject: [PATCH 43/46] Clean up panel layouts Make sure everything follows a consistent style and is properly labeled. --- app/styles/base.css | 30 ++++++------- vnc.html | 105 +++++++++++++++++++++++++++++++------------- 2 files changed, 89 insertions(+), 46 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index b87c52e8..bc5fc280 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -283,6 +283,15 @@ input[type=button]:active, select:active { transform: translateX(75px); } +.noVNC_panel hr { + border: none; + border-top: 1px solid rgb(192, 192, 192); +} + +.noVNC_panel label { + display: block; +} + .noVNC_submit { float: right; } @@ -332,6 +341,10 @@ input[type=button]:active, select:active { display: none; } +#noVNC_xvp input[type=button] { + width: 100%; +} + /* Clipboard */ :root:not(.noVNC_connected) #noVNC_clipboard_button { display: none; @@ -350,7 +363,7 @@ input[type=button]:active, select:active { } #noVNC_settings ul { list-style: none; - margin: 3px; + margin: 0px; padding: 0px; } #noVNC_setting_path { @@ -369,18 +382,9 @@ input[type=button]:active, select:active { margin: 0px; padding: 0px; } -#noVNC_connect_controls li { - padding-bottom:8px; -} -#noVNC_setting_host { - width:150px; -} #noVNC_setting_port { width: 80px; } -#noVNC_setting_password { - width: 150px; -} /* ---------------------------------------- * Status Dialog @@ -462,12 +466,6 @@ input[type=button]:active, select:active { margin: 0px; padding: 0px; } -#noVNC_password_dlg li { - padding-bottom:8px; -} -#noVNC_password_input { - width: 150px; -} /* ---------------------------------------- * Main Area diff --git a/vnc.html b/vnc.html index 8a68ba6f..0d97734b 100644 --- a/vnc.html +++ b/vnc.html @@ -147,37 +147,62 @@
      -
    • Encrypt
    • -
    • True Color
    • -
    • Local Cursor
    • -
    • Clip to Window
    • -
    • Shared Mode
    • -
    • View Only
    • -
      -
    • Path
    • -
    • +
    • +
    • -
    • Repeater ID
    • -
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    • + +
    • +

    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +

    • -
    • + + +
    • -
    • + + + +
    • +

    • +
    • +
    • -
      -
    @@ -192,11 +217,26 @@
      -
    • -
    • -
    • -
    • -
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +
    • + + +
    • +

    • +
    • + +
    @@ -213,8 +253,13 @@
      -
    • -
    • +
    • + + +
    • +
    • + +
    From 5454c3451124741a0244eed66c5fc8afb6306a53 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 30 Aug 2016 16:38:45 +0200 Subject: [PATCH 44/46] Add headings to panels --- app/styles/base.css | 15 +++++++++++++++ app/styles/black.css | 2 +- app/styles/blue.css | 2 +- vnc.html | 12 ++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/app/styles/base.css b/app/styles/base.css index bc5fc280..89b8eeaf 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -292,6 +292,21 @@ input[type=button]:active, select:active { display: block; } +.noVNC_panel .noVNC_heading { + background-color: rgb(110, 132, 163); + border-radius: 5px; + padding: 5px; + /* Compensate for padding in image */ + padding-right: 8px; + color: white; + font-size: 20px; + margin-bottom: 10px; + white-space: nowrap; +} +.noVNC_panel .noVNC_heading img { + vertical-align: bottom; +} + .noVNC_submit { float: right; } diff --git a/app/styles/black.css b/app/styles/black.css index d982a813..178fa100 100644 --- a/app/styles/black.css +++ b/app/styles/black.css @@ -12,7 +12,7 @@ color:#fff; } -#noVNC_control_bar, #noVNC_control_bar_handle { +#noVNC_control_bar, #noVNC_control_bar_handle, .noVNC_panel .noVNC_heading { background: #4c4c4c; } diff --git a/app/styles/blue.css b/app/styles/blue.css index e36e6d1d..a38ede15 100644 --- a/app/styles/blue.css +++ b/app/styles/blue.css @@ -12,6 +12,6 @@ color:#fff; } -#noVNC_control_bar, #noVNC_control_bar_handle { +#noVNC_control_bar, #noVNC_control_bar_handle, .noVNC_panel .noVNC_heading { background: #080F80; } diff --git a/vnc.html b/vnc.html index 0d97734b..50cd7795 100644 --- a/vnc.html +++ b/vnc.html @@ -115,6 +115,9 @@ title="Shutdown/Reboot..." />
    +
    + Power +
    @@ -127,6 +130,9 @@ title="Clipboard" />
    +
    + Clipboard +

    @@ -147,6 +153,9 @@
      +
    • + Settings +
    • @@ -217,6 +226,9 @@
        +
      • + Connection +
      • From 1a15cb5b3257973d64e16ea4c88a7eb72e077fb7 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 22 Sep 2016 12:58:05 +0200 Subject: [PATCH 45/46] Add hover hints to buttons Disable it on touch devices though as it is mostly annoying there. --- app/styles/base.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/styles/base.css b/app/styles/base.css index 89b8eeaf..4431908d 100644 --- a/app/styles/base.css +++ b/app/styles/base.css @@ -97,6 +97,10 @@ input[type=button]:active, select:active { margin-top: 3px; } +:root:not(.noVNC_touch) input[type=button]:hover:not(:disabled), :root:not(.noVNC_touch) select:hover:not(:disabled) { + background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250)); +} + /* ---------------------------------------- * WebKit centering hacks * ---------------------------------------- @@ -250,6 +254,13 @@ input[type=button]:active, select:active { padding-top: 5px; padding-bottom: 3px; } +:root:not(.noVNC_touch) .noVNC_button.noVNC_selected:hover { + border-color: rgba(0, 0, 0, 0.4); + background: rgba(0, 0, 0, 0.2); +} +:root:not(.noVNC_touch) .noVNC_button:hover { + background: rgba(255, 255, 255, 0.2); +} .noVNC_button.noVNC_hidden { display: none; } From 4b30f9ce091cde40fd5304816be7dc72f09c2521 Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Fri, 23 Sep 2016 17:31:23 +0200 Subject: [PATCH 46/46] Clean up virtual keyboard handling --- app/ui.js | 79 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/app/ui.js b/app/ui.js index f78b74c5..cfcfe1c5 100644 --- a/app/ui.js +++ b/app/ui.js @@ -231,12 +231,12 @@ var UI; document.getElementById("noVNC_mouse_button4") .addEventListener('click', function () { UI.setMouseButton(0); }); document.getElementById("noVNC_keyboard_button") - .addEventListener('click', UI.showKeyboard); + .addEventListener('click', UI.toggleVirtualKeyboard); document.getElementById("noVNC_keyboardinput") .addEventListener('input', UI.keyInput); document.getElementById("noVNC_keyboardinput") - .addEventListener('blur', UI.hideKeyboard); + .addEventListener('blur', UI.onblurVirtualKeyboard); document.getElementById("noVNC_keyboardinput") .addEventListener('submit', function () { return false; }); @@ -1281,45 +1281,64 @@ var UI; * KEYBOARD * ------v------*/ - // On touch devices, show the OS keyboard - showKeyboard: function() { - var kbi = document.getElementById('noVNC_keyboardinput'); - var skb = document.getElementById('noVNC_keyboard_button'); - var l = kbi.value.length; - if(UI.keyboardVisible === false) { - kbi.focus(); - try { kbi.setSelectionRange(l, l); } // Move the caret to the end - catch (err) {} // setSelectionRange is undefined in Google Chrome - UI.keyboardVisible = true; - skb.classList.add("noVNC_selected"); - } else if(UI.keyboardVisible === true) { - kbi.blur(); - skb.classList.remove("noVNC_selected"); - UI.keyboardVisible = false; + showVirtualKeyboard: function() { + if (!UI.isTouchDevice) + return; + + var input = document.getElementById('noVNC_keyboardinput'); + + if (document.activeElement == input) + return; + + UI.keyboardVisible = true; + document.getElementById('noVNC_keyboard_button') + .classList.add("noVNC_selected"); + input.focus(); + + try { + var l = input.value.length; + // Move the caret to the end + input.setSelectionRange(l, l); + } catch (err) {} // setSelectionRange is undefined in Google Chrome + }, + + hideVirtualKeyboard: function() { + if (!UI.isTouchDevice) + return; + + var input = document.getElementById('noVNC_keyboardinput'); + + if (document.activeElement != input) + return; + + input.blur(); + }, + + toggleVirtualKeyboard: function () { + if (UI.keyboardVisible) { + UI.hideVirtualKeyboard(); + } else { + UI.showVirtualKeyboard(); } }, - hideKeyboard: function() { - document.getElementById('noVNC_keyboard_button') - .classList.remove("noVNC_selected"); + onblurVirtualKeyboard: function() { //Weird bug in iOS if you change keyboardVisible //here it does not actually occur so next time //you click keyboard icon it doesnt work. UI.hideKeyboardTimeout = setTimeout(function() { UI.keyboardVisible = false; + document.getElementById('noVNC_keyboard_button') + .classList.remove("noVNC_selected"); },100); }, keepKeyboard: function() { clearTimeout(UI.hideKeyboardTimeout); if(UI.keyboardVisible === true) { - document.getElementById('noVNC_keyboardinput').focus(); - document.getElementById('noVNC_keyboard_button') - .classList.add("noVNC_selected"); + UI.showVirtualKeyboard(); } else if(UI.keyboardVisible === false) { - document.getElementById('noVNC_keyboardinput').blur(); - document.getElementById('noVNC_keyboard_button') - .classList.remove("noVNC_selected"); + UI.hideVirtualKeyboard(); } }, @@ -1400,6 +1419,12 @@ var UI; } }, +/* ------^------- + * /KEYBOARD + * ============== + * EXTRA KEYS + * ------v------*/ + openExtraKeys: function() { UI.closeAllPanels(); UI.openControlbar(); @@ -1467,7 +1492,7 @@ var UI; }, /* ------^------- - * /KEYBOARD + * /EXTRA KEYS * ============== * MISC * ------v------*/