diff --git a/.eslintrc b/.eslintrc
index 7797028e9..10e15cec3 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -26,10 +26,13 @@
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"indent": ["error", 4, { "SwitchCase": 1,
+ "VariableDeclarator": "first",
"FunctionDeclaration": { "parameters": "first" },
+ "FunctionExpression": { "parameters": "first" },
"CallExpression": { "arguments": "first" },
"ArrayExpression": "first",
"ObjectExpression": "first",
+ "ImportDeclaration": "first",
"ignoreComments": true }],
"comma-spacing": ["error"],
"comma-style": ["error"],
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 715c98538..84e634d2f 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -67,27 +67,30 @@ jobs:
path: ${{ steps.snapcraft.outputs.snap }}
- uses: snapcore/action-publish@v1
with:
- store_login: ${{ secrets.SNAPCRAFT_LOGIN }}
snap: ${{ steps.snapcraft.outputs.snap }}
release: stable
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
if: |
github.repository == 'novnc/noVNC' &&
github.event_name == 'release' &&
!github.event.release.prerelease
- uses: snapcore/action-publish@v1
with:
- store_login: ${{ secrets.SNAPCRAFT_LOGIN }}
snap: ${{ steps.snapcraft.outputs.snap }}
release: beta
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
if: |
github.repository == 'novnc/noVNC' &&
github.event_name == 'release' &&
github.event.release.prerelease
- uses: snapcore/action-publish@v1
with:
- store_login: ${{ secrets.SNAPCRAFT_LOGIN }}
snap: ${{ steps.snapcraft.outputs.snap }}
release: edge
+ env:
+ SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
if: |
github.repository == 'novnc/noVNC' &&
github.event_name == 'push' &&
diff --git a/AUTHORS b/AUTHORS
index dec0e8932..e8fb12404 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,9 +1,9 @@
maintainers:
-- Joel Martin (@kanaka)
-- Solly Ross (@directxman12)
- Samuel Mannehed for Cendio AB (@samhed)
- Pierre Ossman for Cendio AB (@CendioOssman)
maintainersEmeritus:
+- Joel Martin (@kanaka)
+- Solly Ross (@directxman12)
- @astrand
contributors:
# There are a bunch of people that should be here.
diff --git a/LICENSE.txt b/LICENSE.txt
index ee81d2029..37efdcdba 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,4 +1,4 @@
-noVNC is Copyright (C) 2019 The noVNC Authors
+noVNC is Copyright (C) 2022 The noVNC Authors
(./AUTHORS)
The noVNC core library files are licensed under the MPL 2.0 (Mozilla
diff --git a/README.md b/README.md
index c94e13c2c..a771cb438 100644
--- a/README.md
+++ b/README.md
@@ -65,10 +65,14 @@ Please tweet [@noVNC](http://www.twitter.com/noVNC) if you do.
### Features
* Supports all modern browsers including mobile (iOS, Android)
-* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG
+* Supported authentication methods: none, classical VNC, RealVNC's
+ RSA-AES, Tight, VeNCrypt Plain, XVP, Apple's Diffie-Hellman,
+ UltraVNC's MSLogonII
+* Supported VNC encodings: raw, copyrect, rre, hextile, tight, tightPNG,
+ ZRLE, JPEG
* Supports scaling, clipping and resizing the desktop
* Local cursor rendering
-* Clipboard copy/paste
+* Clipboard copy/paste with full Unicode support
* Translations
* Touch gestures for emulating common mouse actions
* Licensed mainly under the [MPL 2.0](http://www.mozilla.org/MPL/2.0/), see
@@ -203,11 +207,13 @@ See [AUTHORS](AUTHORS) for a (full-ish) list of authors. If you're not on
that list and you think you should be, feel free to send a PR to fix that.
* Core team:
- * [Joel Martin](https://github.com/kanaka)
* [Samuel Mannehed](https://github.com/samhed) (Cendio)
- * [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack)
* [Pierre Ossman](https://github.com/CendioOssman) (Cendio)
+* Previous core contributors:
+ * [Joel Martin](https://github.com/kanaka) (Project founder)
+ * [Solly Ross](https://github.com/DirectXMan12) (Red Hat / OpenStack)
+
* Notable contributions:
* UI and Icons : Pierre Ossman, Chris Gordon
* Original Logo : Michael Sersen
diff --git a/app/images/icons/Makefile b/app/images/icons/Makefile
index be564b43b..03eaed071 100644
--- a/app/images/icons/Makefile
+++ b/app/images/icons/Makefile
@@ -1,42 +1,42 @@
-ICONS := \
- novnc-16x16.png \
- novnc-24x24.png \
- novnc-32x32.png \
- novnc-48x48.png \
- novnc-64x64.png
-
-ANDROID_LAUNCHER := \
- novnc-48x48.png \
- novnc-72x72.png \
- novnc-96x96.png \
- novnc-144x144.png \
- novnc-192x192.png
-
-IPHONE_LAUNCHER := \
- novnc-60x60.png \
- novnc-120x120.png
-
-IPAD_LAUNCHER := \
- novnc-76x76.png \
- novnc-152x152.png
-
-ALL_ICONS := $(ICONS) $(ANDROID_LAUNCHER) $(IPHONE_LAUNCHER) $(IPAD_LAUNCHER)
+BROWSER_SIZES := 16 24 32 48 64
+#ANDROID_SIZES := 72 96 144 192
+# FIXME: The ICO is limited to 8 icons due to a Chrome bug:
+# https://bugs.chromium.org/p/chromium/issues/detail?id=1381393
+ANDROID_SIZES := 96 144 192
+WEB_ICON_SIZES := $(BROWSER_SIZES) $(ANDROID_SIZES)
+
+#IOS_1X_SIZES := 20 29 40 76 # No such devices exist anymore
+IOS_2X_SIZES := 40 58 80 120 152 167
+IOS_3X_SIZES := 60 87 120 180
+ALL_IOS_SIZES := $(IOS_1X_SIZES) $(IOS_2X_SIZES) $(IOS_3X_SIZES)
+
+ALL_ICONS := \
+ $(ALL_IOS_SIZES:%=novnc-ios-%.png) \
+ novnc.ico
all: $(ALL_ICONS)
-novnc-16x16.png: novnc-icon-sm.svg
- convert -density 90 \
- -background transparent "$<" "$@"
-novnc-24x24.png: novnc-icon-sm.svg
- convert -density 135 \
- -background transparent "$<" "$@"
-novnc-32x32.png: novnc-icon-sm.svg
- convert -density 180 \
- -background transparent "$<" "$@"
+# Our testing shows that the ICO file need to be sorted in largest to
+# smallest to get the apporpriate behviour
+WEB_ICON_SIZES_REVERSE := $(shell echo $(WEB_ICON_SIZES) | tr ' ' '\n' | sort -nr | tr '\n' ' ')
+WEB_BASE_ICONS := $(WEB_ICON_SIZES_REVERSE:%=novnc-%.png)
+.INTERMEDIATE: $(WEB_BASE_ICONS)
+novnc.ico: $(WEB_BASE_ICONS)
+ convert $(WEB_BASE_ICONS) "$@"
+
+# General conversion
novnc-%.png: novnc-icon.svg
- convert -density $$[`echo $* | cut -d x -f 1` * 90 / 48] \
- -background transparent "$<" "$@"
+ convert -depth 8 -background transparent \
+ -size $*x$* "$(lastword $^)" "$@"
+
+# iOS icons use their own SVG
+novnc-ios-%.png: novnc-ios-icon.svg
+ convert -depth 8 -background transparent \
+ -size $*x$* "$(lastword $^)" "$@"
+
+# The smallest sizes are generated using a different SVG
+novnc-16.png novnc-24.png novnc-32.png: novnc-icon-sm.svg
clean:
rm -f *.png
diff --git a/app/images/icons/novnc-120x120.png b/app/images/icons/novnc-120x120.png
deleted file mode 100644
index 40823efba..000000000
Binary files a/app/images/icons/novnc-120x120.png and /dev/null differ
diff --git a/app/images/icons/novnc-144x144.png b/app/images/icons/novnc-144x144.png
deleted file mode 100644
index eee71f11c..000000000
Binary files a/app/images/icons/novnc-144x144.png and /dev/null differ
diff --git a/app/images/icons/novnc-152x152.png b/app/images/icons/novnc-152x152.png
deleted file mode 100644
index 0694b2de3..000000000
Binary files a/app/images/icons/novnc-152x152.png and /dev/null differ
diff --git a/app/images/icons/novnc-16x16.png b/app/images/icons/novnc-16x16.png
deleted file mode 100644
index 42108f409..000000000
Binary files a/app/images/icons/novnc-16x16.png and /dev/null differ
diff --git a/app/images/icons/novnc-192x192.png b/app/images/icons/novnc-192x192.png
deleted file mode 100644
index ef9201f43..000000000
Binary files a/app/images/icons/novnc-192x192.png and /dev/null differ
diff --git a/app/images/icons/novnc-24x24.png b/app/images/icons/novnc-24x24.png
deleted file mode 100644
index 110613594..000000000
Binary files a/app/images/icons/novnc-24x24.png and /dev/null differ
diff --git a/app/images/icons/novnc-32x32.png b/app/images/icons/novnc-32x32.png
deleted file mode 100644
index ff00dc305..000000000
Binary files a/app/images/icons/novnc-32x32.png and /dev/null differ
diff --git a/app/images/icons/novnc-48x48.png b/app/images/icons/novnc-48x48.png
deleted file mode 100644
index f24cd6cc9..000000000
Binary files a/app/images/icons/novnc-48x48.png and /dev/null differ
diff --git a/app/images/icons/novnc-60x60.png b/app/images/icons/novnc-60x60.png
deleted file mode 100644
index 06b0d609a..000000000
Binary files a/app/images/icons/novnc-60x60.png and /dev/null differ
diff --git a/app/images/icons/novnc-64x64.png b/app/images/icons/novnc-64x64.png
deleted file mode 100644
index 6d0fb3418..000000000
Binary files a/app/images/icons/novnc-64x64.png and /dev/null differ
diff --git a/app/images/icons/novnc-72x72.png b/app/images/icons/novnc-72x72.png
deleted file mode 100644
index 23163a22d..000000000
Binary files a/app/images/icons/novnc-72x72.png and /dev/null differ
diff --git a/app/images/icons/novnc-76x76.png b/app/images/icons/novnc-76x76.png
deleted file mode 100644
index aef61c480..000000000
Binary files a/app/images/icons/novnc-76x76.png and /dev/null differ
diff --git a/app/images/icons/novnc-96x96.png b/app/images/icons/novnc-96x96.png
deleted file mode 100644
index 1a77c53f4..000000000
Binary files a/app/images/icons/novnc-96x96.png and /dev/null differ
diff --git a/app/images/icons/novnc-ios-120.png b/app/images/icons/novnc-ios-120.png
new file mode 100644
index 000000000..8da7bab3d
Binary files /dev/null and b/app/images/icons/novnc-ios-120.png differ
diff --git a/app/images/icons/novnc-ios-152.png b/app/images/icons/novnc-ios-152.png
new file mode 100644
index 000000000..60b2bcef5
Binary files /dev/null and b/app/images/icons/novnc-ios-152.png differ
diff --git a/app/images/icons/novnc-ios-167.png b/app/images/icons/novnc-ios-167.png
new file mode 100644
index 000000000..98fade2e2
Binary files /dev/null and b/app/images/icons/novnc-ios-167.png differ
diff --git a/app/images/icons/novnc-ios-180.png b/app/images/icons/novnc-ios-180.png
new file mode 100644
index 000000000..5d24df70a
Binary files /dev/null and b/app/images/icons/novnc-ios-180.png differ
diff --git a/app/images/icons/novnc-ios-40.png b/app/images/icons/novnc-ios-40.png
new file mode 100644
index 000000000..cf14894da
Binary files /dev/null and b/app/images/icons/novnc-ios-40.png differ
diff --git a/app/images/icons/novnc-ios-58.png b/app/images/icons/novnc-ios-58.png
new file mode 100644
index 000000000..f6dfbebd2
Binary files /dev/null and b/app/images/icons/novnc-ios-58.png differ
diff --git a/app/images/icons/novnc-ios-60.png b/app/images/icons/novnc-ios-60.png
new file mode 100644
index 000000000..8cda29530
Binary files /dev/null and b/app/images/icons/novnc-ios-60.png differ
diff --git a/app/images/icons/novnc-ios-80.png b/app/images/icons/novnc-ios-80.png
new file mode 100644
index 000000000..6c417c47e
Binary files /dev/null and b/app/images/icons/novnc-ios-80.png differ
diff --git a/app/images/icons/novnc-ios-87.png b/app/images/icons/novnc-ios-87.png
new file mode 100644
index 000000000..4377d874b
Binary files /dev/null and b/app/images/icons/novnc-ios-87.png differ
diff --git a/app/images/icons/novnc-ios-icon.svg b/app/images/icons/novnc-ios-icon.svg
new file mode 100644
index 000000000..009452ac6
--- /dev/null
+++ b/app/images/icons/novnc-ios-icon.svg
@@ -0,0 +1,183 @@
+
+
+
+
diff --git a/app/images/icons/novnc.ico b/app/images/icons/novnc.ico
new file mode 100644
index 000000000..c3bc58e38
Binary files /dev/null and b/app/images/icons/novnc.ico differ
diff --git a/app/locale/fr.json b/app/locale/fr.json
index 19e8255b3..22531f73b 100644
--- a/app/locale/fr.json
+++ b/app/locale/fr.json
@@ -1,21 +1,22 @@
{
+ "HTTPS is required for full functionality": "",
"Connecting...": "En cours de connexion...",
"Disconnecting...": "Déconnexion en cours...",
"Reconnecting...": "Reconnexion en cours...",
"Internal error": "Erreur interne",
"Must set host": "Doit définir l'hôte",
- "Connected (encrypted) to ": "Connecté (crypté) à ",
- "Connected (unencrypted) to ": "Connecté (non crypté) à ",
- "Something went wrong, connection is closed": "Quelque chose est arrivé, la connexion est fermée",
+ "Connected (encrypted) to ": "Connecté (chiffré) à ",
+ "Connected (unencrypted) to ": "Connecté (non chiffré) à ",
+ "Something went wrong, connection is closed": "Quelque chose s'est mal passé, la connexion a été fermée",
"Failed to connect to server": "Échec de connexion au serveur",
"Disconnected": "Déconnecté",
- "New connection has been rejected with reason: ": "Une nouvelle connexion a été rejetée avec raison: ",
+ "New connection has been rejected with reason: ": "Une nouvelle connexion a été rejetée avec motif : ",
"New connection has been rejected": "Une nouvelle connexion a été rejetée",
"Credentials are required": "Les identifiants sont requis",
- "noVNC encountered an error:": "noVNC a rencontré une erreur:",
+ "noVNC encountered an error:": "noVNC a rencontré une erreur :",
"Hide/Show the control bar": "Masquer/Afficher la barre de contrôle",
"Drag": "Faire glisser",
- "Move/Drag Viewport": "Déplacer/faire glisser Viewport",
+ "Move/Drag Viewport": "Déplacer/faire glisser le Viewport",
"Keyboard": "Clavier",
"Show Keyboard": "Afficher le clavier",
"Extra keys": "Touches supplémentaires",
@@ -39,34 +40,39 @@
"Reboot": "Redémarrer",
"Reset": "Réinitialiser",
"Clipboard": "Presse-papiers",
- "Clear": "Effacer",
- "Fullscreen": "Plein écran",
+ "Edit clipboard content in the textarea below.": "",
"Settings": "Paramètres",
"Shared Mode": "Mode partagé",
"View Only": "Afficher uniquement",
"Clip to Window": "Clip à fenêtre",
- "Scaling Mode:": "Mode mise à l'échelle:",
+ "Scaling Mode:": "Mode mise à l'échelle :",
"None": "Aucun",
"Local Scaling": "Mise à l'échelle locale",
"Remote Resizing": "Redimensionnement à distance",
"Advanced": "Avancé",
- "Quality:": "Qualité:",
- "Compression level:": "Niveau de compression:",
- "Repeater ID:": "ID Répéteur:",
+ "Quality:": "Qualité :",
+ "Compression level:": "Niveau de compression :",
+ "Repeater ID:": "ID Répéteur :",
"WebSocket": "WebSocket",
- "Encrypt": "Crypter",
- "Host:": "Hôte:",
- "Port:": "Port:",
- "Path:": "Chemin:",
+ "Encrypt": "Chiffrer",
+ "Host:": "Hôte :",
+ "Port:": "Port :",
+ "Path:": "Chemin :",
"Automatic Reconnect": "Reconnecter automatiquemen",
- "Reconnect Delay (ms):": "Délai de reconnexion (ms):",
+ "Reconnect Delay (ms):": "Délai de reconnexion (ms) :",
"Show Dot when No Cursor": "Afficher le point lorsqu'il n'y a pas de curseur",
- "Logging:": "Se connecter:",
- "Version:": "Version:",
+ "Logging:": "Se connecter :",
+ "Version:": "Version :",
"Disconnect": "Déconnecter",
"Connect": "Connecter",
- "Username:": "Nom d'utilisateur:",
- "Password:": "Mot de passe:",
+ "Server identity": "",
+ "The server has provided the following identifying information:": "",
+ "Fingerprint:": "",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "",
+ "Approve": "",
+ "Reject": "",
+ "Username:": "Nom d'utilisateur :",
+ "Password:": "Mot de passe :",
"Send Credentials": "Envoyer les identifiants",
"Cancel": "Annuler"
}
\ No newline at end of file
diff --git a/app/locale/sv.json b/app/locale/sv.json
index e46df45b5..077ef42c8 100644
--- a/app/locale/sv.json
+++ b/app/locale/sv.json
@@ -1,4 +1,5 @@
{
+ "HTTPS is required for full functionality": "HTTPS krävs för full funktionalitet",
"Connecting...": "Ansluter...",
"Disconnecting...": "Kopplar ner...",
"Reconnecting...": "Återansluter...",
@@ -39,8 +40,8 @@
"Reboot": "Boota om",
"Reset": "Återställ",
"Clipboard": "Urklipp",
- "Clear": "Rensa",
- "Fullscreen": "Fullskärm",
+ "Edit clipboard content in the textarea below.": "Redigera urklippets innehåll i fältet nedan.",
+ "Full Screen": "Fullskärm",
"Settings": "Inställningar",
"Shared Mode": "Delat Läge",
"View Only": "Endast Visning",
@@ -65,6 +66,13 @@
"Version:": "Version:",
"Disconnect": "Koppla från",
"Connect": "Anslut",
+ "Server identity": "Server-identitet",
+ "The server has provided the following identifying information:": "Servern har gett följande identifierande information:",
+ "Fingerprint:": "Fingeravtryck:",
+ "Please verify that the information is correct and press \"Approve\". Otherwise press \"Reject\".": "Kontrollera att informationen är korrekt och tryck sedan \"Godkänn\". Tryck annars \"Neka\".",
+ "Approve": "Godkänn",
+ "Reject": "Neka",
+ "Credentials": "Användaruppgifter",
"Username:": "Användarnamn:",
"Password:": "Lösenord:",
"Send Credentials": "Skicka Användaruppgifter",
diff --git a/app/localization.js b/app/localization.js
index 100901c9d..7d7e6e6af 100644
--- a/app/localization.js
+++ b/app/localization.js
@@ -16,13 +16,19 @@ export class Localizer {
this.language = 'en';
// Current dictionary of translations
- this.dictionary = undefined;
+ this._dictionary = undefined;
}
// Configure suitable language based on user preferences
- setup(supportedLanguages) {
+ async setup(supportedLanguages, baseURL) {
this.language = 'en'; // Default: US English
+ this._dictionary = undefined;
+ this._setupLanguage(supportedLanguages);
+ await this._setupDictionary(baseURL);
+ }
+
+ _setupLanguage(supportedLanguages) {
/*
* Navigator.languages only available in Chrome (32+) and FireFox (32+)
* Fall back to navigator.language for other browsers
@@ -40,12 +46,6 @@ export class Localizer {
.replace("_", "-")
.split("-");
- // Built-in default?
- if ((userLang[0] === 'en') &&
- ((userLang[1] === undefined) || (userLang[1] === 'us'))) {
- return;
- }
-
// First pass: perfect match
for (let j = 0; j < supportedLanguages.length; j++) {
const supLang = supportedLanguages[j]
@@ -64,7 +64,12 @@ export class Localizer {
return;
}
- // Second pass: fallback
+ // Second pass: English fallback
+ if (userLang[0] === 'en') {
+ return;
+ }
+
+ // Third pass pass: other fallback
for (let j = 0;j < supportedLanguages.length;j++) {
const supLang = supportedLanguages[j]
.toLowerCase()
@@ -84,10 +89,32 @@ export class Localizer {
}
}
+ async _setupDictionary(baseURL) {
+ if (baseURL) {
+ if (!baseURL.endsWith("/")) {
+ baseURL = baseURL + "/";
+ }
+ } else {
+ baseURL = "";
+ }
+
+ if (this.language === "en") {
+ return;
+ }
+
+ let response = await fetch(baseURL + this.language + ".json");
+ if (!response.ok) {
+ throw Error("" + response.status + " " + response.statusText);
+ }
+
+ this._dictionary = await response.json();
+ }
+
// Retrieve localised text
get(id) {
- if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) {
- return this.dictionary[id];
+ if (typeof this._dictionary !== 'undefined' &&
+ this._dictionary[id]) {
+ return this._dictionary[id];
} else {
return id;
}
@@ -103,13 +130,20 @@ export class Localizer {
return items.indexOf(searchElement) !== -1;
}
+ function translateString(str) {
+ // We assume surrounding whitespace, and whitespace around line
+ // breaks is just for source formatting
+ str = str.split("\n").map(s => s.trim()).join(" ").trim();
+ return self.get(str);
+ }
+
function translateAttribute(elem, attr) {
- const str = self.get(elem.getAttribute(attr));
+ const str = translateString(elem.getAttribute(attr));
elem.setAttribute(attr, str);
}
function translateTextNode(node) {
- const str = self.get(node.data.trim());
+ const str = translateString(node.data);
node.data = str;
}
diff --git a/app/styles/base.css b/app/styles/base.css
index bf1fef953..f83ad4b93 100644
--- a/app/styles/base.css
+++ b/app/styles/base.css
@@ -22,8 +22,6 @@
/*
* State variables (set on :root):
*
- * noVNC_touch: Device has touch input
- *
* noVNC_loading: Page is still loading
* noVNC_connecting: Connecting to server
* noVNC_reconnecting: Re-establishing a connection
@@ -321,16 +319,20 @@ html {
.noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
transform: none;
}
+/* Larger touch area for the handle, used when a touch screen is available */
#noVNC_control_bar_handle div {
position: absolute;
right: -35px;
top: 0;
width: 50px;
height: 100%;
-}
-:root:not(.noVNC_touch) #noVNC_control_bar_handle div {
display: none;
}
+@media (any-pointer: coarse) {
+ #noVNC_control_bar_handle div {
+ display: initial;
+ }
+}
.noVNC_right #noVNC_control_bar_handle div {
left: -35px;
right: auto;
@@ -389,39 +391,41 @@ html {
vertical-align: middle;
border:1px solid rgba(255, 255, 255, 0.2);
border-radius: 6px;
+ background-color: transparent;
+ background-image: unset; /* we don't want the gradiant from input.css */
}
#noVNC_control_bar .noVNC_button.noVNC_selected {
border-color: rgba(0, 0, 0, 0.8);
- background: rgba(0, 0, 0, 0.5);
+ background-color: rgba(0, 0, 0, 0.5);
}
-#noVNC_control_bar .noVNC_button:disabled {
- opacity: 0.4;
- /* See firefox bug regarding cursor on disabled :
- https://bugzilla.mozilla.org/show_bug.cgi?id=1798304 */
- cursor: default;
+#noVNC_control_bar .noVNC_button.noVNC_selected:not(:disabled):hover {
+ border-color: rgba(0, 0, 0, 0.4);
+ background-color: rgba(0, 0, 0, 0.2);
}
-#noVNC_control_bar .noVNC_button:focus {
- outline: none;
+#noVNC_control_bar .noVNC_button:not(:disabled):hover {
+ background-color: rgba(255, 255, 255, 0.2);
}
#noVNC_control_bar .noVNC_button:not(:disabled):active {
padding-top: 5px;
padding-bottom: 3px;
}
-/* Android browsers don't properly update hover state if touch events
- * are intercepted, but focus should be safe to display */
-:root:not(.noVNC_touch) #noVNC_control_bar .noVNC_button.noVNC_selected:not(:disabled):hover,
-#noVNC_control_bar .noVNC_button.noVNC_selected:not(:disabled):focus {
- border-color: rgba(0, 0, 0, 0.4);
- background: rgba(0, 0, 0, 0.2);
-}
-:root:not(.noVNC_touch) #noVNC_control_bar .noVNC_button:not(:disabled):hover,
-#noVNC_control_bar .noVNC_button:not(:disabled):focus {
- background: rgba(255, 255, 255, 0.2);
-}
#noVNC_control_bar .noVNC_button.noVNC_hidden {
display: none !important;
}
+/* Android browsers don't properly update hover state if touch events are
+ * intercepted, like they are when clicking on the remote screen. */
+@media (any-pointer: coarse) {
+ #noVNC_control_bar .noVNC_button:not(:disabled):hover {
+ background-color: transparent;
+ }
+ #noVNC_control_bar .noVNC_button.noVNC_selected:not(:disabled):hover {
+ border-color: rgba(0, 0, 0, 0.8);
+ background-color: rgba(0, 0, 0, 0.5);
+ }
+}
+
+
/* Panels */
.noVNC_panel {
transform: translateX(25px);
@@ -549,8 +553,15 @@ html {
:root:not(.noVNC_connected) #noVNC_mobile_buttons {
display: none;
}
-:root:not(.noVNC_touch) #noVNC_mobile_buttons {
- display: none;
+@media not all and (any-pointer: coarse) {
+ /* FIXME: The button for the virtual keyboard is the only button in this
+ group of "mobile buttons". It is bad to assume that no touch
+ devices have physical keyboards available. Hopefully we can get
+ a media query for this:
+ https://github.com/w3c/csswg-drafts/issues/3871 */
+ :root.noVNC_connected #noVNC_mobile_buttons {
+ display: none;
+ }
}
/* Extra manual keys */
@@ -586,6 +597,7 @@ html {
width: 360px;
min-width: 150px;
height: 160px;
+ min-height: 70px;
box-sizing: border-box;
max-width: 100%;
@@ -649,7 +661,7 @@ html {
justify-content: center;
align-content: center;
- line-height: 25px;
+ line-height: 1.6;
word-wrap: break-word;
color: #fff;
@@ -723,36 +735,32 @@ html {
font-size: calc(25vw - 30px);
}
}
-#noVNC_connect_button {
- cursor: pointer;
-
- padding: 10px;
+#noVNC_connect_dlg div {
+ padding: 12px;
- color: white;
background-color: rgb(110, 132, 163);
border-radius: 12px;
-
text-align: center;
font-size: 20px;
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
}
-#noVNC_connect_button div {
- margin: 2px;
+#noVNC_connect_button {
+ width: 100%;
padding: 5px 30px;
- border: 1px solid rgb(83, 99, 122);
- border-bottom-width: 2px;
+
+ cursor: pointer;
+
+ border-color: rgb(83, 99, 122);
border-radius: 5px;
+
background: linear-gradient(to top, rgb(110, 132, 163), rgb(99, 119, 147));
+ color: white;
/* This avoids it jumping around when :active */
vertical-align: middle;
}
-#noVNC_connect_button div:active {
- border-bottom-width: 1px;
- margin-top: 3px;
-}
-:root:not(.noVNC_touch) #noVNC_connect_button div:hover {
+#noVNC_connect_button:hover {
background: linear-gradient(to top, rgb(110, 132, 163), rgb(105, 125, 155));
}
@@ -879,7 +887,7 @@ html {
.noVNC_logo {
color:yellow;
font-family: 'Orbitron', 'OrbitronTTF', sans-serif;
- line-height:90%;
+ line-height: 0.9;
text-shadow: 0.1em 0.1em 0 black;
}
.noVNC_logo span{
diff --git a/app/styles/input.css b/app/styles/input.css
index d6499a664..dc345aabc 100644
--- a/app/styles/input.css
+++ b/app/styles/input.css
@@ -5,25 +5,13 @@
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
*/
-input, select, textarea {
+/*
+ * Common for all inputs
+ */
+input, input::file-selector-button, button, select, textarea {
/* Respect standard font settings */
font: inherit;
-}
-input:not([type]),
-input[type=date],
-input[type=datetime-local],
-input[type=email],
-input[type=month],
-input[type=number],
-input[type=password],
-input[type=search],
-input[type=tel],
-input[type=text],
-input[type=time],
-input[type=url],
-input[type=week],
-textarea {
/* Disable default rendering */
appearance: none;
background: none;
@@ -32,125 +20,262 @@ textarea {
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));
+ --bg-gradient: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240));
+ background-image: var(--bg-gradient);
}
+/*
+ * Buttons
+ */
input[type=button],
input[type=color],
+input[type=image],
input[type=reset],
input[type=submit],
+input::file-selector-button,
button,
select {
- /* Disable default rendering */
- appearance: none;
- background: none;
-
- padding: 5px;
- 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;
-}
+ margin-top: 0;
-input[type=button],
-input[type=color],
-input[type=reset],
-input[type=submit],
-button {
padding-left: 20px;
padding-right: 20px;
+
+ /* Disable Chrome's touch tap highlight */
+ -webkit-tap-highlight-color: transparent;
}
+/*
+ * Select dropdowns
+ */
select {
- --select-arrow: calc(100% - 7px) no-repeat url('data:image/svg+xml;utf8, \
+ --select-arrow: url('data:image/svg+xml;utf8, \
');
- background: var(--select-arrow),
- linear-gradient(to top, rgb(255, 255, 255), rgb(240, 240, 240));
+ background-image: var(--select-arrow), var(--bg-gradient);
+ background-position: calc(100% - 7px), left top;
+ background-repeat: no-repeat;
padding-right: calc(2*7px + 8px);
padding-left: 7px;
}
-:root:not(.noVNC_touch) select:hover:not(:disabled) {
- background: var(--select-arrow),
- linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250));
+/* FIXME: :active isn't set when the