# Technical Documentation: kasmtech/KasmVNC > ℹ️ **Provenance:** Hybrid Fusion: `kasmtech/KasmVNC` (README + 4 In-Tree Chapters) · [CodeWiki Reference](https://codewiki.google/github.com/kasmtech/KasmVNC) · Recency: Active (< 180 days) ## 1. Project Overview & Quickstart (kasmtech/KasmVNC) # KasmVNC - Linux Web Remote Desktop KasmVNC provides remote web-based access to a Desktop or application. While VNC is in the name, KasmVNC differs from other VNC variants such as TigerVNC, RealVNC, and TurboVNC. KasmVNC has broken from the RFB specification which defines VNC, in order to support modern technologies and increase security. KasmVNC is accessed by users from any modern browser and does not support legacy VNC viewer applications. KasmVNC uses a modern YAML based configuration at the server and user level, allowing for ease of management. [Kasm Technologies](https://www.kasmweb.com) developed Kasm Workspaces, the Containerized Streaming Platform. Kasm has open-sourced the Workspace docker images, which include containerized [full desktops and apps](https://github.com/kasmtech/workspaces-images) and [base images](https://github.com/kasmtech/workspaces-core-images) intended for developers to create customized streaming containers. These containers can be used standalone or within the [Kasm Workspaces Platform](https://www.kasmweb.com) which provides a full Enterprise feature set. ## Documentation **Do not use the README from the master branch**, unless you are compiling KasmVNC yourself from the tip of master. Use the documentation for your specific release. - [KasmVNC Documentation](https://www.kasmweb.com/kasmvnc/docs/latest/index.html) For beta releases prior to version 1.0.0, use the README in this github project on the tagged commit for that release. ## Installation **You must disconnect and reconnect to the server after installation, for the group membership to apply.** ### Debian/Ubuntu/Kali ```sh # Please choose the package for your distro here (under Assets): # https://github.com/kasmtech/KasmVNC/releases wget sudo apt-get install ./kasmvncserver_*.deb # Add your user to the ssl-cert group sudo adduser $USER ssl-cert ``` ### Oracle 8 ```sh # Please choose the package for your distro here (under Assets): # https://github.com/kasmtech/KasmVNC/releases wget # Ensure KasmVNC dependencies are available sudo dnf config-manager --set-enabled ol8_codeready_builder sudo dnf install oracle-epel-release-el8 sudo dnf localinstall ./kasmvncserver_*.rpm # Add your user to the kasmvnc-cert group sudo usermod -a -G kasmvnc-cert $USER ``` ## Getting Started The following examples provide basic usage of KasmVNC with the tools provided. For full documentation on all the utilities and the runtime environment, see our [KasmVNC Documentation](https://www.kasmweb.com/kasmvnc/docs/latest/index.html) ```sh # Start a session and be guided to setup a user and select a default desktop environment vncserver # Start a session with the mate desktop environment vncserver -select-de mate # Add a new user with read/write permissions vncpasswd -u my_username -w -r # Tail the logs tail -f ~/.vnc/*.log # Get a list of current sessions with display IDs vncserver -list # Kill the VNC session with display ID :2 vncserver -kill :2 ``` ### Optional systemd auto-start on boot ```sh # Optionally use systemd to start KasmVNC on boot. sudo reboot # Needed for systemd to pick up $USER's ssl-cert or kasmvnc-cert group systemctl --user enable kasmvncserver@:1 # :1 is Xorg DISPLAY number. systemctl --user start kasmvncserver@:1 # You can run multiple KasmVNC instances via systemd by passing a different # DISPLAY number: # systemctl --user enable kasmvncserver@:2 # systemctl --user start kasmvncserver@:2 # systemctl --user enable kasmvncserver@:3 # systemctl --user start kasmvncserver@:3 ``` ## Configuration KasmVNC is configured via YAML based configurations. The server level configuration is at `/etc/kasmvnc/kasmvnc.yaml`. Edits to this file apply to all users. Individual users can override server global configurations by specifying them in their configuration file at `~/.vnc/kasmvnc.yaml`. The following configuration shows all default settings. Many of the encoding settings can be overridden by the client, unless the `runtime_configuration.allow_client_to_override_kasm_server_settings` setting is set tot false. By default the client is allowed to modify encoding settings. For a full description of each setting see the [configuration reference](https://www.kasmweb.com/kasmvnc/docs/latest/configuration.html). ``` /* Detailed source-code truncated for AI context efficiency. */ ``` # New Features! - Faster jpeg compression (via statically linked libjpeg-turbo) - Webp image compression for better bandwidth usage - Automatic mixing of webp and jpeg based on CPU availability on server - Multi-threaded image encoding for smoother frame rate for servers with more cores - WebCodecs video streaming with H.264, H.265, and AV1 support - WebRTC UDP Transit - Lossless QOI Image format for Local LAN - [Full screen video detection](https://github.com/kasmtech/KasmVNC/wiki/Video-Rendering-Options#video-mode), goes into configurable video mode for better full screen videoo playback performance. - [Dynamic jpeg/webp image coompression](https://github.com/kasmtech/KasmVNC/wiki/Video-Rendering-Options#dynamic-image-quality) quality settings based on screen change rates - Seemless clipboard support (on Chromium based browsers) - Binary clipboard support for text, images, and formatted text (on Chromium based browsers) - Allow client to set/change most configuration settings - [Data Loss Prevention features](https://github.com/kasmtech/KasmVNC/wiki/Data-Loss-Prevention) - Key stroke logging - Clipboard logging - Max clipboard transfer size up and down - Min time between clipboard operations required - Keyboard input rate limit - Screen region selection - Deb packages for Debian, Ubuntu, and Kali Linux included in release. - RPM packages for Oracle, OpenSUSE, Fedora. RPM packages are currently not updatable and not released, though you can build and install them. See build documentation. - Web [API](https://github.com/kasmtech/KasmVNC/wiki/API) added for remotely controlling and getting information from KasmVNC - Multi-User support with permissions that can be changed via the API - Web UI uses a webpack for faster load times. - Network and CPU bottleneck statistics - Relative cursor support (game pointer mode) - Cursor lock - IME support for languages with extended characters - Better mobile support - DRI3 GPU acceleration with open source drivers (AMDGPU,Intel,ATI,ARM) ### Compiling From Source See the [builder/README.md](https://github.com/kasmtech/KasmVNC/blob/master/builder/README.md). We containerize our build systems to ensure highly repeatable builds. ### License and Acknowledgements See the [LICENSE.TXT](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT) and [ACKNOWLEDGEMENTS.md](https://github.com/kasmtech/KasmVNC/blob/master/ACKNOWLEDGEMENTS.md) This project is tested with BrowserStack. ## 2. In-Tree Documentation Chapters (kasmtech/KasmVNC) ## File: README.md # KasmVNC - Linux Web Remote Desktop KasmVNC provides remote web-based access to a Desktop or application. While VNC is in the name, KasmVNC differs from other VNC variants such as TigerVNC, RealVNC, and TurboVNC. KasmVNC has broken from the RFB specification which defines VNC, in order to support modern technologies and increase security. KasmVNC is accessed by users from any modern browser and does not support legacy VNC viewer applications. KasmVNC uses a modern YAML based configuration at the server and user level, allowing for ease of management. [Kasm Technologies](https://www.kasmweb.com) developed Kasm Workspaces, the Containerized Streaming Platform. Kasm has open-sourced the Workspace docker images, which include containerized [full desktops and apps](https://github.com/kasmtech/workspaces-images) and [base images](https://github.com/kasmtech/workspaces-core-images) intended for developers to create customized streaming containers. These containers can be used standalone or within the [Kasm Workspaces Platform](https://www.kasmweb.com) which provides a full Enterprise feature set. ## Documentation **Do not use the README from the master branch**, unless you are compiling KasmVNC yourself from the tip of master. Use the documentation for your specific release. - [KasmVNC Documentation](https://www.kasmweb.com/kasmvnc/docs/latest/index.html) For beta releases prior to version 1.0.0, use the README in this github project on the tagged commit for that release. ## Installation **You must disconnect and reconnect to the server after installation, for the group membership to apply.** ### Debian/Ubuntu/Kali ```sh # Please choose the package for your distro here (under Assets): # https://github.com/kasmtech/KasmVNC/releases wget sudo apt-get install ./kasmvncserver_*.deb # Add your user to the ssl-cert group sudo adduser $USER ssl-cert ``` ### Oracle 8 ```sh # Please choose the package for your distro here (under Assets): # https://github.com/kasmtech/KasmVNC/releases wget # Ensure KasmVNC dependencies are available sudo dnf config-manager --set-enabled ol8_codeready_builder sudo dnf install oracle-epel-release-el8 sudo dnf localinstall ./kasmvncserver_*.rpm # Add your user to the kasmvnc-cert group sudo usermod -a -G kasmvnc-cert $USER ``` ## Getting Started The following examples provide basic usage of KasmVNC with the tools provided. For full documentation on all the utilities and the runtime environment, see our [KasmVNC Documentation](https://www.kasmweb.com/kasmvnc/docs/latest/index.html) ```sh # Start a session and be guided to setup a user and select a default desktop environment vncserver # Start a session with the mate desktop environment vncserver -select-de mate # Add a new user with read/write permissions vncpasswd -u my_username -w -r # Tail the logs tail -f ~/.vnc/*.log # Get a list of current sessions with display IDs vncserver -list # Kill the VNC session with display ID :2 vncserver -kill :2 ``` ### Optional systemd auto-start on boot ```sh # Optionally use systemd to start KasmVNC on boot. sudo reboot # Needed for systemd to pick up $USER's ssl-cert or kasmvnc-cert group systemctl --user enable kasmvncserver@:1 # :1 is Xorg DISPLAY number. systemctl --user start kasmvncserver@:1 # You can run multiple KasmVNC instances via systemd by passing a different # DISPLAY number: # systemctl --user enable kasmvncserver@:2 # systemctl --user start kasmvncserver@:2 # systemctl --user enable kasmvncserver@:3 # systemctl --user start kasmvncserver@:3 ``` ## Configuration KasmVNC is configured via YAML based configurations. The server level configuration is at `/etc/kasmvnc/kasmvnc.yaml`. Edits to this file apply to all users. Individual users can override server global configurations by specifying them in their configuration file at `~/.vnc/kasmvnc.yaml`. The following configuration shows all default settings. Many of the encoding settings can be overridden by the client, unless the `runtime_configuration.allow_client_to_override_kasm_server_settings` setting is set tot false. By default the client is allowed to modify encoding settings. For a full description of each setting see the [configuration reference](https://www.kasmweb.com/kasmvnc/docs/latest/configuration.html). ``` /* Detailed source-code truncated for AI context efficiency. */ ``` # New Features! - Faster jpeg compression (via statically linked libjpeg-turbo) - Webp image compression for better bandwidth usage - Automatic mixing of webp and jpeg based on CPU availability on server - Multi-threaded image encoding for smoother frame rate for servers with more cores - WebCodecs video streaming with H.264, H.265, and AV1 support - WebRTC UDP Transit - Lossless QOI Image format for Local LAN - [Full screen video detection](https://github.com/kasmtech/KasmVNC/wiki/Video-Rendering-Options#video-mode), goes into configurable video mode for better full screen videoo playback performance. - [Dynamic jpeg/webp image coompression](https://github.com/kasmtech/KasmVNC/wiki/Video-Rendering-Options#dynamic-image-quality) quality settings based on screen change rates - Seemless clipboard support (on Chromium based browsers) - Binary clipboard support for text, images, and formatted text (on Chromium based browsers) - Allow client to set/change most configuration settings - [Data Loss Prevention features](https://github.com/kasmtech/KasmVNC/wiki/Data-Loss-Prevention) - Key stroke logging - Clipboard logging - Max clipboard transfer size up and down - Min time between clipboard operations required - Keyboard input rate limit - Screen region selection - Deb packages for Debian, Ubuntu, and Kali Linux included in release. - RPM packages for Oracle, OpenSUSE, Fedora. RPM packages are currently not updatable and not released, though you can build and install them. See build documentation. - Web [API](https://github.com/kasmtech/KasmVNC/wiki/API) added for remotely controlling and getting information from KasmVNC - Multi-User support with permissions that can be changed via the API - Web UI uses a webpack for faster load times. - Network and CPU bottleneck statistics - Relative cursor support (game pointer mode) - Cursor lock - IME support for languages with extended characters - Better mobile support - DRI3 GPU acceleration with open source drivers (AMDGPU,Intel,ATI,ARM) ### Compiling From Source See the [builder/README.md](https://github.com/kasmtech/KasmVNC/blob/master/builder/README.md). We containerize our build systems to ensure highly repeatable builds. ### License and Acknowledgements See the [LICENSE.TXT](https://github.com/kasmtech/KasmVNC/blob/master/LICENSE.TXT) and [ACKNOWLEDGEMENTS.md](https://github.com/kasmtech/KasmVNC/blob/master/ACKNOWLEDGEMENTS.md) This project is tested with BrowserStack. --- ## File: builder/README.md ## REQIUREMENTS Docker CE # Build a deb/rpm package ``` # builder/build-package # os_codename is what "lsb_release -c" outputs, e.g. buster, focal. # # build_tag allows building multiple versions of deb package (rpm not supported) # targeting a single distro release (e.g. Ubuntu Focal). If build_tag is given, # the package name will include build_tag as part of Debian revision. For # example: # * with build_tag: kasmvncserver_0.9.1~beta-1+libjpeg-turbo-latest_amd64.deb # * without build_tag: kasmvncserver_0.9.1~beta-1_amd64.deb # You need to have .build and .deb.build for the build_tag. # # Packages will be placed under builder/build/ builder/build-package ubuntu focal builder/build-package debian buster builder/build-package debian bullseye builder/build-package kali kali-rolling builder/build-package fedora thirtythree ``` # Build an apk package ## Requirements Building an apk package requires a signing key to be present in environment. For example: ```sh KASMVNC_ALPINE_PRIVATE_KEY=$(cat <`` from any X Window System installation. Some other common keys are: =================== =================================================== Key name Keysym value =================== =================================================== BackSpace 0xff08 Tab 0xff09 Return or Enter 0xff0d Escape 0xff1b Insert 0xff63 Delete 0xffff Home 0xff50 End 0xff57 Page Up 0xff55 Page Down 0xff56 Left 0xff51 Up 0xff52 Right 0xff53 Down 0xff54 F1 0xffbe F2 0xffbf F3 0xffc0 F4 0xffc1 ... ... F12 0xffc9 Shift (left) 0xffe1 Shift (right) 0xffe2 Control (left) 0xffe3 Control (right) 0xffe4 Meta (left) 0xffe7 Meta (right) 0xffe8 Alt (left) 0xffe9 Alt (right) 0xffea =================== =================================================== The interpretation of keysyms is a complex area. In order to be as widely interoperable as possible the following guidelines should be used: - The "shift state" (i.e. whether either of the Shift keysyms are down) should only be used as a hint when interpreting a keysym. For example, on a US keyboard the '#' character is shifted, but on a UK keyboard it is not. A server with a US keyboard receiving a '#' character from a client with a UK keyboard will not have been sent any shift presses. In this case, it is likely that the server will internally need to "fake" a shift press on its local system, in order to get a '#' character and not, for example, a '3'. - The difference between upper and lower case keysyms is significant. This is unlike some of the keyboard processing in the X Window System which treats them as the same. For example, a server receiving an uppercase 'A' keysym without any shift presses should interpret it as an uppercase 'A'. Again this may involve an internal "fake" shift press. - Servers should ignore "lock" keysyms such as CapsLock and NumLock where possible. Instead they should interpret each character-based keysym according to its case. Note that some applications directly examine the state of CapsLock and NumLock and an extension such as `QEMU LED State Pseudo-encoding`_ or `VMware LED State Pseudo-encoding`_ could be needed for correct behaviour. - Unlike Shift, the state of modifier keys such as Control and Alt should be taken as modifying the interpretation of other keysyms. Note that there are no keysyms for ASCII control characters such as ctrl-a; these should be generated by viewers sending a Control press followed by an 'a' press. - On a viewer where modifiers like Control and Alt can also be used to generate character-based keysyms, the viewer may need to send extra "release" events in order that the keysym is interpreted correctly. For example, on a German PC keyboard on Windows, ctrl-alt-q generates the '@' character. In this case, the viewer needs to send "fake" release events for Control and Alt in order that the '@' character is interpreted correctly (ctrl-alt-@ is likely to mean something completely different to the server). - There is no universal standard for "backward tab" in the X Window System. On some systems shift+tab gives the keysym "ISO Left Tab", on others it gives a private "BackTab" keysym and on others it gives "Tab" and applications tell from the shift state that it means backward-tab rather than forward-tab. In the RFB protocol the latter approach is preferred. Viewers should generate a shifted Tab rather than ISO Left Tab. However, to be backwards-compatible with existing viewers, servers should also recognise ISO Left Tab as meaning a shifted Tab. Note that extensions such as `QEMU Extended Key Event Message`_ provide alternative behaviours for keyboard events that do not follow what is described here. PointerEvent ------------ Indicates either pointer movement or a pointer button press or release. The pointer is now at (*x-position*, *y-position*), and the current state of buttons 1 to 8 are represented by bits 0 to 7 of *button-mask* respectively, 0 meaning up, 1 meaning down (pressed). On a conventional mouse, buttons 1, 2 and 3 correspond to the left, middle and right buttons on the mouse. On a wheel mouse, each step of the wheel is represented by a press and release of a certain button. Button 4 means up, button 5 means down, button 6 means left and button 7 means right. Some pointer devices support additional buttons. Button 8 is typically the back button and button 9 is typically the forward button. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 5 *message-type* 1 ``U16`` *button-mask* 2 ``U16`` *x-position* 2 ``U16`` *y-position* =============== ==================== ========== ======================= The `QEMU Pointer Motion Change Pseudo-encoding`_ allows for the negotiation of an alternative interpretation for the *x-position* and *y-position* fields, as relative deltas. ClientCutText ------------- The client has new ISO 8859-1 (Latin-1) text in its cut buffer. Ends of lines are represented by the linefeed / newline character (value 10) alone. No carriage-return (value 13) is needed. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 6 *message-type* 3 *padding* 4 ``U32`` *length* *length* ``U8`` array *text* =============== ==================== ========== ======================= See also `Extended Clipboard Pseudo-Encoding`_ which modifies the behaviour of this message. EnableContinuousUpdates ----------------------- This message informs the server to switch between only sending `FramebufferUpdate`_ messages as a result of a `FramebufferUpdateRequest`_ message, or sending ``FramebufferUpdate`` messages continuously. The client must establish that the server supports this message before sending it. The client can do so using either the `Tight Security Type`_ authentication, or using the `ContinuousUpdates Pseudo-encoding`_. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 150 *message-type* 1 ``U8`` *enable-flag* 2 ``U16`` *x-position* 2 ``U16`` *y-position* 2 ``U16`` *width* 2 ``U16`` *height* =============== ==================== ========== ======================= If *enable-flag* is non-zero, then the server can start sending ``FramebufferUpdate`` messages as needed for the area specified by *x-position*, *y-position*, *width*, and *height*. If continuous updates are already active, then they must remain active and the coordinates must be replaced with the last message seen. If *enable-flag* is zero, then the server must only send ``FramebufferUpdate`` messages as a result of receiving ``FramebufferUpdateRequest`` messages. The server must also immediately send out a `EndOfContinuousUpdates`_ message. This message must be sent out even if continuous updates were already disabled. The server must ignore all incremental update requests (``FramebufferUpdateRequest`` with *incremental* set to non-zero) as long as continuous updates are active. Non-incremental update requests must however be honored, even if the area in such a request does not overlap the area specified for continuous updates. ClientFence ----------- A client supporting the *Fence* extension sends this to request a synchronisation of the data stream. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 248 *message-type* 3 *padding* 4 ``U32`` *flags* 1 ``U8`` *length* *length* ``U8`` array *payload* =============== ==================== ========== ======================= The *flags* byte informs the server if this is a new request, or a response to a server request sent earlier, as well as what kind of synchronisation that is desired. The server should not delay the response more than necessary, even if the synchronisation requirements would allow it. =============== ======================================================= Bit Description =============== ======================================================= 0 **BlockBefore** 1 **BlockAfter** 2 **SyncNext** 3-30 Currently unused 31 **Request** =============== ======================================================= The server should respond with a `ServerFence`_ with the **Request** bit cleared, as well as clearing any bits it does not understand. The remaining bits should remain set in the response. This allows the client to determine which flags the server supports when new ones are defined in the future. **BlockBefore** All messages preceding this one must have finished processing and taken effect before the response is sent. Messages following this one are unaffected and may be processed in any order the protocol permits, even before the response is sent. **BlockAfter** All messages following this one must not start processing until the response is sent. Messages preceding this one are unaffected and may be processed in any order the protocol permits, even being delayed until after the response is sent. **SyncNext** The message following this one must be executed in an atomic manner so that anything preceding the fence response **must not** be affected by the message, and anything following the fence response **must** be affected by the message. Anything unaffected by the following message can be sent at any time the protocol permits. The primary purpose of this synchronisation is to allow safe usage of stream altering commands such as `SetPixelFormat`_, which would impose strict ordering on `FramebufferUpdate`_ messages even with asynchrounous extensions such as the `ContinuousUpdates Pseudo-encoding`_. If **BlockAfter** is also set then the interaction between the two flags can be ambiguous. In this case we relax the requirement for **BlockAfter** and allow the following message (the one made atomic by **SyncNext**) to be processed before a response is sent. All messages after that first one are still subjected to the semantics of **BlockAfter** however. The behaviour will be similar to the following series of messages: 1. *ClientFence* with **SyncNext** 2. *message made atomic* 3. *ClientFence* with **BlockAfter** **Request** Indicates that this is a new request and that a response is expected. If this bit is cleared then this message is a response to an earlier request. The client can also include a chunk of data to differentiate between responses and to avoid keeping state. This data is specified using *length* and *payload*. The size of this data is limited to 64 bytes in order to minimise the disturbance to highly parallel clients and servers. xvp Client Message ------------------ A client supporting the *xvp* extension sends this to request that the server initiate a clean shutdown, clean reboot or abrupt reset of the system whose framebuffer the client is displaying. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 250 *message-type* 1 *padding* 1 ``U8`` 1 *xvp-extension-version* 1 ``U8`` *xvp-message-code* =============== ==================== ========== ======================= The possible values for *xvp-message-code* are: 2 - XVP_SHUTDOWN, 3 - XVP_REBOOT, and 4 - XVP_RESET. The client must have already established that the server supports this extension, by requesting the `xvp Pseudo-encoding`_. SetDesktopSize -------------- Requests a change of desktop size. This message is an extension and may only be sent if the client has previously received an *ExtendedDesktopSize* rectangle. This message also enables clients to handle configuration of a multi head screen layout within the framebuffer extents, as described in `Screen Model`_. The server must send an *ExtendedDesktopSize* rectangle for every *SetDesktopSize* message received. Several rectangles may be sent in a single *FramebufferUpdate* message, but the rectangles must not be merged or reordered in any way. Note that rectangles sent for other reasons may be interleaved with the ones generated as a result of *SetDesktopSize* messages. Upon a successful request the server must send an *ExtendedDesktopSize* rectangle to the requesting client with the exact same information the client provided in the corresponding *SetDesktopSize* message. *x-position* must be set to 1, indicating a client initiated event, and *y-position* must be set to 0, indicating success. The server must also send an *ExtendedDesktopSize* rectangle to all other connected clients, but with *x-position* set to 2, indicating a change initiated by another client. If the server can not or will not satisfy the request, it must send an *ExtendedDesktopSize* rectangle to the requesting client with *x-position* set to 1 and *y-position* set to the relevant error code. All remaining fields are undefined, although the basic structure must still be followed. The server must not send an *ExtendedDesktopSize* rectangle to any other connected clients. All *ExtendedDesktopSize* rectangles that are sent as a result of a *SetDesktopSize* message should be sent as soon as possible. ======================== ================= ======= ==================== No. of bytes Type [Value] Description ======================== ================= ======= ==================== 1 ``U8`` 251 *message-type* 1 *padding* 2 ``U16`` *width* 2 ``U16`` *height* 1 ``U8`` *number-of-screens* 1 *padding* *number-of-screens* * 16 ``SCREEN`` array *screens* ======================== ================= ======= ==================== The *width* and *height* indicates the framebuffer size requested. This structure is followed by *number-of-screens* number of ``SCREEN`` structures, which is defined in `ExtendedDesktopSize Pseudo-encoding`_: =============== =============================== ======================= No. of bytes Type Description =============== =============================== ======================= 4 ``U32`` *id* 2 ``U16`` *x-position* 2 ``U16`` *y-position* 2 ``U16`` *width* 2 ``U16`` *height* 4 ``U32`` *flags* =============== =============================== ======================= The *id* field must be preserved upon modification as it determines the difference between a moved screen and a newly created one. The client should make every effort to preserve the fields it does not wish to modify, including any unknown *flags* bits. gii Client Message ------------------ This message is an extension and may only be sent if the client has previously received a `gii Server Message`_ confirming that the server supports the General Input Interface extension. Version ~~~~~~~ The client response to a *gii* Version message from the server is the following response: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 253 *message-type* 1 ``U8`` 1 or 129 *endian-and-sub-type* 2 ``EU16`` 2 *length* 2 ``EU16`` 1 *version* =============== ==================== ========== ======================= *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. *version* is set by the client and ultimately decides the version of *gii* protocol extension to use. It should be in the range given by the server in the *gii* Version message. If the server doesn't support any version that the client supports, the client should instead stop using the *gii* extension at this point. Device Creation ~~~~~~~~~~~~~~~ After establishing the *gii* protocol extension version, the client proceeds by requesting creation of one or more devices. ===================== =============== ========================== ====================== No. of bytes Type [Value] Description ===================== =============== ========================== ====================== 1 ``U8`` 253 *message-type* 1 ``U8`` 2 or 130 *endian-and-sub-type* 2 ``EU16`` 56 + *num-valuators* * 116 *length* 31 ``U8`` array *device-name* 1 ``U8`` 0 *nul-terminator* 4 ``EU32`` *vendor-id* 4 ``EU32`` *product-id* 4 ``EVENT_MASK`` *can-generate* 4 ``EU32`` *num-registers* 4 ``EU32`` *num-valuators* 4 ``EU32`` *num-buttons* *num-valuators* * 116 ``VALUATOR`` ===================== =============== ========================== ====================== *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. ``EVENT_MASK`` is a bit-field indicating which events the device can generate. ============= ========================================================= Value Bit name ============= ========================================================= 0x00000020 Key press 0x00000040 Key release 0x00000080 Key repeat 0x00000100 Pointer relative 0x00000200 Pointer absolute 0x00000400 Pointer button press 0x00000800 Pointer button release 0x00001000 Valuator relative 0x00002000 Valuator absolute ============= ========================================================= and ``VALUATOR`` is =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 4 ``EU32`` *index* 74 ``U8`` array *long-name* 1 ``U8`` 0 *nul-terminator* 4 ``U8`` array *short-name* 1 ``U8`` 0 *nul-terminator* 4 ``ES32`` *range-min* 4 ``ES32`` *range-center* 4 ``ES32`` *range-max* 4 ``EU32`` *SI-unit* 4 ``ES32`` *SI-add* 4 ``ES32`` *SI-mul* 4 ``ES32`` *SI-div* 4 ``ES32`` *SI-shift* =============== ==================== ========== ======================= The *SI-unit* field is defined as: ========= ==================== ======================================== Number SI-unit Description ========= ==================== ======================================== 0 unknown 1 s time 2 1/s frequency 3 m length 4 m/s velocity 5 m/s^2 acceleration 6 rad angle 7 rad/s angular velocity 8 rad/s^2 angular acceleration 9 m^2 area 10 m^3 volume 11 kg mass 12 N (kg*m/s^2) force 13 N/m^2 (Pa) pressure 14 Nm torque 15 Nm, VAs, J energy 16 Nm/s, VA, W power 17 K temperature 18 A current 19 V (kg*m^2/(As^3)) voltage 20 V/A (Ohm) resistance 21 As/V capacity 22 Vs/A inductivity ========= ==================== ======================================== The *SI-add*, *SI-mul*, *SI-div* and *SI-shift* fields of the ``VALUATOR`` indicate how the raw value should be translated to the SI-unit using the below formula. float SI = (float) (SI_add + value[n]) * (float) SI_mul / (float) SI_div * pow(2.0, SI_shift); Setting *SI-mul* to zero indicates that the valuator is non-linear or that the factor is unknown. Device Destruction ~~~~~~~~~~~~~~~~~~ The client can destroy a device with a device destruct message. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 253 *message-type* 1 ``U8`` 3 or 131 *endian-and-sub-type* 2 ``EU16`` 4 *length* 4 ``EU32`` *device-origin* =============== ==================== ========== ======================= *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. *device-origin* is the handle retrieved with a prior device creation request. Injecting Events ~~~~~~~~~~~~~~~~ =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 253 *message-type* 1 ``U8`` 0 or 128 *endian-and-sub-type* 2 ``EU16`` *length* =============== ==================== ========== ======================= followed by *length* bytes of ``EVENT`` entries *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. ``EVENT`` is one of ``KEY_EVENT``, ``PTR_MOVE_EVENT``, ``PTR_BUTTON_EVENT`` and ``VALUATOR_EVENT``. ``KEY_EVENT`` is: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 24 *event-size* 1 ``U8`` 5, 6 or 7 *event-type* 2 ``EU16`` *padding* 4 ``EU32`` *device-origin* 4 ``EU32`` *modifiers* 4 ``EU32`` *symbol* 4 ``EU32`` *label* 4 ``EU32`` *button* =============== ==================== ========== ======================= The possible values for *event-type* are: 5 - key pressed, 6 - key released and 7 - key repeat. XXX describe *modifiers*, *symbol*, *label* and *button*. Meanwhile, see http://www.ggi-project.org/documentation/libgii/current/gii_key_event.3.html for details. *device-origin* is the handle retrieved with a prior device creation request. ``PTR_MOVE_EVENT`` is: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 24 *event-size* 1 ``U8`` 8 or 9 *event-type* 2 ``EU16`` *padding* 4 ``EU32`` *device-origin* 4 ``ES32`` *x* 4 ``ES32`` *y* 4 ``ES32`` *z* 4 ``ES32`` *wheel* =============== ==================== ========== ======================= The possible values for *event-type* are: 8 - pointer relative and 9 - pointer absolute. *device-origin* is the handle retrieved with a prior device creation request. ``PTR_BUTTON_EVENT`` is: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 12 *event-size* 1 ``U8`` 10 or 11 *event-type* 2 ``EU16`` *padding* 4 ``EU32`` *device-origin* 4 ``EU32`` *button-number* =============== ==================== ========== ======================= The possible values for *event-type* are: 10 - pointer button press and 11 - pointer button release. *device-origin* is the handle retrieved with a prior device creation request. *button-number* 1 is the primary or left button, *button-number* 2 is the secondary or right button and *button-number* 3 is the tertiary or middle button. Other values for *button-number* are also valid. ``VALUATOR_EVENT`` is: =============== ================= ================== ================== No. of bytes Type [Value] Description =============== ================= ================== ================== 1 ``U8`` 16 + 4 * *count* *event-size* 1 ``U8`` 12 or 13 *event-type* 2 ``EU16`` *padding* 4 ``EU32`` *device-origin* 4 ``EU32`` *first* 4 ``EU32`` *count* 4 * *count* ``ES32`` array *value* =============== ================= ================== ================== The possible values for *event-type* are: 12 - relative valuator and 13 - absolute valuator. *device-origin* is the handle retrieved with a prior device creation request. The event reports *count* valuators starting with *first*. QEMU Client Message ------------------- This message may only be sent if the client has previously received a *FrameBufferUpdate* that confirms support for the intended *submessage-type*. Every ``QEMU Client Message`` begins with a standard header =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` *submessage-type* =============== ==================== ========== ======================= This header is then followed by arbitrary data whose format is determined by the *submessage-type*. Possible values for *submessage-type* and their associated pseudo encodings are ================ ================ ==================== Submessage Type Pseudo Encoding Description ================ ================ ==================== 0 -258 Extended key events 1 -259 Audio ================ ================ ==================== QEMU Extended Key Event Message ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This submessage allows the client to send an extended key event containing a keycode, in addition to a keysym. The advantage of providing the keycode is that it enables the server to interpret the key event independently of the clients' locale specific keymap. This can be important for virtual desktops whose key input device requires scancodes, for example, virtual machines emulating a PS/2 keycode. Prior to this extension, RFB servers for such virtualization software would have to be configured with a keymap matching the client. With this extension it is sufficient for the guest operating system to be configured with the matching keymap. The VNC server is keymap independent. The full message is: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 0 *submessage-type* 2 ``U16`` *down-flag* 4 ``U32`` *keysym* 4 ``U32`` *keycode* =============== ==================== ========== ======================= The *keysym* and *down-flag* fields also take the same values as described for the `KeyEvent`_ message. Auto repeating behaviour of keys is also as described for the `KeyEvent`_ message. The *keycode* is the XT keycode that produced the *keysym*. An XT keycode is an XT make scancode sequence encoded to fit in a single ``U32`` quantity. Single byte XT scancodes with a byte value less than 0x7f are encoded as is. 2-byte XT scancodes whose first byte is 0xe0 and second byte is less than 0x7f are encoded with the high bit of the first byte set. Some example mappings are ============= ================== ============ ========== XT scancode X11 keysym RFB keycode down-flag ============= ================== ============ ========== 0x1e XK_A (0x41) 0x1e 1 0x9e XK_A (0x41) 0x1e 0 0xe0 0x4d XK_Right (0xff53) 0xcd 1 0xe0 0xcd XK_Right (0xff53) 0xcd 0 ============= ================== ============ ========== The multi-byte scancode sequence for the Print/SysRq key SHOULD be sent as 0x54, regardless of what modifier keys are currently pressed. For backwards compatibility servers SHOULD also accept 0xb7 as a synonym for 0x54. The multi-byte scancode sequence for the Pause/Break key MUST be sent as 0xc6, regardless of what modifier keys are currently pressed. An unknown keysym should have the value 0. The client must not send a QEMU Extended Key Event Message if the keycode isn't known. Instead a standard `KeyEvent`_ message should be used. QEMU Audio Client Message ~~~~~~~~~~~~~~~~~~~~~~~~~ This submessage allows the client to control how the audio data stream is received. There are three operations that can be invoked with this submessage, the payload varies according to which operation is requested. The first operation enables audio capture from the server: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 0 *operation* =============== ==================== ========== ======================= After invoking this operation, the client will receive a `QEMU Audio Server Message`_ when an audio stream begins. The second operation is the inverse, to disable audio capture on the server: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 1 *operation* =============== ==================== ========== ======================= Due to inherant race conditions in the protocol, after invoking this operation, the client may still receive further `QEMU Audio Server Message`_ messages for a short time. The third and final operation is to set the audio sample format. This should be set before audio capture is enabled on the server, otherwise the client will not be able to reliably interpret the receiving audio buffers: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 2 *operation* 1 ``U8`` *sample-format* 1 ``U8`` *nchannels* 4 ``U32`` *frequency* =============== ==================== ========== ======================= The *sample-format* field must take one of the following values, and this describes the number of bytes that each sample will consume: ====== ============= ======= Value No. of bytes Type ====== ============= ======= 0 1 ``U8`` 1 1 ``S8`` 2 2 ``U16`` 3 2 ``S16`` 4 4 ``U32`` 5 4 ``S32`` ====== ============= ======= The *nchannels* field must be either ``1`` (mono) or ``2`` (stereo). Server to Client Messages +++++++++++++++++++++++++ The server to client message types that all clients must support are: =========== =========================================================== Number Name =========== =========================================================== 0 `FramebufferUpdate`_ 1 `SetColourMapEntries`_ 2 `Bell`_ 3 `ServerCutText`_ =========== =========================================================== Optional message types are: =========== =========================================================== Number Name =========== =========================================================== 4 ResizeFrameBuffer 5 KeyFrameUpdate 6 Possibly used in UltraVNC 7 FileTransfer 8-10 Possibly used in UltraVNC 11 TextChat 12 Possibly used in UltraVNC 13 KeepAlive 14 Possibly used in UltraVNC 15 ResizeFrameBuffer 127 VMware 128 Car Connectivity 150 `EndOfContinuousUpdates`_ 173 ServerState 178 Kasm stats 179 Kasm frame stats 180 Kasm binary clipboard 248 `ServerFence`_ 249 OLIVE Call Control 250 `xvp Server Message`_ 252 tight 253 `gii Server Message`_ 254 VMware 255 `QEMU Server Message`_ =========== =========================================================== The official, up-to-date list is maintained by IANA [#reg]_. Note that before sending a message with an optional message type a server must have determined that the client supports the relevant extension by receiving some extension-specific confirmation from the client; usually a request for a given pseudo-encoding. FramebufferUpdate ----------------- A framebuffer update consists of a sequence of rectangles of pixel data which the client should put into its framebuffer. It is sent in response to a *FramebufferUpdateRequest* from the client. Note that there may be an indefinite period between the *FramebufferUpdateRequest* and the *FramebufferUpdate*. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 0 *message-type* 1 *padding* 2 ``U16`` *number-of-rectangles* =============== ==================== ========== ======================= This is followed by *number-of-rectangles* rectangles of pixel data. Each rectangle consists of: =============== =============================== ======================= No. of bytes Type Description =============== =============================== ======================= 2 ``U16`` *x-position* 2 ``U16`` *y-position* 2 ``U16`` *width* 2 ``U16`` *height* 4 ``S32`` *encoding-type* =============== =============================== ======================= followed by the pixel data in the specified encoding. See `Encodings`_ for the format of the data for each encoding and `Pseudo-encodings`_ for the meaning of pseudo-encodings. Note that a framebuffer update marks a transition from one valid framebuffer state to another. That means that a single update handles all received *FramebufferUpdateRequest* up to the point where the update is sent out. However, because there is no strong connection between a *FramebufferUpdateRequest* and a subsequent *FramebufferUpdate*, a client that has more than one *FramebufferUpdateRequest* pending at any given time cannot be sure that it has received all framebuffer updates. See the `LastRect Pseudo-encoding`_ for an extension to this message. SetColourMapEntries ------------------- When the pixel format uses a "colour map", this message tells the client that the specified pixel values should be mapped to the given RGB intensities. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 1 *message-type* 1 *padding* 2 ``U16`` *first-colour* 2 ``U16`` *number-of-colours* =============== ==================== ========== ======================= followed by *number-of-colours* repetitions of the following: =============== =============================== ======================= No. of bytes Type Description =============== =============================== ======================= 2 ``U16`` *red* 2 ``U16`` *green* 2 ``U16`` *blue* =============== =============================== ======================= Bell ---- Ring a bell on the client if it has one. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 2 *message-type* =============== ==================== ========== ======================= ServerCutText ------------- The server has new ISO 8859-1 (Latin-1) text in its cut buffer. Ends of lines are represented by the linefeed / newline character (value 10) alone. No carriage-return (value 13) is needed. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 3 *message-type* 3 *padding* 4 ``U32`` *length* *length* ``U8`` array *text* =============== ==================== ========== ======================= See also `Extended Clipboard Pseudo-Encoding`_ which modifies the behaviour of this message. EndOfContinuousUpdates ---------------------- This message is sent whenever the server sees a `EnableContinuousUpdates`_ message with *enable* set to a non-zero value. It indicates that the server has stopped sending continuous updates and is now only reacting to `FramebufferUpdateRequest`_ messages. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 150 *message-type* =============== ==================== ========== ======================= ServerFence ----------- A server supporting the *Fence* extension sends this to request a synchronisation of the data stream. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 248 *message-type* 3 *padding* 4 ``U32`` *flags* 1 ``U8`` *length* *length* ``U8`` array *payload* =============== ==================== ========== ======================= The format and semantics is identical to `ClientFence`_, but with the roles of the client and server reversed. xvp Server Message ------------------ This has the following format: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 250 *message-type* 1 *padding* 1 ``U8`` 1 *xvp-extension-version* 1 ``U8`` *xvp-message-code* =============== ==================== ========== ======================= The possible values for *xvp-message-code* are: 0 - XVP_FAIL and 1 - XVP_INIT. A server which supports the *xvp* extension declares this by sending a message with an XVP_INIT *xvp-message-code* when it receives a request from the client to use the `xvp Pseudo-encoding`_. The server must specify in this message the highest *xvp-extension-version* it supports: the client may assume that the server supports all versions from 1 up to this value. The client is then free to use any supported version. Currently, only version 1 is defined. A server which subsequently receives an `xvp Client Message`_ requesting an operation which it is unable to perform, informs the client of this by sending a message with an XVP_FAIL *xvp-message-code*, and the same *xvp-extension-version* as included in the client's operation request. gii Server Message ------------------ This message is an extension and may only be sent if the server has previously received a `SetEncodings`_ message confirming that the client supports the General Input Interface extension via the `gii Pseudo-encoding`_. Version ~~~~~~~ The server response from a server with *gii* capabilities to a client declaring *gii* capabilities is a *gii* version message: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 253 *message-type* 1 ``SUB_TYPE`` 1 or 129 *endian-and-sub-type* 2 ``EU16`` 4 *length* 2 ``EU16`` 1 *maximum-version* 2 ``EU16`` 1 *minimum-version* =============== ==================== ========== ======================= *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. Device Creation Response ~~~~~~~~~~~~~~~~~~~~~~~~ The server response to a *gii* Device Creation request from the client is the following response: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 253 *message-type* 1 ``SUB_TYPE`` 2 or 130 *endian-and-sub-type* 2 ``EU16`` 4 *length* 4 ``EU32`` *device-origin* =============== ==================== ========== ======================= *endian-and-sub-type* is a bit-field with the leftmost bit indicating big endian if set, and little endian if cleared. The rest of the bits are the actual message sub type. *device-origin* is used as a handle to the device in subsequent communications. A *device-origin* of zero indicates device creation failure. QEMU Server Message ------------------- This message may only be sent if the client has previously received a *FrameBufferUpdate* that confirms support for the intended *submessage-type*. Every ``QEMU Server Message`` begins with a standard header =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` *submessage-type* =============== ==================== ========== ======================= This header is then followed by arbitrary data whose format is determined by the *submessage-type*. Possible values for *submessage-type* and their associated pseudo encodings are ================ ================ ==================== Submessage Type Pseudo Encoding Description ================ ================ ==================== 1 -259 Audio ================ ================ ==================== Submessage type 0 is unused, since the `QEMU Extended Key Event Pseudo-encoding`_ does not require any server messages. QEMU Audio Server Message ~~~~~~~~~~~~~~~~~~~~~~~~~ This submessage allows the server to send an audio data stream to the client. There are three operations that can be invoked with this submessage, the payload varies according to which operation is requested. The first operation informs the client that an audio stream is about to start =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 1 *operation* =============== ==================== ========== ======================= The second operation informs the client that an audio stream has now finished: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 0 *operation* =============== ==================== ========== ======================= The third and final operation is to provide audio data. =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 255 *message-type* 1 ``U8`` 1 *submessage-type* 2 ``U16`` 2 *operation* 4 ``U32`` *data-length* *data-length* ``U8`` array *data* =============== ==================== ========== ======================= The *data-length* will be a multiple of (*sample-format* * *nchannels*) as requested by the client in an earlier `QEMU Audio Client Message`_. Encodings +++++++++ The encodings defined in this document are: ============ ========================================================== Number Name ============ ========================================================== 0 `Raw Encoding`_ 1 `CopyRect Encoding`_ 2 `RRE Encoding`_ 4 `CoRRE Encoding`_ 5 `Hextile Encoding`_ 6 `zlib Encoding`_ 7 `Tight Encoding`_ 8 `zlibhex Encoding`_ 16 `ZRLE Encoding`_ 21 `JPEG Encoding`_ 50 `Open H.264 Encoding`_ -260 `Tight PNG Encoding`_ ============ ========================================================== The pseudo-encodings defined in this document are: ============ ========================================================== Number Name ============ ========================================================== -23 to -32 `JPEG Quality Level Pseudo-encoding`_ -223 `DesktopSize Pseudo-encoding`_ -224 `LastRect Pseudo-encoding`_ -239 `Cursor Pseudo-encoding`_ -240 `X Cursor Pseudo-encoding`_ -247 to -256 `Compression Level Pseudo-encoding`_ -257 `QEMU Pointer Motion Change Pseudo-encoding`_ -258 `QEMU Extended Key Event Pseudo-encoding`_ -259 `QEMU Audio Pseudo-encoding`_ -261 `QEMU LED State Pseudo-encoding`_ -305 `gii Pseudo-encoding`_ -307 `DesktopName Pseudo-encoding`_ -308 `ExtendedDesktopSize Pseudo-encoding`_ -309 `xvp Pseudo-encoding`_ -312 `Fence Pseudo-encoding`_ -313 `ContinuousUpdates Pseudo-encoding`_ -314 `Cursor With Alpha Pseudo-encoding`_ -412 to -512 `JPEG Fine-Grained Quality Level Pseudo-encoding`_ -763 to -768 `JPEG Subsampling Level Pseudo-encoding`_ 0x574d5664 `VMware Cursor Pseudo-encoding`_ 0x574d5665 `VMware Cursor State Pseudo-encoding`_ 0x574d5666 `VMware Cursor Position Pseudo-encoding`_ 0x574d5667 `VMware Key Repeat Pseudo-encoding`_ 0x574d5668 `VMware LED state Pseudo-encoding`_ 0x574d5669 `VMware Display Mode Change Pseudo-encoding`_ 0x574d566a `VMware Virtual Machine State Pseudo-encoding`_ 0xc0a1e5ce `Extended Clipboard Pseudo-encoding`_ ============ ========================================================== Other registered encodings are: =========================== =========================================== Number Name =========================== =========================================== 9 Ultra 10 Ultra2 15 TRLE 17 Hitachi ZYWRLE 20 H.264 22 JRLE 1000 to 1002 Apple Inc. 1011 Apple Inc. 1024 to 1099 RealVNC 1100 to 1105 Apple Inc. -1 to -22 Tight options -33 to -218 Tight options -219 to -222 Historical libVNCServer use -225 PointerPos -226 to -238 Tight options -241 to -246 Tight options -262 to -272 QEMU -273 to -304 VMware -306 popa -310 OLIVE Call Control -311 ClientRedirect -523 to -528 Car Connectivity 0x48323634 VA H.264 0x574d5600 to 0x574d56ff VMware 0xc0a1e5cf PluginStreaming 0xfffe0000 KeyboardLedState 0xfffe0001 SupportedMessages 0xfffe0002 SupportedEncodings 0xfffe0003 ServerIdentity 0xfffe0004 to 0xfffe00ff libVNSServer 0xffff0000 Cache 0xffff0001 CacheEnable 0xffff0002 XOR zlib 0xffff0003 XORMonoRect zlib 0xffff0004 XORMultiColor zlib 0xffff0005 SolidColor 0xffff0006 XOREnable 0xffff0007 CacheZip 0xffff0008 SolMonoZip 0xffff0009 UltraZip 0xffff8000 ServerState 0xffff8001 EnableKeepAlive 0xffff8002 FTProtocolVersion 0xffff8003 Session =========================== =========================================== The official, up-to-date list is maintained by IANA [#reg]_. Raw Encoding ------------ The simplest encoding type is raw pixel data. In this case the data consists of *width* * *height* pixel values (where *width* and *height* are the width and height of the rectangle). The values simply represent each pixel in left-to-right scanline order. All RFB clients must be able to cope with pixel data in this raw encoding, and RFB servers should only produce raw encoding unless the client specifically asks for some other encoding type. ======================================= =================== =========== No. of bytes Type Description ======================================= =================== =========== *width* * *height* * *bytesPerPixel* ``PIXEL`` array *pixels* ======================================= =================== =========== CopyRect Encoding ----------------- The *CopyRect* (copy rectangle) encoding is a very simple and efficient encoding which can be used when the client already has the same pixel data elsewhere in its framebuffer. The encoding on the wire simply consists of an X,Y coordinate. This gives a position in the framebuffer from which the client can copy the rectangle of pixel data. This can be used in a variety of situations, the most obvious of which are when the user moves a window across the screen, and when the contents of a window are scrolled. A less obvious use is for optimising drawing of text or other repeating patterns. An intelligent server may be able to send a pattern explicitly only once, and knowing the previous position of the pattern in the framebuffer, send subsequent occurrences of the same pattern using the *CopyRect* encoding. =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 2 ``U16`` *src-x-position* 2 ``U16`` *src-y-position* =============== =================== =================================== RRE Encoding ------------ RRE stands for *rise-and-run-length encoding* and as its name implies, it is essentially a two-dimensional analogue of run-length encoding. RRE-encoded rectangles arrive at the client in a form which can be rendered immediately and efficiently by the simplest of graphics engines. RRE is not appropriate for complex desktops, but can be useful in some situations. The basic idea behind RRE is the partitioning of a rectangle of pixel data into rectangular subregions (subrectangles) each of which consists of pixels of a single value and the union of which comprises the original rectangular region. The near-optimal partition of a given rectangle into such subrectangles is relatively easy to compute. The encoding consists of a background pixel value, *Vb* (typically the most prevalent pixel value in the rectangle) and a count *N*, followed by a list of *N* subrectangles, each of which consists of a tuple <*v*, *x*, *y*, *w*, *h*> where *v* (!= *Vb*) is the pixel value, (*x*, *y*) are the coordinates of the subrectangle relative to the top-left corner of the rectangle, and (*w*, *h*) are the width and height of the subrectangle. The client can render the original rectangle by drawing a filled rectangle of the background pixel value and then drawing a filled rectangle corresponding to each subrectangle. On the wire, the data begins with the header: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 4 ``U32`` *number-of-subrectangles* *bytesPerPixel* ``PIXEL`` *background-pixel-value* =============== =================== =================================== This is followed by *number-of-subrectangles* instances of the following structure: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== *bytesPerPixel* ``PIXEL`` *subrect-pixel-value* 2 ``U16`` *x-position* 2 ``U16`` *y-position* 2 ``U16`` *width* 2 ``U16`` *height* =============== =================== =================================== CoRRE Encoding -------------- CoRRE stands for *compressed rise-and-run-length encoding* and as its name implies, it is a variant of the above `RRE Encoding`_ and as such essentially a two-dimensional analogue of run-length encoding. The only difference between CoRRE and RRE is that the position, width and height of the subrectangles are limited to a maximum of 255 pixels. Because of this, the server needs to produce several rectangles in order to cover a larger area. The `Hextile Encoding`_ is probably a better choice in the majority of cases. On the wire, the data begins with the header: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 4 ``U32`` *number-of-subrectangles* *bytesPerPixel* ``PIXEL`` *background-pixel-value* =============== =================== =================================== This is followed by *number-of-subrectangles* instances of the following structure: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== *bytesPerPixel* ``PIXEL`` *subrect-pixel-value* 1 ``U8`` *x-position* 1 ``U8`` *y-position* 1 ``U8`` *width* 1 ``U8`` *height* =============== =================== =================================== Hextile Encoding ---------------- Hextile is a variation on the RRE idea. Rectangles are split up into 16x16 tiles, allowing the dimensions of the subrectangles to be specified in 4 bits each, 16 bits in total. The rectangle is split into tiles starting at the top left going in left-to-right, top-to-bottom order. The encoded contents of the tiles simply follow one another in the predetermined order. If the width of the whole rectangle is not an exact multiple of 16 then the width of the last tile in each row will be correspondingly smaller. Similarly if the height of the whole rectangle is not an exact multiple of 16 then the height of each tile in the final row will also be smaller. Each tile is either encoded as raw pixel data, or as a variation on RRE. Each tile has a background pixel value, as before. The background pixel value does not need to be explicitly specified for a given tile if it is the same as the background of the previous tile. However the background pixel value may not be carried over if the previous tile was raw. If all of the subrectangles of a tile have the same pixel value, this can be specified once as a foreground pixel value for the whole tile. As with the background, the foreground pixel value can be left unspecified, meaning it is carried over from the previous tile. The foreground pixel value may not be carried over if the previous tile was raw or had the SubrectsColored bit set. It may, however, be carried over from a previous tile with the AnySubrects bit clear, as long as that tile itself carried over a valid foreground from its previous tile. So the data consists of each tile encoded in order. Each tile begins with a subencoding type byte, which is a mask made up of a number of bits: =============== ======= =========== =================================== No. of bytes Type [Value] Description =============== ======= =========== =================================== 1 ``U8`` *subencoding-mask*: .. 1 **Raw** .. 2 **BackgroundSpecified** .. 4 **ForegroundSpecified** .. 8 **AnySubrects** .. 16 **SubrectsColoured** =============== ======= =========== =================================== If the **Raw** bit is set then the other bits are irrelevant; *width* * *height* pixel values follow (where *width* and *height* are the width and height of the tile). Otherwise the other bits in the mask are as follows: **BackgroundSpecified** If set, a pixel value follows which specifies the background colour for this tile: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== *bytesPerPixel* ``PIXEL`` *background-pixel-value* ========================== ============= ========================== The first non-raw tile in a rectangle must have this bit set. If this bit isn't set then the background is the same as the last tile. **ForegroundSpecified** If set, a pixel value follows which specifies the foreground colour to be used for all subrectangles in this tile: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== *bytesPerPixel* ``PIXEL`` *foreground-pixel-value* ========================== ============= ========================== If this bit is set then the **SubrectsColoured** bit must be zero. **AnySubrects** If set, a single byte follows giving the number of subrectangles following: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== 1 ``U8`` *number-of-subrectangles* ========================== ============= ========================== If not set, there are no subrectangles (i.e. the whole tile is just solid background colour). **SubrectsColoured** If set then each subrectangle is preceded by a pixel value giving the colour of that subrectangle, so a subrectangle is: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== *bytesPerPixel* ``PIXEL`` *subrect-pixel-value* 1 ``U8`` *x-and-y-position* 1 ``U8`` *width-and-height* ========================== ============= ========================== If not set, all subrectangles are the same colour, the foreground colour; if the **ForegroundSpecified** bit wasn't set then the foreground is the same as the last tile. A subrectangle is: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== 1 ``U8`` *x-and-y-position* 1 ``U8`` *width-and-height* ========================== ============= ========================== The position and size of each subrectangle is specified in two bytes, *x-and-y-position* and *width-and-height*. The most-significant four bits of *x-and-y-position* specify the X position, the least-significant specify the Y position. The most-significant four bits of *width-and-height* specify the width minus one, the least-significant specify the height minus one. zlib Encoding ------------- The zlib encoding uses zlib [#zlib]_ to compress rectangles encoded according to the `Raw Encoding`_. A single zlib "stream" object is used for a given RFB connection, so that zlib rectangles must be encoded and decoded strictly in order. .. [#zlib] see http://www.gzip.org/zlib/ =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 4 ``U32`` *length* *length* ``U8`` array *zlibData* =============== =================== =================================== The *zlibData*, when uncompressed, represents a rectangle according to the `Raw Encoding`_. Tight Encoding -------------- Tight encoding provides efficient compression for pixel data. To reduce implementation complexity, the width of any Tight-encoded rectangle cannot exceed 2048 pixels. If a wider rectangle is desired, it must be split into several rectangles and each one should be encoded separately. The first byte of each Tight-encoded rectangle is a *compression-control* byte: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 1 ``U8`` *compression-control* =============== =================== =================================== The least significant four bits of the *compression-control* byte inform the client which zlib compression streams should be reset before decoding the rectangle. Each bit is independent and corresponds to a separate zlib stream that should be reset: ================== ==================================================== Bit Description ================== ==================================================== 0 Reset stream 0 1 Reset stream 1 2 Reset stream 2 3 Reset stream 3 ================== ==================================================== One of three possible compression methods are supported in the Tight encoding. These are **BasicCompression**, **FillCompression** and **JpegCompression**. If the bit 7 (the most significant bit) of the *compression-control* byte is 0, then the compression type is **BasicCompression**. In that case, bits 7-4 (the most significant four bits) of *compression-control* should be interpreted as follows: =============== =================== =================================== Bits Binary value Description =============== =================== =================================== 5-4 00 Use stream 0 .. 01 Use stream 1 .. 10 Use stream 2 .. 11 Use stream 3 6 0 --- .. 1 *read-filter-id* 7 0 **BasicCompression** =============== =================== =================================== Otherwise, if the bit 7 of *compression-control* is set to 1, then the compression method is either **FillCompression**, **JpegCompression**, or Kasm-specific depending on other bits of the same byte: =============== =================== =================================== Bits Binary value Description =============== =================== =================================== 7-4 1000 **FillCompression** .. 1001 **JpegCompression** .. 1011 **WebpCompression** .. any other Invalid =============== =================== =================================== Note: **JpegCompression** may only be used when *bits-per-pixel* is either 16 or 32 and the client has advertized a quality level using the `JPEG Quality Level Pseudo-encoding`_. The Tight encoding makes use of a new type ``TPIXEL`` (Tight pixel). This is the same as a ``PIXEL`` for the agreed pixel format, except where *true-colour-flag* is non-zero, *bits-per-pixel* is 32, *depth* is 24 and all of the bits making up the red, green and blue intensities are exactly 8 bits wide. In this case a ``TPIXEL`` is only 3 bytes long, where the first byte is the red component, the second byte is the green component, and the third byte is the blue component of the pixel color value. The data following the *compression-control* byte depends on the compression method. **FillCompression** If the compression type is **FillCompression**, then the only pixel value follows, in ``TPIXEL`` format. This value applies to all pixels of the rectangle. **JpegCompression** If the compression type is **JpegCompression**, the following data stream looks like this: =============== ================ ================================== No. of bytes Type Description =============== ================ ================================== 1-3 *length* in compact representation *length* ``U8`` array *jpeg-data* =============== ================ ================================== *length* is compactly represented in one, two or three bytes, according to the following scheme: =========================== ======================================= Value Description =========================== ======================================= 0xxxxxxx for values 0..127 1xxxxxxx 0yyyyyyy for values 128..16383 1xxxxxxx 1yyyyyyy zzzzzzzz for values 16384..4194303 =========================== ======================================= Here each character denotes one bit, xxxxxxx are the least significant 7 bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the most significant 8 bits (bits 14-21). For example, decimal value 10000 should be represented as two bytes: binary 10010000 01001110, or hexadecimal 90 4E. The *jpeg-data* is a JFIF stream. **BasicCompression** If the compression type is **BasicCompression** and bit 6 (the *read-filter-id* bit) of the *compression-control* byte was set to 1, then the next (second) byte specifies *filter-id* which tells the decoder what filter type was used by the encoder to pre-process pixel data before the compression. The *filter-id* byte can be one of the following: =============== ========= ======== ================================ No. of bytes Type [Value] Description =============== ========= ======== ================================ 1 ``U8`` *filter-id* .. 0 **CopyFilter** (no filter) .. 1 **PaletteFilter** .. 2 **GradientFilter** =============== ========= ======== ================================ If bit 6 of the *compression-control* byte is set to 0 (no *filter-id* byte), then the **CopyFilter** is used. **CopyFilter** When the **CopyFilter** is active, raw pixel values in ``TPIXEL`` format will be compressed. See below for details on the compression. **PaletteFilter** The **PaletteFilter** converts true-color pixel data to indexed colors and a palette which can consist of 2..256 colors. If the number of colors is 2, then each pixel is encoded in 1 bit, otherwise 8 bits are used to encode one pixel. 1-bit encoding is performed such way that the most significant bits correspond to the leftmost pixels, and each row of pixels is aligned to the byte boundary. When the **PaletteFilter** is used, the palette is sent before the pixel data. The palette begins with an unsigned byte which value is the number of colors in the palette minus 1 (i.e. 1 means 2 colors, 255 means 256 colors in the palette). Then follows the palette itself which consist of pixel values in ``TPIXEL`` format. **GradientFilter** The **GradientFilter** pre-processes pixel data with a simple algorithm which converts each color component to a difference between a "predicted" intensity and the actual intensity. Such a technique does not affect uncompressed data size, but helps to compress photo-like images better. Pseudo-code for converting intensities to differences follows:: P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; if (P[i,j] < 0) then P[i,j] := 0; if (P[i,j] > MAX) then P[i,j] := MAX; D[i,j] := V[i,j] - P[i,j]; Here ``V[i,j]`` is the intensity of a color component for a pixel at coordinates ``(i,j)``. For pixels outside the current rectangle, ``V[i,j]`` is assumed to be zero (which is relevant for ``P[i,0]`` and ``P[0,j]``). MAX is the maximum intensity value for a color component. Note: The **GradientFilter** may only be used when *bits-per-pixel* is either 16 or 32. After the pixel data has been filtered with one of the above three filters, it is compressed using the zlib library. But if the data size after applying the filter but before the compression is less then 12, then the data is sent as is, uncompressed. Four separate zlib streams (0..3) can be used and the decoder should read the actual stream id from the *compression-control* byte (see [NOTE1]_). If the compression is not used, then the pixel data is sent as is, otherwise the data stream looks like this: =============== ================ ================================== No. of bytes Type Description =============== ================ ================================== 1-3 *length* in compact representation *length* ``U8`` array *zlibData* =============== ================ ================================== *length* is compactly represented in one, two or three bytes, just like in the **JpegCompression** method (see above). .. [NOTE1] The decoder must reset the zlib streams before decoding the rectangle, if some of the bits 0, 1, 2 and 3 in the *compression-control* byte are set to 1. Note that the decoder must reset the indicated zlib streams even if the compression type is **FillCompression** or **JpegCompression**. zlibhex Encoding ---------------- The zlibhex encoding uses zlib [#zlib]_ to optionally compress subrectangles according to the `Hextile Encoding`_. Refer to the hextile encoding for information on how the rectangle is divided into subrectangles and other basic properties of subrectangles. One zlib "stream" object is used for subrectangles encoded according to the **Raw** subencoding and one zlib "stream" object is used for all other subrectangles. The hextile subencoding bitfield is extended with these bits: =============== ======= =========== =================================== No. of bytes Type [Value] Description =============== ======= =========== =================================== 1 ``U8`` *subencoding-mask*: .. 32 **ZlibRaw** .. 64 **Zlib** =============== ======= =========== =================================== If either of the **ZlibRaw** or the **Zlib** bit is set, the subrectangle is compressed using zlib, like this: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 2 ``U16`` *length* *length* ``U8`` array *zlibData* =============== =================== =================================== Like the **Raw** bit in hextile, the **ZlibRaw** bit in zlibhex cancels all other bits and the subrectangle is encoded using the first zlib "stream" object. The *zlibData*, when uncompressed, should in this case be interpreted as the **Raw** data in the hextile encoding. If the **Zlib** bit is set, the rectangle is encoded using the second zlib "stream" object. The *zlibData*, when uncompressed, represents a plain hextile rectangle according to the lower 5 bits in the subencoding. If neither the **ZlibRaw** nor the **Zlib** bit is set, the subrectangle follows the rules described in the `Hextile Encoding`_. ZRLE Encoding ------------- ZRLE stands for Zlib [#zlib]_ Run-Length Encoding, and combines zlib compression, tiling, palettisation and run-length encoding. On the wire, the rectangle begins with a 4-byte length field, and is followed by that many bytes of zlib-compressed data. A single zlib "stream" object is used for a given RFB protocol connection, so that ZRLE rectangles must be encoded and decoded strictly in order. =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 4 ``U32`` *length* *length* ``U8`` array *zlibData* =============== =================== =================================== The *zlibData* when uncompressed represents tiles of 64x64 pixels in left-to-right, top-to-bottom order, similar to hextile. If the width of the rectangle is not an exact multiple of 64 then the width of the last tile in each row is smaller, and if the height of the rectangle is not an exact multiple of 64 then the height of each tile in the final row is smaller. ZRLE makes use of a new type ``CPIXEL`` (compressed pixel). This is the same as a ``PIXEL`` for the agreed pixel format, except where *true-colour-flag* is non-zero, *bits-per-pixel* is 32, *depth* is 24 or less and all of the bits making up the red, green and blue intensities fit in either the least significant 3 bytes or the most significant 3 bytes. In this case a ``CPIXEL`` is only 3 bytes long, and contains the least significant or the most significant 3 bytes as appropriate. *bytesPerCPixel* is the number of bytes in a ``CPIXEL``. Note that for the corner case where *bits-per-pixel* is 32 and *depth* is 16 or less (this is a corner case, since the client is **much** better off using 16 or even 8 *bits-per-pixels*) a ``CPIXEL`` is still 3 bytes long. By convention, the three least significant bytes are used when both the three least and the three most significant bytes would cover the used bits. Each tile begins with a *subencoding* type byte. The top bit of this byte is set if the tile has been run-length encoded, clear otherwise. The bottom seven bits indicate the size of the palette used: zero means no palette, one means that the tile is of a single colour, 2 to 127 indicate a palette of that size. The possible values of *subencoding* are: 0 Raw pixel data. *width* * *height* pixel values follow (where width and height are the width and height of the tile): ====================================== ================ =========== No. of bytes Type Description ====================================== ================ =========== *width* * *height* * *bytesPerCPixel* ``CPIXEL`` array *pixels* ====================================== ================ =========== 1 A solid tile consisting of a single colour. The pixel value follows: ========================== ============= ========================== No. of bytes Type Description ========================== ============= ========================== *bytesPerCPixel* ``CPIXEL`` *pixelValue* ========================== ============= ========================== 2 to 16 Packed palette types. Followed by the palette, consisting of *paletteSize* (=*subencoding*) pixel values. Then the packed pixels follow, each pixel represented as a bit field yielding an index into the palette (0 meaning the first palette entry). For *paletteSize* 2, a 1-bit field is used, for *paletteSize* 3 or 4 a 2-bit field is used and for *paletteSize* from 5 to 16 a 4-bit field is used. The bit fields are packed into bytes, the most significant bits representing the leftmost pixel (i.e. big endian). For tiles not a multiple of 8, 4 or 2 pixels wide (as appropriate), padding bits are used to align each row to an exact number of bytes. ================================= ================== ============== No. of bytes Type Description ================================= ================== ============== *paletteSize* * *bytesPerCPixel* ``CPIXEL`` array *palette* *m* ``U8`` array *packedPixels* ================================= ================== ============== where *m* is the number of bytes representing the packed pixels. For *paletteSize* of 2 this is floor((*width* + 7) / 8) * *height*, for *paletteSize* of 3 or 4 this is floor((*width* + 3) / 4) * *height*, for *paletteSize* of 5 to 16 this is floor((*width* + 1) / 2) * *height*. 17 to 127 Unused (no advantage over palette RLE). 128 Plain RLE. Consists of a number of runs, repeated until the tile is done. Runs may continue from the end of one row to the beginning of the next. Each run is a represented by a single pixel value followed by the length of the run. The length is represented as one or more bytes. The length is calculated as one more than the sum of all the bytes representing the length. Any byte value other than 255 indicates the final byte. So for example length 1 is represented as [0], 255 as [254], 256 as [255,0], 257 as [255,1], 510 as [255,254], 511 as [255,255,0] and so on. =================== =============== ======= ======================= No. of bytes Type [Value] Description =================== =============== ======= ======================= *bytesPerCPixel* ``CPIXEL`` *pixelValue* *r* ``U8`` array 255 1 ``U8`` (*runLength* - 1) % 255 =================== =============== ======= ======================= Where *r* is floor((*runLength* - 1) / 255). 129 Unused. 130 to 255 Palette RLE. Followed by the palette, consisting of *paletteSize* = (*subencoding* - 128) pixel values: ================================= ================== ============== No. of bytes Type Description ================================= ================== ============== *paletteSize* * *bytesPerCPixel* ``CPIXEL`` array *palette* ================================= ================== ============== Then as with plain RLE, consists of a number of runs, repeated until the tile is done. A run of length one is represented simply by a palette index: ================================= ================== ============== No. of bytes Type Description ================================= ================== ============== 1 ``U8`` *paletteIndex* ================================= ================== ============== A run of length more than one is represented by a palette index with the top bit set, followed by the length of the run as for plain RLE. =================== =============== ======= ======================= No. of bytes Type [Value] Description =================== =============== ======= ======================= 1 ``U8`` *paletteIndex* + 128 *r* ``U8`` array 255 1 ``U8`` (*runLength* - 1) % 255 =================== =============== ======= ======================= Where *r* is floor((*runLength* - 1) / 255). JPEG Encoding ------------- The JPEG encoding uses JPEG format to compress rects. The message is simply a JPEG image: =============== ================ ====================================== No. of bytes Type Description =============== ================ ====================================== variable ``U8`` array *data* =============== ================ ====================================== As defined in the JPEG standard, a JPEG image consists of a sequence of segments, each of which begins with a marker. The EOF marker indicates the end of the message. When the segments of "Define Huffman Tables (DHT)" or "Define Quantization Tables (DQT)" do not exist, the client should reuse the previous Huffman tables or quantization tables for decoding. Open H.264 Encoding ------------------- The Open H.264 Encoding implements the widely used H.264 format for efficient rectangle compression for transmission over poor communication channels. The message looks like this: =============== ================ ================================== No. of bytes Type Description =============== ================ ================================== 4 ``U32`` *length* of *data* 4 ``U32`` *flags* *length* ``U8`` array *data* =============== ================ ================================== The *flags* is used by the server to send additional information to the client. The current values of the *flags* are listed below. Unknown flag values should be ignored by the client. =============== =================================================== Bit Description =============== =================================================== 0 **ResetContext** 1 **ResetAllContexts** 2-31 Currently unused =============== =================================================== The *data* is one or more H.264 frames glued together in a row. This encoding prescribes the use of the H.264 baseline profile for the lowest latency. Since H.264 is a differential format, this introduces the concept of context for RFB frame. The context is the state of the H.264 encoder/decoder associated with a particular rectangle. When the server wants to send an H.264 rectangle, the *rect* coordinates and size inside a *FrameBufferUpdate* will be used to find the decoder context in the client. If the client finds a suitable decoder that can be used for the specified coordinates, the client uses it (and its internal state) to decode and display the new frame. The client should only decode frames based on the internal state of the context and ignore changes in the output buffer that may occur when overlapping of rects. When new data is received, the client context will redraw its rectangle and update the previously overlapped data. The server can use the *flags* to control the contexts of the client. All currently existing flags must be applied before decoding. The **ResetContext** flag requires the client to delete the current context with coordinates specified in *FrameBufferUpdate* and create a new one. The **ResetAllContexts** flag deletes all client contexts. The server can send an empty *data* and *length* equal to zero, in which case the client must interpret this *FramebufferUpdate* as a control message and apply the *flags*. The server can send multiple frames in a single *data*, which must be parsed as a regular H.264 stream. The server is unable to split frames into multiple packets. The *data* field must always contain 0 or more whole frames. The client must first decode all the received frames in a single message, and then display the result. The server must start sending *data* for the new context from I-frame to provide correct decoding for the client side. The client can handle decoding errors at its discretion. However, the recommended processing method is to ignore and wait for the correct frame from the server side. The client must support 64 simultaneously contexts. The server must use a minimum number of contexts to ensure that a single screen works. Ideally, one context per screen. When trying to create a new context beyond 64, the client must destroy the oldest context, then create the new one. The oldest context is the one that has not received frame updates for the longest time. Tight PNG Encoding ------------------------- The Tight PNG encoding is a variant of the Tight encoding that disallows the **BasicCompression** type and replaces it with a new **PngCompression** type. The purpose of this encoding is to support clients which have efficient PNG decoding/rendering (perhaps even in hardware) but may have inefficient decoding of the raw zlib data contained in the **BasicCompression** type. The Tight PNG encoding is identical to the Tight encoding except that bit 7-4 of the *compression-control* byte indicate either **FillCompression**, **JpegCompression**, or **PngCompression** and are interpreted as follows: =============== =================== =================================== Bits Binary value Description =============== =================== =================================== 7-4 1000 **FillCompression** .. 1001 **JpegCompression** .. 1010 **PngCompression** .. any other Invalid =============== =================== =================================== **FillCompression** Identical to Tight encoding. **JpegCompression** Identical to Tight encoding. As with the Tight encoding, **JpegCompression** may only be used when *bits-per-pixel* is either 16 or 32 and the client has advertized a quality level using the `JPEG Quality Level Pseudo-encoding`_ **PngCompression** If the compression type is **PngCompression**, the data stream is the same as **JpegCompression** (as defined in the Tight encoding) except that the *jpeg-data* is replaced by *png-data* which is image data in the PNG (Portable Network Graphics) format. Pseudo-encodings ++++++++++++++++ JPEG Quality Level Pseudo-encoding ---------------------------------- Specifies the desired quality from the JPEG encoder. Encoding number -23 implies high JPEG quality and -32 implies low JPEG quality. Low quality can be useful in low bandwidth situations. If the JPEG quality level is not specified, **JpegCompression** is not used in the `Tight Encoding`_. The quality level concerns lossy compression and hence the setting is a tradeoff between image quality and bandwidth. The specification defines neither what bandwidth is required at a certain quality level nor what image quality you can expect. The quality level is also just a hint to the server. Cursor Pseudo-encoding ----------------------- A client which requests the *Cursor* pseudo-encoding is declaring that it is capable of drawing a mouse cursor locally. This can significantly improve perceived performance over slow links. The server sets the cursor shape by sending a pseudo-rectangle with the *Cursor* pseudo-encoding as part of an update. The pseudo-rectangle's *x-position* and *y-position* indicate the hotspot of the cursor, and *width* and *height* indicate the width and height of the cursor in pixels. The data consists of *width* * *height* pixel values followed by a bitmask. The bitmask consists of left-to-right, top-to-bottom scanlines, where each scanline is padded to a whole number of bytes floor((*width* + 7) / 8). Within each byte the most significant bit represents the leftmost pixel, with a 1-bit meaning the corresponding pixel in the cursor is valid. ====================================== ================ =============== No. of bytes Type Description ====================================== ================ =============== *width* * *height* * *bytesPerPixel* ``PIXEL`` array *cursor-pixels* floor((*width* + 7) / 8) * *height* ``U8`` array *bitmask* ====================================== ================ =============== X Cursor Pseudo-encoding ------------------------ A client which requests the *X Cursor* pseudo-encoding is declaring that it is capable of drawing a mouse cursor locally. This can significantly improve perceived performance over slow links. The server sets the cursor shape by sending a pseudo-rectangle with the *X Cursor* pseudo-encoding as part of an update. The pseudo-rectangle's *x-position* and *y-position* indicate the hotspot of the cursor, and *width* and *height* indicate the width and height of the cursor in pixels. If either *width* or *height* is zero then there is no data associated with the pseudo-rectangle. Otherwise the data consists of the primary and secondary colours for the cursor, followed by one bitmap for the colour and one bitmask for the transparency. The bitmap and bitmask both consist of left-to-right, top-to-bottom scanlines, where each scanline is padded to a whole number of bytes floor((*width* + 7) / 8). Within each byte the most significant bit represents the leftmost pixel, with a 1-bit meaning the corresponding pixel should use the primary colour, or that the pixel is valid. ====================================== ================ =============== No. of bytes Type Description ====================================== ================ =============== 1 ``U8`` *primary-r* 1 ``U8`` *primary-g* 1 ``U8`` *primary-b* 1 ``U8`` *secondary-r* 1 ``U8`` *secondary-g* 1 ``U8`` *secondary-b* floor((*width* + 7) / 8) * *height* ``U8`` array *bitmap* floor((*width* + 7) / 8) * *height* ``U8`` array *bitmask* ====================================== ================ =============== DesktopSize Pseudo-encoding --------------------------- A client which requests the *DesktopSize* pseudo-encoding is declaring that it is capable of coping with a change in the framebuffer width and/or height. The server changes the desktop size by sending a pseudo-rectangle with the *DesktopSize* pseudo-encoding. The pseudo-rectangle's *x-position* and *y-position* are ignored, and *width* and *height* indicate the new width and height of the framebuffer. There is no further data associated with the pseudo-rectangle. The semantics of the *DesktopSize* pseudo-encoding were originally not clearly defined and as a results there are multiple differing implementations in the wild. Both the client and server need to take special steps to ensure maximum compatibility. In the initial implementation the *DesktopSize* pseudo-rectangle was sent in its own update without any modifications to the framebuffer data. The client would discard the framebuffer contents upon receiving this pseudo-rectangle and the server would consider the entire framebuffer to be modified. A later implementation sent the *DesktopSize* pseudo-rectangle together with modifications to the framebuffer data. It also expected the client to retain the framebuffer contents as those modifications could be from after the framebuffer resize had occurred on the server. The semantics defined here retain compatibility with both of two older implementations. Server Semantics ~~~~~~~~~~~~~~~~ The update containing the pseudo-rectangle should not contain any rectangles that change the framebuffer data as that will most likely be discarded by the client and will have to be resent later. The server should assume that the client discards the framebuffer data when receiving a *DesktopSize* pseudo-rectangle. It should therefore not use any encoding that relies on the previous contents of the framebuffer. The server should also consider the entire framebuffer to be modified. Some early client implementations require the *DesktopSize* pseudo-rectangle to be the very last rectangle in an update. Servers should make every effort to support these. The server should only send a *DesktopSize* pseudo-rectangle when an actual change of the framebuffer dimensions has occurred. Some clients respond to a *DesktopSize* pseudo-rectangle in a way that could send the system into an infinite loop if the server sent out the pseudo-rectangle for anything other than an actual change. Client Semantics ~~~~~~~~~~~~~~~~ The client should assume that the server expects the framebuffer data to be retained when the framebuffer dimensions change. This requirement can be satisfied either by actually retaining the framebuffer data, or by making sure that *incremental* is set to zero (false) in the next *FramebufferUpdateRequest*. The principle of one framebuffer update being a transition from one valid state to another does not hold for updates with the *DesktopSize* pseudo-rectangle as the framebuffer contents can temporarily be partially or completely undefined. Clients should try to handle this gracefully, e.g. by showing a black framebuffer or delay the screen update until a proper update of the framebuffer contents has been received. LastRect Pseudo-encoding ------------------------ A client which requests the *LastRect* pseudo-encoding is declaring that it does not need the exact number of rectangles in a *FramebufferUpdate* message. Instead, it will stop parsing when it reaches a *LastRect* rectangle. A server may thus start transmitting the *FramebufferUpdate* message before it knows exactly how many rectangles it is going to transmit, and the server typically advertises this situation by saying that it is going to send 65535 rectangles, but it then stops with a *LastRect* instead of sending all of them. There is no further data associated with the pseudo-rectangle. Compression Level Pseudo-encoding --------------------------------- Specifies the desired compression level. Encoding number -247 implies high compression level, -256 implies low compression level. Low compression level can be useful to get low latency in medium to high bandwidth situations and high compression level can be useful in low bandwidth situations. The compression level concerns the general tradeoff between CPU time and bandwidth. It is therefore probably difficult to define exact cut-off points for which compression levels should be used for any given bandwidth. The compression level is just a hint for the server, and there is no specification for what a specific compression level means. Most servers use this hint to control lossless compression algorithms as the tradeoff between CPU time and bandwidth is obvious there. However it can also be used for other algorithms where this tradeoff is relevant. QEMU Pointer Motion Change Pseudo-encoding ------------------------------------------ A client that supports this encoding declares that is able to send pointer motion events either as absolute coordinates, or relative deltas. The server can switch between different pointer motion modes by sending a rectangle with this encoding. If the *x-position* in the update is 1, the server is requesting absolute coordinates, which is the RFB protocol default when this encoding is not supported. If the *x-position* in the update is 0, the server is requesting relative deltas. When relative delta mode is active, the semantics of the `PointerEvent`_ message are changed. The *x-position* and *y-position* fields are to be treated as ``S16`` quantities, denoting the delta from the last position. A client can compute the signed deltas with the logic:: uint16 dx = x + 0x7FFF - last_x uint16 dy = y + 0x7FFF - last_y If the client needs to send an updated *button-mask* without any associated motion, it should use the value 0x7FFF in the *x-position* and *y-position* fields of the `PointerEvent`_ Servers are advised to implement this pseudo-encoding if the virtual desktop is associated a input device that expects relative coordinates, for example, a virtual machine with a PS/2 mouse. Prior to this extension, a server with such a input device would have to perform the absolute to relative delta conversion itself. This can result in the client pointer hitting an "invisible wall". Clients are advised that when generating events in relative pointer mode, they should grab and hide the local pointer. When the local pointer hits any edge of the client window, it should be warped back by 100 pixels. This ensures that continued movement of the user's input device will continue to generate relative deltas and thus avoid the "invisible wall" problem. QEMU Extended Key Event Pseudo-encoding --------------------------------------- A client that supports this encoding is indicating that it is able to provide raw keycodes as an alternative to keysyms. If a server wishes to receive raw keycodes it will send an empty pseudo-rectangle with the matching pseudo-encoding. After receiving this notification, clients may optionally use the `QEMU Extended Key Event Message`_ to send key events, in preference to the traditional `KeyEvent`_ message. QEMU Audio Pseudo-encoding -------------------------- A client that supports this encoding is indicating that it is able to receive an audio data stream. If a server wishes to send audio data it will send an empty pseudo-rectangle with the matching pseudo-encoding. After receiving this notification, clients may optionally use the `QEMU Audio Client Message`_. QEMU LED State Pseudo-encoding ------------------------------ A client that supports this encoding is indicating that it can toggle the state of lock keys on the local keyboard. The server will send a pseudo-rectangle with the following contents when it wishes to update the client's state: =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 1 ``U8`` *state* =============== =================== =================================== The bits of *state* are defined as: =============== ======================================================= Bit Description =============== ======================================================= 0 Scroll Lock 1 Num Lock 2 Caps Lock =============== ======================================================= The remaining bits are reserved and must be ignored. An update must be sent whenever the server state changes, but may also be sent at other times to compensate for variance in behaviour between the server and client keyboard handling. gii Pseudo-encoding ------------------- A client that supports the General Input Interface extension starts by requesting the *gii* pseudo-encoding declaring that it is capable of accepting the `gii Server Message`_. The server, in turn, declares that it is capable of accepting the `gii Client Message`_ by sending a `gii Server Message`_ of subtype *version*. Requesting the *gii* pseudo-encoding is the first step when a client wants to use the *gii* extension of the RFB protocol. The *gii* extension is used to provide a more powerful input protocol for cases where the standard input model is insufficient. It supports relative mouse movements, mouses with more than 8 buttons and mouses with more than three axes. It even supports joysticks and gamepads. DesktopName Pseudo-encoding --------------------------- A client which requests the DesktopName pseudo-encoding is declaring that it is capable of coping with a change of the desktop name. The server changes the desktop name by sending a pseudo-rectangle with the DesktopName pseudo-encoding in an update. The pseudo-rectangle's x-position, y-position, width, and height must be zero. After the rectangle header, a string with the new name follows. =============== =================== =================================== No. of bytes Type Description =============== =================== =================================== 4 ``U32`` *name-length* *name-length* ``U8`` array *name-string* =============== =================== =================================== The text encoding used for *name-string* is UTF-8. ExtendedDesktopSize Pseudo-encoding ----------------------------------- A client which requests the *ExtendedDesktopSize* pseudo-encoding is declaring that it is capable of coping with a change in the framebuffer width, height, and/or screen configuration. This encoding is used in conjunction with the *SetDesktopSize* message. If a server supports the *ExtendedDesktopSize* encoding, it must also have basic support for the *SetDesktopSize* message although it may deny all requests to change the screen layout. The *ExtendedDesktopSize* pseudo-encoding is designed to replace the simpler *DesktopSize* one. Servers and clients should support both for maximum compatibility, but a server must only send the extended version to a client asking for both. The semantics of *DesktopSize* are not as well-defined as for *ExtendedDesktopSize* and handling both at the same time would require needless complexity in the client. The server must send an *ExtendedDesktopSize* rectangle in response to a *FramebufferUpdateRequest* with *incremental* set to zero, assuming the client has requested the *ExtendedDesktopSize* pseudo-encoding using the *SetEncodings* message. This requirement is needed so that the client has a reliable way of fetching the initial screen configuration, and to determine if the server supports the *SetDesktopSize* message. A consequence of this is that a client must not respond to an *ExtendedDesktopSize* rectangle by sending a *FramebufferUpdateRequest* with *incremental* set to zero. Doing so would make the system go into an infinite loop. The server must also send an *ExtendedDesktopSize* rectangle in response to a *SetDesktopSize* message, indicating the result. For a full description of server behaviour as a result of the *SetDesktopSize* message, see `SetDesktopSize`_. Rectangles sent as a result of a *SetDesktopSize* message must be sent as soon as possible. Rectangles sent for other reasons may be subjected to delays imposed by the server. An update containing an *ExtendedDesktopSize* rectangle must not contain any changes to the framebuffer data, neither before nor after the *ExtendedDesktopSize* rectangle. The pseudo-rectangle's *x-position* indicates the reason for the change: 0 The screen layout was changed via non-RFB means on the server. For example the server may have provided means for server-side applications to manipulate the screen layout. This code is also used when the client sends a non-incremental *FrameBufferUpdateRequest* to learn the server's current state. 1 The client receiving this message requested a change of the screen layout. The change may or may not have happened depending on server policy or available resources. The status code in the *y-position* field must be used to determine which. 2 Another client requested a change of the screen layout and the server approved it. A rectangle with this code is never sent if the server denied the request. More reasons may be added in the future. Clients should treat an unknown value as a server-side change (i.e. as if *x-position* was set to zero). The pseudo-rectangle's *y-position* indicates the status code for a change requested by a client: ======= =============================================================== Code Description ======= =============================================================== 0 No error 1 Resize is administratively prohibited 2 Out of resources 3 Invalid screen layout 4 Request forwarded (might complete asyncronously) ======= =============================================================== This field shall be set to zero by the server and ignored by clients when not defined. Other error codes may be added in the future and clients must treat them as an unknown failure. The "Request forwarded" error code is used when the server is not in direct control of the screen layout and is unable to determine if the request will succeed or not. An example for this situation is a virtual machine monitor like qemu which can only forward the request to the guest, but it is in the hands of the guest to actually respond to the request. In case the request succeeds the server will send another *ExtendedDesktopSize* message. Note that there can be a longer delay and even continuous screen updates before the request succeeds, for example in case the request comes in while the guest is booting. The *width* and *height* indicates the new width and height of the framebuffer. The encoding data is defined as: =========================== =================== ======================= No. of bytes Type Description =========================== =================== ======================= 1 ``U8`` *number-of-screens* 3 *padding* *number-of-screens* * 16 ``SCREEN`` array *screens* =========================== =================== ======================= The *number-of-screens* field indicates the number of active screens and allows for multi head configurations. It also indicates how many ``SCREEN`` structures follow, which define the position and dimensions of heads within the framebuffer extents. The semantics of screens are defined in `Screen Model`_. The ``SCREEN`` structures are defined as: =============== =============================== ======================= No. of bytes Type Description =============== =============================== ======================= 4 ``U32`` *id* 2 ``U16`` *x-position* 2 ``U16`` *y-position* 2 ``U16`` *width* 2 ``U16`` *height* 4 ``U32`` *flags* =============== =============================== ======================= The *id* field contains an arbitrary value that the server and client can use to map RFB screens to physical screens. The value must be unique in the current set of screens and must be preserved for the lifetime of that RFB screen. New ids are assigned by whichever side creates the screen. An *id* may be reused if there has been a subsequent update of the screen layout where the *id* was not used. The *flags* field is currently unused. Clients and servers must ignore, but preserve, any bits it does not understand. For new screens, those bits must be set to zero. Note that a simple client which does not support multi head does not need to parse the list of screens and can simply display the entire framebuffer whose extents were given by the *width* and *height* field of the ``FramebufferUpdate`` message. xvp Pseudo-encoding ------------------- A client which requests the *xvp* pseudo-encoding is declaring that it wishes to use the *xvp* extension. If the server supports this, it replies with a message of type `xvp Server Message`_, using an *xvp-message-code* of *XVP_INIT*. This informs the client that it may then subsequently send messages of type `xvp Client Message`_. Fence Pseudo-encoding --------------------- A client which requests the *Fence* pseudo-encoding is declaring that it supports and/or wishes to use the *Fence* extension. The server should send a `ServerFence`_ the first time it sees a ``SetEncodings`` message with the *Fence* pseudo-encoding, in order to inform the client that this extension is supported. The message can use any flags or payload. ContinuousUpdates Pseudo-encoding --------------------------------- A client which requests the *ContinuousUpdates* pseudo-encoding is declaring that it wishes to use the `EnableContinuousUpdates`_ extension. The server must send a `EndOfContinuousUpdates`_ message the first time it sees a ``SetEncodings`` message with the *ContinuousUpdates* pseudo-encoding, in order to inform the client that the extension is supported. Cursor With Alpha Pseudo-encoding --------------------------------- A client which requests the *Cursor With Alpha* pseudo-encoding is declaring that it is capable of drawing a mouse cursor locally. This can significantly improve perceived performance over slow links. The server sets the cursor shape by sending a pseudo-rectangle with the *Cursor With Alpha* pseudo-encoding as part of an update. The pseudo-rectangle's *x-position* and *y-position* indicate the hotspot of the cursor, and *width* and *height* indicate the width and height of the cursor in pixels. The data consists of the following header: ====================================== ================ =============== No. of bytes Type Description ====================================== ================ =============== 4 ``S32`` *encoding* ====================================== ================ =============== It is followed by *width* * *height* pixels values encoded according to *encoding*. The pixel format is always 32 bits with 8 bits for each channel in the order red, green, blue, alpha. Alpha is pre-multiplied for each colour channel. The server is free to use any encoding that the client has specified as supported. However some encodings may be unsuitable as they cannot include the extra bits that are used for alpha. Also note that the data used for the cursor shares state with other rects. E.g. the zlib stream for a ZRLE encoding is the same as for data rects. JPEG Fine-Grained Quality Level Pseudo-encoding ----------------------------------------------- The JPEG Fine-Grained Quality Level pseudo-encoding allows the image quality to be specified on a 0 to 100 scale, with -512 corresponding to image quality 0 and -412 corresponding to image quality 100. This pseudo-encoding was originally intended for use with JPEG-encoded subrectangles, but it could be used with other types of image encoding as well. JPEG Subsampling Level Pseudo-Encoding -------------------------------------- The JPEG Subsampling Level pseudo-encoding allows the level of chrominance subsampling to be specified. When a JPEG image is encoded, the RGB pixels are first converted to YCbCr, a colorspace in which brightness (luminance) is separated from color (chrominance). Since the human eye is more sensitive to spatial changes in brightness than to spatial changes in color, the chrominance components (Cb, Cr) can be subsampled to save bandwidth without losing much image quality (on smooth images, such as photographs, chrominance subsampling is often not distinguishable by the human eye). Subsampling can be implemented either by averaging together groups of chrominance components or by simply picking one component from the group and discarding the rest. The values for this pseudo-encoding are defined as follows: -768 = 1X chrominance subsampling (no chrominance subsampling). Chrominance components are sent for every pixel in the source image. -767 = 4X chrominance subsampling. Chrominance components are sent for every fourth pixel in the source image. This would typically be implemented using 4:2:0 subsampling (2X subsampling in both X and Y directions), but it could also be implemented using 4:1:1 subsampling (4X subsampling in the X direction.) -766 = 2X chrominance subsampling. Chrominance components are sent for every other pixel in the source image. This would typically be implemented using 4:2:2 subsampling (2X subsampling in the X direction.) -765 = Grayscale. All chrominance components in the source image are discarded. -764 = 8X chrominance subsampling. Chrominance components are sent for every 8th pixel in the source image. This would typically be implemented using 4:1:0 subsampling (4X subsampling in the X direction and 2X subsampling in the Y direction.) -763 = 16X chrominance subsampling. Chrominance components are sent for every 16th pixel in the source image. This would typically be implemented using 4X subsampling in both X and Y directions. This pseudo-encoding was originally intended for use with JPEG-encoded subrectangles, but it could be used with other types of image encoding as well. Kasm-specific pseudo-encodings ------------------------------ These allow remote configuration of some properties, in case the server allows it. For the interpretation of these values, see the man page and server config docs. Video time = 0-100 Video area = 1-100 Dynamic quality max = 0-9 Dynamic quality min = 0-9 Prefer bandwidth over quality = bool Treat lossless = 0-10 Webp video quality = 0-9 Jpeg video quality = 0-9 Webp support = bool Video out time = 1-100 Video scaling = 0-9, currently 0-2 defined Max video resolution = bool Frame rate = 10-60 VMware Cursor Pseudo-encoding ----------------------------- A server sets the cursor shape by sending a pseudo-rectangle with the VMware Cursor pseudo-encoding as part of an update. The pseudo-rectangle's *x-position* and *y-position* indicate the hotspot of the cursor, and *width* and *height* indicate the width and height of the cursor in pixels. The data starts with a *cursor-type* byte followed by padding: =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 1 ``U8`` *cursor-type* 1 ``U8`` padding =============== ==================== ======================= The value of *cursor-type* is either 0 to indicate a 'classic' cursor which consists of an AND mask and a XOR mask, or 1 indicate an alpha cursor. The data for a classic cursor consists two sets of *width* * *height* pixel values, defining an AND mask and a XOR mask: ======================================= =================== ============= No. of bytes Type Description ======================================= =================== ============= *width* * *height* * *bytesPerPixel* ``PIXEL`` array *and-mask* *width* * *height* * *bytesPerPixel* ``PIXEL`` array *xor-mask* ======================================= =================== ============= Classic cursors can be drawn using the following code: :: dst[i] = (dst[i] & and-mask[i]) ^ xor-mask[i]; The data for an alpha cursor consists of *width* * *height* RGBA pixel values: ======================================= =================== ============== No. of bytes Type Description ======================================= =================== ============== *width* * *height* * 4 ``U8`` array *cursor bytes* ======================================= =================== ============== Alpha cursors should be drawn by compositing the cursor image into the framebuffer. VMware Cursor State Pseudo-encoding ----------------------------------- A server sets the cursor state by sending a pseudo-rectangle with the VMware Cursor State pseudo-encoding as part of an update. =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 2 ``U16`` *cursor-state* =============== ==================== ======================= *cursor-state* is a bit-field which describes the state of the cursor: =============== ======================================================= Bit Description =============== ======================================================= 0 Cursor visible. 1 Cursor absolute. 2 Cursor wrap. =============== ======================================================= If cursor visible is not set, the cursor should not be rendered into the framebuffer until another cursor state message is received that turns the cursor back on. The cursor absolute bit indicates whether the virtual machine is using an absolute or relative mouse. The cursor warp bit is set when the virtual machine artificially moves the position of the cursor. This value is for information purposes only. VMware Cursor Position Pseudo-encoding -------------------------------------- A server updates the cursor position by sending a pseudo-rectangle with the VMware Cursor Position pseudo-encoding. The *x-position* and *y-position* define the new position of the cursor hot spot (not the the top left corner of cursor image). VMware Key Repeat Pseudo-encoding --------------------------------- The server notifies the client of changes to the keyboard key repeat by sending a pseudo-rectangle with the VMware Key Repeat pseudo-encoding. It is used to determine whether the client or server should handle the key repeat. =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 2 ``U16`` *key-repeat-enabled* 4 ``U32`` *period* 4 ``U32`` *delay* =============== ==================== ======================= *key-repeat-enabled* is 1 if the VNC client should handle key repeat, 0 if the server handles key repeat. *period* defines the period to wait between key repeats. *delay* defines the delay for the first key repeat. VMware LED State Pseudo-encoding --------------------------------- The server sends a pseudo-rectangle with the VMware LED State pseudo-encoding to toggle the state of lock keys on the keyboard. This pseudo-rectangle has the following contents: =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 4 ``U32`` *led-flags* =============== ==================== ======================= *led-flags* is a bitmask which defines whether a keyboard LED is on or off. =============== ======================================================= Bit Description =============== ======================================================= 0 Scroll Lock 1 Num Lock 2 Caps Lock =============== ======================================================= The remaining bits are reserved and must be ignored. VMware Display Mode Change Pseudo-encoding ------------------------------------------ The server changes the desktop size by sending a pseudo-rectangle with the VMware Display Mode Change pseudo-encoding. This encoding is used for scenarios not addressed by the `DesktopSize Pseudo-encoding`_. Specifically, the `DesktopSize Pseudo-encoding`_ does not allow the VNC server to redefine both the color depth and size of the framebuffer. This is useful when the client prefers to receive the framebuffer native color depth at all times. It is defined to be similar to the ServerInitialisation header to facilitate client implementations. The new pixel format takes effect immediately after the server sends a pseudo-rectangle with the VMware Display Mode Change pseudo-encoding. The *width* and *height* of the pseudo-rectangle specify the new width and height of the display. The rest of the format is described below: =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 1 ``U8`` *bits-per-sample* 1 ``U8`` *depth* 1 ``U8`` *color* 1 ``U8`` *true-color* 2 ``U16`` *max-red* 2 ``U16`` *max-green* 2 ``U16`` *max-blue* 1 ``U8`` *red-shift* 1 ``U8`` *green-shift* 1 ``U8`` *blue-shift* 3 padding =============== ==================== ======================= VMware Virtual Machine State Pseudo-encoding -------------------------------------------- The server sends a pseudo-rectangle with the VMware Virtual Machine State pseudo-encoding to notify the client of changes in the Virtual Machine state. =============== ==================== ======================= No. of bytes Type Description =============== ==================== ======================= 2 ``U16`` *vm-state-flags* =============== ==================== ======================= *vm-state-flags* is a bitmask field. These flags describe the virtual machine state. =============== ======================================================= Bit Description =============== ======================================================= 0 A end-user sitting at a local virtual machine console has entered fullscreen mode. 1 A end-user sitting at a local virtual machine console has temporarily disabled VNC updates. =============== ======================================================= Extended Clipboard Pseudo-Encoding ---------------------------------- A client which requests the *Extended Clipboard* pseudo-encoding is declaring that it supports the extended versions of the `ClientCutText`_ and `ServerCutText`_ messages. The format of these messages are altered so that *length* is now signed rather than unsigned: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 1 ``U8`` 6/3 *message-type* 3 *padding* 4 ``S32`` *length* =============== ==================== ========== ======================= A positive value of *length* indicates that the message follows the original format with 8859-1 text data: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= *length* ``U8`` array *text* =============== ==================== ========== ======================= A negative value of *length* indicates that the extended message format is used and *abs(length)* is the total number of following bytes. All messages start with a header: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= 4 ``U32`` *flags* =============== ==================== ========== ======================= The bits of *flags* have the following meaning: =============== ======================================================= Bit Description =============== ======================================================= 0 *text* 1 *rtf* 2 *html* 3 *dib* 4 *files* 5-15 Reserved for future formats 16-23 Reserved 24 *caps* 25 *request* 26 *peek* 27 *notify* 28 *provide* 29-31 Reserved for future actions =============== ======================================================= The different formats are: *text* Plain, unformatted text using the UTF-8 encoding. End of line is represented by carriage-return and linefeed / newline pairs (values 13 and 10). The text must be followed by a terminating null even though the length is also explicitly given. *rtf* Microsoft Rich Text Format. *html* Microsoft HTML clipboard fragments. *dib* Microsoft Device Independent Bitmap v5. A file header must not be included. *files* Currently reserved but not defined. If *caps* is set then the other bits indicate which formats and actions that the sender is willing to receive. Following *flags* is an array indicating the maximing unsolicited size for each format: =============== ==================== ========== ======================= No. of bytes Type [Value] Description =============== ==================== ========== ======================= *formats* * 4 ``U32`` array *sizes* =============== ==================== ========== ======================= The number of entries in *sizes* corresponds to the number of format bits set in *flags* (bit 0-15). The server must send a `ServerCutText`_ message with *caps* set on each `SetEncodings`_ message received which includes the *Extended Clipboard* pseudo-encoding. The client may send a `ClientCutText`_ message with *caps* set back to indicate its capabilities. Otherwise the client is assumed to support *text*, *rtf*, *html*, *request*, *notify* and *provide* and a maximum size of 20 MiB for *text* and 0 bytes for the other types. Note that it is recommended to set all sizes to 0 bytes to force all clipboard updates to be sent in the form of a *notify* action. Failing to do so makes it ambiguous if an incoming message indicates a completely new set of formats, or an update to previous formats caused by size restrictions. It may be possible to also resolve this ambiguity using *peek* actions. Also be aware that there are some implementations that deviate from the behaviour specified here. The prominent changes are that *dib* is also in the default set of supported formats, that default limits are now 10 MiB for *text*, 2 MiB for *rtf* and *html*, and 0 bytes for *dib*, and that the client ignores the advertised formats and maximum sizes given in the *caps* message. If *caps* is not set then only one of the other actions (bit 24-31) may be set. *request* The recipient should respond with a *provide* message with the clipboard data for the formats indicated in *flags*. No other data is provided with this message. *peek* The recipient should send a new *notify* message indicating which formats are available. No other bits in *flags* need to be set and no other data is provided with this message. *notify* This message indicates which formats are available on the remote side and should be sent whenever the clipboard changes, or as a response to a *peek* message. The available formats are specified in *flags* and no other data is provided with this message. *provide* This message includes the actual clipboard data and should be sent whenever the clipboard changes and the data for each format is less than the respective specified maximum size, or as a response to a *request* message. The header is followed by a Zlib [#zlib]_ stream which contains a pair of *size* and *data* for each format indicated in *caps*: =============== ==================== ========== =================== No. of bytes Type [Value] Description =============== ==================== ========== =================== 4 ``U32`` *size* *size* ``U8`` array *data* =============== ==================== ========== =================== --- METRICS --- - Files Extracted: 5 - Estimated Token Budget: ~56189 tokens - Recency Window: Active (< 180 days) - Canonical Reference: https://codewiki.google/github.com/kasmtech/KasmVNC