This is part of addressing issue #21 - non-US keyboard layouts. There are several challenges when dealing with keyboard events: - The meaning and use of keyCode, charCode and which depends on both the browser and the event type (keyDown/Up vs keyPress). - We cannot automatically determine the keyboard layout - The keyDown and keyUp events have a keyCode value that has not been translated by modifier keys. - The keyPress event has a translated (for layout and modifiers) character code but the attribute containing it differs. keyCode contains the translated value in WebKit (Chrome/Safari), Opera 11 and IE9. charCode contains the value in WebKit and Firefox. The which attribute contains the value on WebKit, Firefox and Opera 11. - The keyDown/Up keyCode value indicates (sort of) the physical key was pressed but only for standard US layout. On a US keyboard, the '-' and '_' characters are on the same key and generate a keyCode value of 189. But on an AZERTY keyboard even though they are different physical keys they both still generate a keyCode of 189! - To prevent a key event from propagating to the browser and causing unwanted default actions (such as closing a tab, opening a menu, shifting focus, etc) we must suppress this event in both keyDown and keyPress because not all key strokes generate on a keyPress event. Also, in WebKit and IE9 suppressing the keyDown prevents a keyPress but other browsers still generated a keyPress even if keyDown is suppressed. For safe key events, we wait until the keyPress event before reporting a key down event. For unsafe key events, we report a key down event when the keyDown event fires and we suppress any further actions (including keyPress). In order to report a key up event that matches what we reported for the key down event, we keep a list of keys that are currently down. When the keyDown event happens, we add the key event to the list. If it is a safe key event, then we update the which attribute in the most recent item on the list when we received a keyPress event (keyPress should immediately follow keyDown). When we received a keyUp event we search for the event on the list with a matching keyCode and we report the character code using the value in the 'which' attribute that was stored with that key. For character codes above 255 we use a character code to keysym lookup table. This is generated using the util/u2x11 script contributed by Colin Dean (xvpsource.org). |
||
---|---|---|
docs | ||
images | ||
include | ||
tests | ||
utils | ||
.gitignore | ||
LICENSE.txt | ||
README.md | ||
favicon.ico | ||
vnc.html | ||
vnc_auto.html |
README.md
noVNC: HTML5 VNC Client
Description
noVNC is a VNC client implemented using HTML5 technologies, specifically Canvas and WebSockets (supports 'wss://' encryption). noVNC is licensed under the LGPLv3.
Special thanks to Sentry Data Systems for sponsoring ongoing development of this project (and for employing me).
Notable commits, announcements and news are posted to @noVNC
Screenshots
Running in Chrome before and after connecting:
See more screenshots here.
Projects/Companies using noVNC
-
Sentry Data Systems: uses noVNC in the Datanex Cloud Computing Platform.
-
Ganeti Web Manager: Feature #1935.
-
openQRM: VNC plugin available by request. Probably included in version 4.8. Video demo.
-
OpenNode: uses noVNC in OpenNode Management Console. OMC Screencast.
Browser Requirements
-
HTML5 Canvas: Except for Internet Explorer, most browsers have had Canvas support for quite some time. Internet Explorer 9 will have Canvas support (finally).
-
HTML5 WebSockets: For browsers that do not have builtin WebSockets support, the project includes web-socket-js, a WebSockets emulator using Adobe Flash.
-
Fast Javascript Engine: noVNC avoids using new Javascript functionality so it will run on older browsers, but decode and rendering happen in Javascript, so a slow Javascript engine will mean noVNC is painfully slow.
-
I maintain a more detailed list of browser compatibility here.
Server Requirements
Unless you are using a VNC server with support for WebSockets connections (only my fork of libvncserver currently), you need to use a WebSockets to TCP socket proxy. There is a python proxy included ('websockify'). One advantage of using the proxy is that it has builtin support for SSL/TLS encryption (i.e. "wss://").
There a few reasons why a proxy is required:
-
WebSockets is not a pure socket protocol. There is an initial HTTP like handshake to allow easy hand-off by web servers and allow some origin policy exchange. Also, each WebSockets frame begins with 0 ('\x00') and ends with 255 ('\xff').
-
Javascript itself does not have the ability to handle pure byte arrays. The python proxy encodes the data as base64 so that the Javascript client can decode the data as an integer array.
Quick Start
-
Use the launch script to start a mini-webserver and the WebSockets proxy (websockify). The
--vnc
option is used to specify the location of a running VNC server:./utils/launch.sh --vnc localhost:5901
-
Point your browser to the cut-and-paste URL that is output by the launch script. Enter a password if the VNC server has one configured. Hit the Connect button and enjoy!
Other Pages
-
Advanced Usage. Generating an SSL certificate, starting a VNC server, advanced websockify usage, etc.
-
Integrating noVNC into existing projects.
-
Troubleshooting noVNC problems.