Merged with default version 0.3.0 stable

Wed, 08 May 2019 15:46:50 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 08 May 2019 15:46:50 +0200
branch
stable
changeset 46
aaa095986ede
parent 35
1625e565ca31 (current diff)
parent 45
71b4c3d1b429 (diff)
child 58
7ce410c79048

Merged with default version 0.3.0

components/vnc_server/Kconfig file | annotate | diff | comparison | revisions
components/vnc_server/component.mk file | annotate | diff | comparison | revisions
components/vnc_server/vnc-server.c file | annotate | diff | comparison | revisions
components/vnc_server/vnc-server.h file | annotate | diff | comparison | revisions
image/w/app/error-handler.js.gz file | annotate | diff | comparison | revisions
image/w/app/images/clipboard.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/connect.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/disconnect.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/drag.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/error.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/expander.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/fullscreen.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/handle.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/handle_bg.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/info.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/mouse_left.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/mouse_middle.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/mouse_none.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/mouse_right.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/settings.svg.gz file | annotate | diff | comparison | revisions
image/w/app/images/warning.svg.gz file | annotate | diff | comparison | revisions
image/w/app/locale/de.json file | annotate | diff | comparison | revisions
image/w/app/locale/el.json file | annotate | diff | comparison | revisions
image/w/app/locale/es.json file | annotate | diff | comparison | revisions
image/w/app/locale/nl.json file | annotate | diff | comparison | revisions
image/w/app/locale/pl.json file | annotate | diff | comparison | revisions
image/w/app/locale/sv.json file | annotate | diff | comparison | revisions
image/w/app/locale/tr.json file | annotate | diff | comparison | revisions
image/w/app/locale/zh.json file | annotate | diff | comparison | revisions
image/w/app/localization.js.gz file | annotate | diff | comparison | revisions
image/w/app/sounds/bell.mp3 file | annotate | diff | comparison | revisions
image/w/app/sounds/bell.oga file | annotate | diff | comparison | revisions
image/w/app/styles/base.css file | annotate | diff | comparison | revisions
image/w/app/styles/web.css file | annotate | diff | comparison | revisions
image/w/app/ui.js.gz file | annotate | diff | comparison | revisions
image/w/app/webutil.js.gz file | annotate | diff | comparison | revisions
image/w/core/base64.js.gz file | annotate | diff | comparison | revisions
image/w/core/des.js.gz file | annotate | diff | comparison | revisions
image/w/core/display.js.gz file | annotate | diff | comparison | revisions
image/w/core/encodings.js.gz file | annotate | diff | comparison | revisions
image/w/core/inflator.js.gz file | annotate | diff | comparison | revisions
image/w/core/input/mouse.js.gz file | annotate | diff | comparison | revisions
image/w/core/rfb.js.gz file | annotate | diff | comparison | revisions
image/w/core/rfb.js.orig file | annotate | diff | comparison | revisions
image/w/core/util/browser.js.gz file | annotate | diff | comparison | revisions
image/w/core/util/events.js.gz file | annotate | diff | comparison | revisions
image/w/core/util/eventtarget.js.gz file | annotate | diff | comparison | revisions
image/w/core/util/logging.js.gz file | annotate | diff | comparison | revisions
image/w/core/util/polyfill.js.gz file | annotate | diff | comparison | revisions
image/w/core/util/strings.js.gz file | annotate | diff | comparison | revisions
image/w/core/websock.js.gz file | annotate | diff | comparison | revisions
image/w/css/style.css file | annotate | diff | comparison | revisions
image/w/js/modl/babel.js.gz file | annotate | diff | comparison | revisions
image/w/js/modl/brloader.js.gz file | annotate | diff | comparison | revisions
image/w/js/utils/common.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/adler32.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/constants.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/crc32.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/deflate.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/gzheader.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/inffast.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/inflate.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/inftrees.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/messages.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/trees.js.gz file | annotate | diff | comparison | revisions
image/w/js/zlib/zstream.js.gz file | annotate | diff | comparison | revisions
image/w/vnc.html.gz file | annotate | diff | comparison | revisions
--- a/Makefile	Thu May 02 11:52:36 2019 +0200
+++ b/Makefile	Wed May 08 15:46:50 2019 +0200
@@ -3,6 +3,7 @@
 # project subdirectory.
 #
 
+PROJECT_VER := "0.3.0"
 PROJECT_NAME := brewboard
 
 include $(IDF_PATH)/make/project.mk
--- a/README.md	Thu May 02 11:52:36 2019 +0200
+++ b/README.md	Wed May 08 15:46:50 2019 +0200
@@ -65,29 +65,21 @@
 enkele aanpassingen voor dit project en daarom zijn die projecten volledig
 geimporteerd in brewboard. 
 
-Voor de VNC client: https://github.com/novnc/noVNC.git. Losse VNC clients
-kunnen verbinden met poort 5900. Niet alle clients doen het goed omdat ze een
-16 bits full color VNC server verwachten en niet goed downgraden naar 8 bits
-kleuren. TigerVNC doet het goed. Voor deze applicatie is 16 bits kleur geen
-optie omdat de schermbuffer dan niet meer in het geheugen past.
-
 De PID library: http://playground.arduino.cc/Code/PIDLibrary by Brett
 Beauregard.
 
 De 1-wire bus: https://www.github.com/DavidAntliff/esp32-owb
 De DS18B20 sensoren: https://www.github.com/DavidAntliff/esp32-ds18b20
 
-De webserver en websockets server. Websockets worden gebruikt voor de VNC
-web client. Hiervoor heb je geen losse VNC client nodig zoals bijvoorbeeld
-de TigerVNC viewer maar wordt de VNC code in je browser gezet met javascript.
+De webserver en websockets server. Websockets worden gebruikt voor de web
+client. Deze web client probeert een kopie te zijn van het touch scherm.
 https://github.com/Molorius/esp32-websocket.git components/websocket
-De javascript VNC client is aangepast voor deze applicatie.
 
 Het schema voor dit project staat op EasyDA. Zie
 https://easyeda.com/mbroek/ESP32_experiments-3ec1c1b17c3b41378ba4493ea69fa5c3.
 Belangrijk als je dit gaat bouwen: koop het juiste ESP32 devkit board. De
 meeste boards hebben niet genoeg aansluitingen naar buiten, je hebt echt de
-36 pens versie van Geekcreit®nodig.
+36 pens versie van Geekcreit® nodig.
 
 
 
@@ -95,6 +87,6 @@
 
 TODO:
       - Nosleep js code toevoegen.
-      - Web client zonder VNC, of toch niet.
+      - Web client zonder VNC, of toch niet. In progress.
 
 
--- a/components/spidriver/spi_master_lobo.c	Thu May 02 11:52:36 2019 +0200
+++ b/components/spidriver/spi_master_lobo.c	Wed May 08 15:46:50 2019 +0200
@@ -65,7 +65,7 @@
 #include "soc/spi_reg.h"
 #include "soc/dport_reg.h"
 #include "soc/rtc_cntl_reg.h"
-#include "rom/ets_sys.h"
+#include "esp32/rom/ets_sys.h"
 #include "esp_types.h"
 #include "esp_attr.h"
 #include "esp_log.h"
--- a/components/tft/tft.c	Thu May 02 11:52:36 2019 +0200
+++ b/components/tft/tft.c	Wed May 08 15:46:50 2019 +0200
@@ -15,12 +15,10 @@
 #include "tft.h"
 #include "time.h"
 #include <math.h>
-#include "rom/tjpgd.h"
+#include "esp32/rom/tjpgd.h"
 #include "esp_heap_caps.h"
 #include "tftspi.h"
 
-#include "vnc-server.h"
-
 #define DEG_TO_RAD 0.01745329252
 #define RAD_TO_DEG 57.295779513
 #define deg_to_rad 0.01745329252 + 3.14159265359
@@ -139,7 +137,6 @@
 
 	if ((x < dispWin.x1) || (y < dispWin.y1) || (x > dispWin.x2) || (y > dispWin.y2)) return;
 	drawPixel(x, y, color, sel);
-	VncDrawPixel(x, y, VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 //====================================================================
@@ -168,7 +165,6 @@
 	if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1;
 	if (h == 0) h = 1;
 	TFT_pushColorRep(x, y, x, y+h-1, color, (uint32_t)h);
-	VncDrawVertLine(x, y, y+h-1, VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 //--------------------------------------------------------------------------
@@ -184,7 +180,6 @@
 	if (w == 0) w = 1;
 
 	TFT_pushColorRep(x, y, x+w-1, y, color, (uint32_t)w);
-	VncDrawHorzLine(x, x+w-1, y, VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 //======================================================================
@@ -287,7 +282,6 @@
 	if (w == 0) w = 1;
 	if (h == 0) h = 1;
 	TFT_pushColorRep(x, y, x+w-1, y+h-1, color, (uint32_t)(h*w));
-	VncFillRect(x, y, x+w-1, y+h-1, VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 //============================================================================
@@ -298,14 +292,12 @@
 //==================================
 void TFT_fillScreen(color_t color) {
 	TFT_pushColorRep(0, 0, _width-1, _height-1, color, (uint32_t)(_height*_width));
-	VncCls(VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 //==================================
 void TFT_fillWindow(color_t color) {
 	TFT_pushColorRep(dispWin.x1, dispWin.y1, dispWin.x2, dispWin.y2,
 			color, (uint32_t)((dispWin.x2-dispWin.x1+1) * (dispWin.y2-dispWin.y1+1)));
-	VncFillRect(dispWin.x1, dispWin.y1, dispWin.x2, dispWin.y2, VNC_RGB2COL(color.r, color.g, color.b));
 }
 
 // ^^^============= Basics drawing functions ================================^^^
@@ -893,9 +885,6 @@
 			// visible pixel
 			bufPos = ((j + fontChar.adjYOffset) * char_width) + (fontChar.xOffset + i);  // bufY + bufX
 			color_line[bufPos] = _fg;
-			VncDrawPixel(x + (fontChar.xOffset + i), y + (j + fontChar.adjYOffset), VNC_RGB2COL(_fg.r, _fg.g, _fg.b));
-		    } else {
-			VncDrawPixel(x + (fontChar.xOffset + i), y + (j + fontChar.adjYOffset), VNC_RGB2COL(_bg.r, _bg.g, _bg.b));
 		    }
 		    mask >>= 1;
 		}
@@ -971,9 +960,6 @@
 		    for (i = 0; i < 8; i++) {
 			if ((ch & mask) !=0) {
 			    color_line[(j*cfont.x_size) + (i+(k*8))] = _fg;
-			    VncDrawPixel(x+i+(k*8), y+j, VNC_RGB2COL(_fg.r, _fg.g, _fg.b));
-			} else {
-			    VncDrawPixel(x+i+(k*8), y+j, VNC_RGB2COL(_bg.r, _bg.g, _bg.b));
 			}
 			mask >>= 1;
 		    }
--- a/components/vnc_server/Kconfig	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-
-menu "VNC Server"
-
-config VNC_SERVER_PORT
-	int "VNC server port number"
-	default 5900
-	help
-		Port VNC server will listen on for client connection.
-		This defaults to the standard port 5900, but may
-		be changed to any other port number if required.
-
-
-config VNC_SERVER_FRAME_WIDTH
-	int "Frame width in pixels"
-	default	320
-	help
-		This sets the width of the VNC server frame buffer.
-
-
-config VNC_SERVER_FRAME_HEIGHT
-	int "Frame heigth in pixels"
-	default 240
-	help
-		This sets the height of the VNC server frame buffer.
-
-
-endmenu
--- a/components/vnc_server/component.mk	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-# Use defaults.
-COMPONENT_ADD_INCLUDEDIRS := .
--- a/components/vnc_server/vnc-server.c	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1361 +0,0 @@
-/**
- * @file vnc-server.c
- * @brief VNC server original written for eCos.
- *
- * The VNC server runs on the target platform and waits for a client 
- * (vncviewer program running on a PC) to connect via an ethernet connection
- * (port 5900). Once a client has connected, the target platform has a 
- * virtual screen, keyboard and mouse.
- *
- * This port of the VNC server has been designed with some limitations in 
- * order to keep memory and processor power requirements to a minimum.
- *
- * The VNC client must accept the settings that the VNC server suggests (bits-per-pixel, 
- * number-of-colours and so on as specified at build time with the eCos configuration 
- * tool) or the VNC server will just disconnect.
- *
- * The VNC server only supports CoRRE encoding and RAW encoding for sending 
- * display data to the client.
- *
- * The VNC server does not support password authentication, the client is able 
- * to connect without the user typing in a password.
- *
- * Only one VNC client may connect to the VNC server at a time.
- *
- * In reality these limitations are not a problem.
- *
- * @author Chris Garry <cgarry@sweeneydesign.co.uk>
- * @author Michiel Broek.
- */
-
-#include "vnc-server.h"
-#include "websocket_server.h"
-
-static const char *TAG = "vnc-server";
-
-#define BACKLOG             5				///< Number of pending connections queue will hold 
-#define MESSAGE_BUFFER_SIZE 60				///< Was 50, but I have seen 52 bytes length
-#define TILE_SIZE           16				///< Tile dimension
-#define TRUE_COLOUR_FLAG    1				///< True colour is set
-#define BIG_ENDIAN_FLAG     1				///< Always send colour data big endian
-
-/* Default display parameters */
-#define BITS_PER_PIXEL      8				///< Bits per pixel
-#define PIXEL_DEPTH         8				///< Usefull bits per pixel
-#define RED_MAX             7				///< Red maximum
-#define GREEN_MAX           7				///< Green maximum
-#define BLUE_MAX            3				///< Blue maximum, together 8 bits.
-#define RED_SHIFT           5				///< Red shift in color byte
-#define GREEN_SHIFT         2				///< Green shift in color byte
-#define BLUE_SHIFT          0				///< Blue shift in color byte
-
-
-/* Initial default RGB332 */
-uint8_t			Bits_Per_Pixel = 8;		///< Current number of bits per pixel
-
-uint16_t		Red_Max     = RED_MAX;		///< Current Red maxmimum
-uint16_t		Green_Max   = GREEN_MAX;	///< Current Green maximum
-uint16_t		Blue_Max    = BLUE_MAX;		///< Current Blue maximum
-uint8_t			Red_Shift   = RED_SHIFT;	///< Current Red bits shift
-uint8_t			Green_Shift = GREEN_SHIFT;	///< Current Green bits shift
-uint8_t			Blue_Shift  = BLUE_SHIFT;	///< Current Blue bits shift
-bool			AltPixels   = false;		///< Alternate the pixels
-
-/* Client to Server message types */
-#define SET_PIXEL_FORMAT         0			///< Set pixel format
-#define FIX_COLOUR_MAP_ENTRIES   1			///< Fix color map entries (not used)
-#define SET_ENCODINGS            2			///< Set encodings
-#define FRAME_BUFFER_UPDATE_REQ  3			///< Request frame buffer update
-#define KEY_EVENT                4			///< Keyboard event (not used)
-#define POINTER_EVENT            5			///< Pointer event, translated to touch events
-#define CLIENT_CUT_TEXT          6			///< Text editing, not used.
-
-/* Macros to split colour to bytes */
-#define COLOUR2BYTE1(col) ((col>>8)&0xFF)		///< High part
-#define COLOUR2BYTE0(col) (col&0xFF)			///< Low part
-
-
-/* Thread function prototypes */
-static TaskHandle_t	xTaskClientHandler = NULL;	///< Task for VNC clients
-static TaskHandle_t	xTaskFrameUpdate   = NULL;	///< Task for framebuffer updates
-static TaskHandle_t	xTaskWSclient      = NULL;	///< Task for websocket clients
-
-SemaphoreHandle_t	SoundBell_lock     = NULL;	///< Lock for the bell sound.
-
-static QueueHandle_t	message_queue;			///< Websockets message queue
-const static int	message_queue_size = 5;		///< Message queue size
-
-/**
- * @brief VNC messages.
- */
-struct strMessage {
-    int			length;				///< Length of the message
-    uint8_t		message[MESSAGE_BUFFER_SIZE];	///< The message
-};
-
-
-uint8_t			VNC_pointer_button = 0;		///< Button mask for the mouse pointer
-uint16_t		VNC_pointer_x = 0;		///< Mouse position X
-uint16_t		VNC_pointer_y = 0;		///< Mouse position Y
-
-
-/* Define size of each thread's stack */
-#define MIN_STACK_SIZE	3072				///< Minimal task stack size
-
-
-/**
- * @brief  Messages
- */
-static char		server_ProtocolVersion[] = "RFB 003.003\n";
-static char		bad_protocol[] = "Unsupported ProtocolVersion";
-static char		server_busy[] = "Server is Busy";
-static char		sound_bell[] = "\2";
-static char		desktop_name[] = "MBSE BrewBoard";	// Hardcoded, don't change or the VNC webclient breaks.
-
-/**
- * @brief  Frame Buffer
- */
-vnc_color_t		frame_buffer[CONFIG_VNC_SERVER_FRAME_HEIGHT+1][CONFIG_VNC_SERVER_FRAME_WIDTH+1];
-
-/* Calculate the number of tiles in the X and Y directions */
-#if (CONFIG_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE) != 0
-#define NUM_TILES_Y_AXIS (CONFIG_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE + 1)
-#define LAST_TILE_HEIGHT (CONFIG_VNC_SERVER_FRAME_HEIGHT % TILE_SIZE)
-#else
-#define NUM_TILES_Y_AXIS (CONFIG_VNC_SERVER_FRAME_HEIGHT/TILE_SIZE)	///< Nr of tiles on the Y axis.
-#define LAST_TILE_HEIGHT TILE_SIZE					///< Height of the last tile.
-#endif
-
-#if (CONFIG_VNC_SERVER_FRAME_WIDTH % TILE_SIZE) != 0
-#define NUM_TILES_X_AXIS (CONFIG_VNC_SERVER_FRAME_WIDTH/TILE_SIZE + 1)
-#define LAST_TILE_WIDTH (CONFIG_VNC_SERVER_FRAME_WIDTH % TILE_SIZE)
-#else
-#define NUM_TILES_X_AXIS (CONFIG_VNC_SERVER_FRAME_WIDTH/TILE_SIZE)	///< Nr of tiles on the X axis.
-#define LAST_TILE_WIDTH TILE_SIZE					///< Width of the last tile.
-#endif
-
-/**
- * @brief  Array for marking tiles that have been updated
- */
-int			tile_updated[NUM_TILES_Y_AXIS+1][NUM_TILES_X_AXIS+1];
-
-EventGroupHandle_t	xEventGroupVNC;			///< Variable to signal that a client is connected and initialised
-const int 		VNC_CLIENT_UPDATE_REQ = BIT0;	///< Client update request event
-int			vnc_client_sock = -1;		///< Client network socket
-bool			vnc_client_connected = false;	///< Client connected?
-int			SoundBellCount;			///< Count the client's bell
-bool			VNC_WS_run = false;		///< Websocket running
-int			VNC_WS_num = -1;		///< Websocket connection number
-
-
-
-/**
- * @brief Variable to hold the frame format details
- */
-vnc_frame_format_t	frame_format = {CONFIG_VNC_SERVER_FRAME_WIDTH, CONFIG_VNC_SERVER_FRAME_HEIGHT, frame_buffer,
-                                   1,			// RGB332 server native.
-                                   0,			// RGB555
-                                   0,			// RGB565
-                                   0,			// BGR233
-                                   0,			// TRUECOLOR0888
-};
-
-
-
-#if 0
-void dump_msg(char *buf, uint16_t buflen, char *mode)
-{   
-    int i, l = 0;
-
-    printf("%s %d", mode, buflen);
-    for (i = 0; i < buflen; i++) {
-	if ((i % 16) == 0) {
-	    printf("\n%02d: ", l);
-	    l++;
-	}
-	printf("%02x ", buf[i]);
-    }
-    printf("\n");
-}
-#endif
-
-
-/**
- * @brief Structure to hold the encoding type details
- */
-volatile struct encoding_type_struct
-{
-    uint8_t		raw;
-    uint8_t		copy_rectangle;
-    uint8_t		rre;
-    uint8_t		corre;
-    uint8_t		hextile;
-} encoding_type;
-
-
-static int GetMessageData(int, char *, int);
-static int GenTileUpdateData(uint8_t *);
-void task_VNCserver(void *);
-void task_frame(void *);
-void task_WS(void *);
-
-
-
-/**
- * @brief Serve a new VNC client.
- */
-void vnc_netconn_serve(void);
-
-
-/* VNC startup. */
-void VncStartup(void)
-{
-    /* Initialise mutex & cond vars */
-    xEventGroupVNC = xEventGroupCreate();
-    SoundBell_lock = xSemaphoreCreateMutex();
-
-    xTaskCreate(&task_VNCserver, "VNCserver",    MIN_STACK_SIZE, NULL, 5, &xTaskClientHandler);
-    xTaskCreate(&task_frame,     "frame_update", MIN_STACK_SIZE, NULL, 6, &xTaskFrameUpdate);
-}
-
-
-/** 
- * @brief Client Handler Task.
- *
- * This task handles the client initialisation sequence. Once the client
- * is initialised this task handles all received messages from the client,
- * but does not send any data to the client.
- */
-void task_VNCserver(void *pvParameter)
-{
-    int			server_sock; 
-    struct sockaddr_in	server_addr;
-    struct sockaddr_in	client_addr;
-    socklen_t		client_addr_size;
-
-    ESP_LOGI(TAG, "Starting VNC server");
-
-    /* Clear the encoding type structure */
-    encoding_type.raw = 0;
-    encoding_type.copy_rectangle = 0;
-    encoding_type.rre = 0;
-    encoding_type.corre = 0;
-    encoding_type.hextile = 0;
-
-    /* Clear the sound bell counter */
-    SoundBellCount = 0;
-    VNC_pointer_button = 0;
-    VNC_pointer_x = VNC_pointer_y = 0;
-
-    /* Create socket for incomming connections */
-    if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
-        ESP_LOGE(TAG, "socket() VNC function failed");
-        exit(1);
-    }
-
-    /* Construct the server address structure */
-    memset(&server_addr, 0, sizeof(server_addr));  /* Fill entire structure with 0's */
-    server_addr.sin_family      = AF_INET;         /* Internet address family */
-    server_addr.sin_addr.s_addr = INADDR_ANY;      /* Autofill with my IP address */
-    server_addr.sin_port        = htons(CONFIG_VNC_SERVER_PORT);
-
-    /* Bind socket to local address */
-    if (bind(server_sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
-        ESP_LOGE(TAG, "bind() VNC function failed");
-        exit(1);
-    }
-
-    /* Set the socket to listen for incoming connections */
-    if (listen(server_sock, BACKLOG) < 0) {
-        ESP_LOGE(TAG, "listen() VNC function failed");
-        exit(1);
-    }
-
-    do {
-	vnc_client_sock = (accept(server_sock, (struct sockaddr *) &client_addr, &client_addr_size));
-	if (vnc_client_sock >= 0) {
-	    vnc_client_connected = true;
-	    vnc_netconn_serve();
-	    vnc_client_connected = false;
-	}
-	vTaskDelay((TickType_t)10); /* allows the freeRTOS scheduler to take over if needed */
-    } while (vnc_client_sock >= 0);
-}
-
-
-
-/**
- * @brief Serve a new VNC client and handle the whole session.
- */
-void vnc_netconn_serve(void)
-{
-    long int			temp_long;
-    char 			protocol_ver[8], message_buffer[MESSAGE_BUFFER_SIZE];
-    int				i, j, message_len, ProtocolOkay;
-    uint32_t			*ptr_to_uint32;
-    uint16_t			*ptr_to_uint16;
-    struct sockaddr_storage	addr;
-    socklen_t			len = sizeof addr;
-    char			ipstr[INET6_ADDRSTRLEN];
-
-    getpeername(vnc_client_sock, (struct sockaddr*)&addr, &len);
-    if (addr.ss_family == AF_INET) {
-	struct sockaddr_in *s = (struct sockaddr_in *)&addr;
-	inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
-    }
-    ESP_LOGI(TAG, "VNC new client %s socket %d", ipstr, vnc_client_sock);
-
-    /* ProtocolVersion Handshake - begin */
-    /* Send ProtocolVersion we want to use to client */
-    message_len = sprintf(message_buffer, "RFB 003.003\n");
-    if (send(vnc_client_sock, message_buffer, message_len, 0) != message_len) {
-	goto close_connection;
-    }
-
-    /* Receive ProtocolVersion the client wants to use */
-    if (GetMessageData(vnc_client_sock, &(message_buffer[0]), 12) == 0) {
-	goto close_connection;
-    }
-
-    /* Check this is acceptable (RFB 003.xxx is okay) */
-    ProtocolOkay = 1;
-    for (i = 0; i < 8; i++) {
-	if (message_buffer[i] != server_ProtocolVersion[i]) {
-	    ProtocolOkay = 0;
-	}
-
-        /* Store the protocol version - ignoring thr 'RFB ' part */
-        protocol_ver[i] = message_buffer[i + 4];
-    }
-    protocol_ver[7] = 0;
-    /* ProtocolVersion Handshake - end */
-
-    /* Authentication - begin */
-    /* Send Authentication scheme to be used to client */
-    if (ProtocolOkay == 0) {
-	/* ProtocolVerion is not okay */
-
-	/* Generate the Bad ProtocolVerion message */
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-	*ptr_to_uint32 = htonl(0);
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[4]);
-	*ptr_to_uint32 = htonl(strlen(bad_protocol));
-	strcpy(&(message_buffer[8]), bad_protocol);
-
-	if (send(vnc_client_sock, message_buffer, 8 + strlen(bad_protocol), 0) != (8 + strlen(bad_protocol))) {
-	    printf("Call to send() 1 failed\n");
-	}
-	goto close_connection;
-
-    } else if (VNC_WS_num != -1) {
-	/* Busy with a websocket client */
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-	*ptr_to_uint32 = htonl(0);
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[4]);
-	*ptr_to_uint32 = htonl(strlen(server_busy));
-	strcpy(&(message_buffer[8]), server_busy);
-
-	if (send(vnc_client_sock, message_buffer, 8 + strlen(server_busy), 0) != (8 + strlen(server_busy))) {
-	    printf("Call to send() 1 failed\n");
-	}
-	goto close_connection;
-
-    } else {
-	/* ProtocolVerion is okay - connect with no authentication*/
-
-	/* Generate the No Authentication message */
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-	*ptr_to_uint32 = htonl((uint32_t)1);
-
-	if (send(vnc_client_sock, message_buffer, 4, 0) != 4) {
-	    goto close_connection;
-	}
-    }
-    /* Authentication - end */
-
-    /* ClientInitialisation - begin */
-    /* Receive initialisation message from client (1 byte) */
-    if (GetMessageData(vnc_client_sock, &(message_buffer[0]), 1) == 0) {
-	goto close_connection;
-    }
-    /* Do nothing with this as we only support 1 Client at a time */
-    /* ClientInitialisation - end */
-
-    /* ServerInitialisation - begin */
-
-    /* Initial default RGB332 */
-    Red_Max     = RED_MAX;
-    Green_Max   = GREEN_MAX;
-    Blue_Max    = BLUE_MAX;
-    Red_Shift   = RED_SHIFT;
-    Green_Shift = GREEN_SHIFT;
-    Blue_Shift  = BLUE_SHIFT;
-    AltPixels   = false;
-
-    /* Create Initialisation message for client */
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[0]);
-    *ptr_to_uint16 = htons((uint16_t)CONFIG_VNC_SERVER_FRAME_WIDTH);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[2]);
-    *ptr_to_uint16 = htons((uint16_t)CONFIG_VNC_SERVER_FRAME_HEIGHT);
-
-    message_buffer[4] = (uint8_t)BITS_PER_PIXEL;
-    message_buffer[5] = (uint8_t)PIXEL_DEPTH;
-    message_buffer[6] = (uint8_t)BIG_ENDIAN_FLAG;
-    message_buffer[7] = (uint8_t)TRUE_COLOUR_FLAG;
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[8]);
-    *ptr_to_uint16 = htons(Red_Max);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[10]);
-    *ptr_to_uint16 = htons(Green_Max);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[12]);
-    *ptr_to_uint16 = htons(Blue_Max);
-
-    message_buffer[14] = Red_Shift;
-    message_buffer[15] = Green_Shift;
-    message_buffer[16] = Blue_Shift;
-
-    ptr_to_uint32 = (uint32_t *) &(message_buffer[20]);
-    *ptr_to_uint32 = htonl(strlen(desktop_name));
-    strcpy(&(message_buffer[24]), desktop_name);
-
-    if (send(vnc_client_sock, message_buffer, 24 + strlen(desktop_name), 0) != (24 + strlen(desktop_name))) {
-	printf("Call to send() 3 failed\n");
-    }
-    /* ServerInitialisation - end */
-
-    /* Cancel any outstanding Sound Bell requests */
-    if (xSemaphoreTake(SoundBell_lock, 10) == pdTRUE) {
-	SoundBellCount = 0;
-	xSemaphoreGive(SoundBell_lock);
-    }
-
-    ESP_LOGI(TAG, "VNC client connected (RFB Protocol Ver: %s)", protocol_ver);
-
-    /* Main message handling loop */
-    while(1) {
-	int num_of_encodings;
-
-	/* Receive 1st byte of message from client */
-	if (GetMessageData(vnc_client_sock, &(message_buffer[0]), 1) == 0) {
-	    goto close_connection;	/* Connection lost */
-	}
-
-	switch(message_buffer[0]) {
-            case SET_PIXEL_FORMAT:
-
-                /* Get the remainder (19 bytes) of message */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 19) == 0) {
-                    goto close_connection;
-                }
-
-                /* Check pixel format is as expected */
-                i = 0;
-                if (message_buffer[4] != BITS_PER_PIXEL) {
-		    ESP_LOGI(TAG, "SetPixelFormat client wants %d bits-per-pixel", message_buffer[4]);
-                    i++;
-                }
-
-                if (message_buffer[5] != PIXEL_DEPTH) {
-		    ESP_LOGI(TAG, "SetPixelFormat client wants %d pixel-depth", message_buffer[5]);
-                    i++;
-                }
-
-                if ((message_buffer[7] & 0x01) != TRUE_COLOUR_FLAG) {
-		    ESP_LOGI(TAG, "SetPixelFormat client wants %d true-colour-flag", message_buffer[7]);
-                    i++;
-                }
-
-                ptr_to_uint16 = (uint16_t *)&(message_buffer[8]);
-                if (htons(*ptr_to_uint16) != Red_Max) {
-		    Red_Max = htons(*ptr_to_uint16);
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d red-max", Red_Max);
-                }
-
-                ptr_to_uint16 = (uint16_t *)&(message_buffer[10]);
-                if (htons(*ptr_to_uint16) != Green_Max) {
-		    Green_Max = htons(*ptr_to_uint16);
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d green-max", Green_Max);
-                }
-
-                ptr_to_uint16 = (uint16_t *)&(message_buffer[12]);
-                if (htons(*ptr_to_uint16) != Blue_Max) {
-		    Blue_Max = htons(*ptr_to_uint16);
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d blue-max", Blue_Max);
-                }
-
-                if (message_buffer[14] != Red_Shift) {
-		    Red_Shift = message_buffer[14];
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d red-shift", Red_Shift);
-                }
-
-                if (message_buffer[15] != Green_Shift) {
-		    Green_Shift = message_buffer[15];
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d green-shift", Green_Shift);
-                }
-
-                if (message_buffer[16] != Blue_Shift) {
-		    Blue_Shift = message_buffer[16];
-		    AltPixels = true;
-		    ESP_LOGI(TAG, "SetPixelFormat client granted %d blue-shift", Blue_Shift);
-                }
-
-                if (i) {
-		    ESP_LOGI(TAG, "SetPixelFormat %d errors, disconnect client", i);
-                     ESP_LOGI(TAG, "Ensure the 'Auto select' is not enabled in your vncviewer options,");
-                    goto close_connection_quietly;
-                }
-
-                break;
-
-            case FIX_COLOUR_MAP_ENTRIES:
-printf("fix colormap entries\n");
-                /* Not supported, just get the data from the buffer and ignore it */
-
-                /* Get the next 5 bytes of message */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 5) == 0) {
-                    goto close_connection;
-                }
-
-                /* Calculate how many colour entries are in the buffer */
-                i = message_buffer[4]*255 + message_buffer[5];
-                i *= 6;
-
-                /* Get this amount of data from the buffer */
-                for (j = 0; j < i; j++) {
-                    if (GetMessageData(vnc_client_sock, &(message_buffer[6]), 6) == 0) {
-                        goto close_connection;
-                    }
-                }
-
-                break;
-
-            case SET_ENCODINGS:
-
-                /* Get the next 3 bytes of message */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 3) == 0) {
-                    goto close_connection;
-                }
-
-                num_of_encodings = message_buffer[2]*255 + message_buffer[3];
-
-                /* Get the remainder of message */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[0]), 4 * num_of_encodings) == 0) {
-                    goto close_connection;
-                }
-
-                /* Clear the encoding type structure */
-                encoding_type.raw = 0;
-                encoding_type.copy_rectangle = 0;
-                encoding_type.rre = 0;
-                encoding_type.corre = 0;
-                encoding_type.hextile = 0;
-
-                for (i = 0; i < num_of_encodings; i++) {
-                    switch(message_buffer[3 + (i*4)]) {
-                    case 0:  /* Raw encoding */
-                        encoding_type.raw = i + 1;
-                        break;
-                    case 1:  /* Copy rectangle encoding */
-                        encoding_type.copy_rectangle = i + 1;
-                        break;
-                    case 2:  /* RRE encoding */
-                        encoding_type.rre = i + 1;
-                        break;
-                    case 4:  /* CoRRE encoding */
-                        encoding_type.corre = i + 1;
-                        break;
-                    case 5:  /* Hextile encoding */
-                        encoding_type.hextile = i + 1;
-                        break;
-                    default:  /* Unknown coding type - do nothing */
-                        break;
-                    }
-                }
-                break;
-
-            case FRAME_BUFFER_UPDATE_REQ:
-                /* Get the remainder of message (9 bytes) */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 9) == 0) {
-                    goto close_connection;
-                }
-
-                if (!message_buffer[1]) {
-                    /* Non-incremental mode - mark the squares that need to be updated */
-                    for (i = (message_buffer[2]*255 + message_buffer[3])/TILE_SIZE;
-                         i <= (message_buffer[2]*255 + message_buffer[3] + message_buffer[6]*255 + message_buffer[7])/TILE_SIZE;
-                         i++) {
-                        for (j = (message_buffer[4]*255 + message_buffer[5])/TILE_SIZE;
-                             j <= (message_buffer[4]*255 + message_buffer[5] + message_buffer[8]*255 + message_buffer[9])/TILE_SIZE;
-                             j++) {
-                            tile_updated[j][i] = 1;
-                        }
-                    }
-                }
-
-                /* Signal that there is now a pending update request */
-                xEventGroupSetBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ);
-		break;
-
-            case KEY_EVENT:
-                /* Handle the key event, ignored for brewboard */
-                /* Get the remainder of message (7 bytes) */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 7) == 0) {
-                    goto close_connection;
-                }
-                break;
-
-            case POINTER_EVENT:
-                /* Handle the pointer event, simulate the touch screen. */
-                /* Get the remainder of message (5 bytes) */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 5) == 0) {
-                    goto close_connection;
-                }
-		/* Set global variables that will be read by another task. */
-		VNC_pointer_button = message_buffer[1];
-		VNC_pointer_x = message_buffer[2]*255 + message_buffer[3];
-		VNC_pointer_y = message_buffer[4]*255 + message_buffer[5];
-                break;
-
-            case CLIENT_CUT_TEXT:
-                /* Handle the client has cut text event */
-                /* Current we just get and discard the data */
-                /* Get the next 7 bytes of the message */
-                if (GetMessageData(vnc_client_sock, &(message_buffer[1]), 7) == 0) {
-                    goto close_connection;
-                }
-
-                ptr_to_uint32 = (uint32_t *)&(message_buffer[4]);
-                temp_long = htonl(*ptr_to_uint32);
-
-                while (temp_long > 0) {
-                    /* Get the text in chunks MESSAGE_BUFFER_SIZE-1 characters */
-                    if (temp_long > MESSAGE_BUFFER_SIZE-2) {
-                        if (GetMessageData(vnc_client_sock, &(message_buffer[0]), MESSAGE_BUFFER_SIZE-1) == 0) {
-                            goto close_connection;
-                        }
-
-                        message_buffer[MESSAGE_BUFFER_SIZE-1] = 0;
-                        temp_long -= (MESSAGE_BUFFER_SIZE-1);
-                    } else {
-                        if (GetMessageData(vnc_client_sock, &(message_buffer[0]), temp_long) == 0) {
-                            goto close_connection;
-                        }
-
-                        message_buffer[temp_long] = 0;
-                        temp_long = 0;
-                    }
-                }
-
-                break;
-
-            default:
-		ESP_LOGI(TAG, "Unknown message %d from client", message_buffer[0]);
-        }
-
-	vTaskDelay( (TickType_t)1);
-    }
-
-close_connection:
-    ESP_LOGI(TAG, "VNC client disconnected");
-
-close_connection_quietly:
-
-    /* Cancel any outstanding update requests */
-    xEventGroupClearBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ);
-    close(vnc_client_sock);
-}
-
-
-
-/**
- * @brief Frame update task. This thread handles the sending of all frame
- *        update data to the client and sends the 'ring bell' message to
- *        the client when required.
- *        Works for VNC port connected clients and Websocket clients.
- * @param pvParameter Ignored
- */
-void task_frame(void *pvParameter)
-{
-    int			i, j, x_pos, y_pos, packet_length, num_updated_tiles;
-    uint16_t		*ptr_to_uint16;
-    /* These are declared static so they don't use thread stack memory */
-    static uint8_t	FramebufferUpdate_msg[4 + 12 + TILE_SIZE*TILE_SIZE*BITS_PER_PIXEL/8 + 1460];
-    static int		FrameBufferPtr;  /* Pointer to next space in buffer */
-    static int		tile_updated_local[NUM_TILES_Y_AXIS][NUM_TILES_X_AXIS];
-
-    ESP_LOGI(TAG, "Starting VNC frame updater");
-
-    while(1) {
-        /* Wait until client sends a frame update request */
-wait_for_client:
-	xEventGroupWaitBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ, pdFALSE, pdFALSE, portMAX_DELAY);
-
-        /* Copy tile_updated array to local version and clear copied tiles */
-	vTaskSuspendAll();
-        num_updated_tiles = 0;
-        for (i = 0; i < NUM_TILES_Y_AXIS; i++) {
-            for (j = 0; j < NUM_TILES_X_AXIS; j++) {
-                if (tile_updated[i][j]) {
-                    tile_updated_local[i][j] = 1;
-                    tile_updated[i][j] = 0;
-                    num_updated_tiles++;  /* Keep count of the updated tiles */
-                }
-            }
-        }
-	xTaskResumeAll();
-
-        if (num_updated_tiles) {
-	    /* Cancel update request */
-	    xEventGroupClearBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ);
-            /* Fill in constant parts of FramebufferUpdate Message */
-            FramebufferUpdate_msg[0] = 0;  /* Message-type */
-            FramebufferUpdate_msg[1] = 0;  /* Padding */
-            ptr_to_uint16 = (uint16_t *) &(FramebufferUpdate_msg[2]);
-            *ptr_to_uint16 = htons(num_updated_tiles);  /* Number-of-rectangles */
-            FrameBufferPtr = 4;
-
-            for (y_pos = 0; y_pos < NUM_TILES_Y_AXIS; y_pos++) {
-                for (x_pos = 0; x_pos < NUM_TILES_X_AXIS; x_pos++) {
-                    if (tile_updated_local[y_pos][x_pos]) {
-                        /* Send current square data to client */
-
-                        /* x-position */
-                        FramebufferUpdate_msg[FrameBufferPtr+0] = (x_pos * TILE_SIZE) / 256;
-                        FramebufferUpdate_msg[FrameBufferPtr+1] = (x_pos * TILE_SIZE) % 256;
-
-                        /* y-position */
-                        FramebufferUpdate_msg[FrameBufferPtr+2] = (y_pos * TILE_SIZE) / 256;
-                        FramebufferUpdate_msg[FrameBufferPtr+3] = (y_pos * TILE_SIZE) % 256;
-
-
-                        /* Set width of tile in packet */
-                        if (x_pos == (NUM_TILES_X_AXIS -1)) {
-                            /* Last tile in X-axis */
-                            FramebufferUpdate_msg[FrameBufferPtr+4] = LAST_TILE_WIDTH / 256;
-                            FramebufferUpdate_msg[FrameBufferPtr+5] = LAST_TILE_WIDTH % 256;
-                        } else {
-                            FramebufferUpdate_msg[FrameBufferPtr+4] = TILE_SIZE / 256;
-                            FramebufferUpdate_msg[FrameBufferPtr+5] = TILE_SIZE % 256;
-                        }
-
-                        if (y_pos == (NUM_TILES_Y_AXIS -1)) {
-                            /* Last tile in Y-axis */
-                            FramebufferUpdate_msg[FrameBufferPtr+6] = LAST_TILE_HEIGHT / 256;
-                            FramebufferUpdate_msg[FrameBufferPtr+7] = LAST_TILE_HEIGHT % 256;
-                        } else {
-                            FramebufferUpdate_msg[FrameBufferPtr+6] = TILE_SIZE / 256;
-                            FramebufferUpdate_msg[FrameBufferPtr+7] = TILE_SIZE % 256;
-                        }
-
-                        /* Generate the packet data for this tile */
-                        packet_length = GenTileUpdateData(&(FramebufferUpdate_msg[FrameBufferPtr]));
-
-                        /* Send the packet data for this tile to the client */
-                        FrameBufferPtr += packet_length;
-
-                        if (FrameBufferPtr > 1460) {
-                            /* Send the data to the client */
-			    if (VNC_WS_num != -1) {
-				ws_server_send_bin_client(VNC_WS_num, (char *)FramebufferUpdate_msg, FrameBufferPtr);
-			    }
-			    if (vnc_client_connected) {
-                            	if (send(vnc_client_sock, FramebufferUpdate_msg, FrameBufferPtr, 0) != FrameBufferPtr) {
-                            	    goto wait_for_client;
-                            	}
-			    }
-                            FrameBufferPtr = 0;
-                        }
-
-                        tile_updated_local[y_pos][x_pos] = 0;  /* Clear the update bit for this square */
-                    }
-                }
-            }
-
-            if (FrameBufferPtr > 0) {
-                /* Last data for this update, send it to the client */
-		if (VNC_WS_num != -1) {
-		    ws_server_send_bin_client(VNC_WS_num, (char *)FramebufferUpdate_msg, FrameBufferPtr);
-		}
-		if (vnc_client_connected) {
-                    if (send(vnc_client_sock, FramebufferUpdate_msg, FrameBufferPtr, 0) != FrameBufferPtr) {
-                    	goto wait_for_client;
-                    }
-		}
-
-                FrameBufferPtr = 0;
-            }
-
-        } else { /* if (num_updated_tiles) */
-            /* There was no new display data to send to the client */
-            /* Sleep for 1/20th second before checking again */
-	    vTaskDelay(20 / portTICK_PERIOD_MS);
-	}
-
-        /* Check for sound bell event */
-	if (xSemaphoreTake(SoundBell_lock, 10) == pdTRUE) {
-            if (SoundBellCount) {
-            	--SoundBellCount;
-		xSemaphoreGive(SoundBell_lock);
-
-		if (vnc_client_connected) {
-            	    if (send(vnc_client_sock, sound_bell, 1, 0) != 1) {
-                    	goto wait_for_client;
-            	    }
-		}
-		if (VNC_WS_num != -1) {
-		    ws_server_send_bin_client(VNC_WS_num, sound_bell, 1);
-		}
-            } else {
-	    	xSemaphoreGive(SoundBell_lock);
-	    }
-	}
-    }
-}
-
-
-
-/**
- * Convert a framebuffer pixel to BGR233 if needed.
- * @param pixel The 8 bit pixel value
- * @return Then unchanged or changed pixel.
- */
-vnc_color_t IRAM_ATTR PixelConvert(vnc_color_t pixel)
-{
-    if (!AltPixels)
-    	return pixel;
-
-    return (((pixel >> RED_SHIFT) & RED_MAX) << Red_Shift) | 
-	   (((pixel >> GREEN_SHIFT) & GREEN_MAX) << Green_Shift) | 
-	   (((pixel >> BLUE_SHIFT) & BLUE_MAX) << Blue_Shift);
-}
-
-
-
-/** 
- * @brief Generate tile update data function
- *
- *        This function is called by the frame_update thread to generate the message
- *        data for a tile to send to the client.  This function expects the
- *        x-position, y-position, width and height fields of the buffer to be filled
- *        in before it is called.
- *
- *        The format of the buffer is:
- *        packet_buffer[0:1] - x-position of tile
- *        packet_buffer[2:3] - y-position of tile
- *        packet_buffer[4:5] - width of tile
- *        packet_buffer[6:7] - height of tile
- *        packet_buffer[8 onwards] - Pixel data for the tile
- *
- *        The pixel data will be encoded with CoRRE encoding (if the CDL option is
- *        enabled and the client can handle it) or RAW encoding if that is smaller
- *        than CoRRE encoding for that particular tile.
- *
- * @param  packet_buffer  Buffer to store tile data
- * @return Length of generated data in bytes
- */
-static int GenTileUpdateData(uint8_t *packet_buffer)
-{
-    uint16_t		x_pos, y_pos;
-    int			i, j;
-    int			tile_width, tile_height;
-
-    /* Get the X and Y positions of this tile from the packet buffer */
-    x_pos = packet_buffer[0] * 256 + packet_buffer[1];
-    y_pos = packet_buffer[2] * 256 + packet_buffer[3];
-
-    /* Get the tile width and height from the packet buffer */
-    tile_width = packet_buffer[4] * 256 + packet_buffer[5];
-    tile_height = packet_buffer[6] * 256 + packet_buffer[7];
-
-    /* Create packet data using RAW encoding */
-    for (i = 0; i < tile_height; i++) {
-        for (j = 0; j < tile_width; j++) {
-	    if (Bits_Per_Pixel == 8) {
-             	packet_buffer[12 + tile_width * i + j] = PixelConvert(frame_buffer[y_pos + i][x_pos + j]);
-	    } else {
-		packet_buffer[12 + 2 * tile_width * i + 2*j]    = COLOUR2BYTE0(frame_buffer[y_pos + i][x_pos + j]);
-		packet_buffer[12 + 2 * tile_width * i + 2*j+ 1] = COLOUR2BYTE1(frame_buffer[y_pos + i][x_pos + j]);
-	    }
-        }
-    }
-
-    /* Set the encoding type to raw */
-    packet_buffer[8+0] = 0;
-    packet_buffer[8+1] = 0;
-    packet_buffer[8+2] = 0;
-    packet_buffer[8+3] = 0;
-
-    return (12 + tile_width*tile_height*(Bits_Per_Pixel/8));
-}
-
-
-
-/**
- * @brief Get message data function
- *        This function is called by the client_handler thread to get data
- *        from the client's socket.
- *
- * @param socket_fd    File descriptor of the socket to get the data from.
- * @param *buffer      Buffer to store received data in.
- * @param num_bytes    Number of bytes to attempt to get.
- *
- * @return  1 on sucessfull completion - 0 on error.
- */
-static int GetMessageData(int socket_fd, char *buffer, int num_bytes)
-{
-    int bytes_rxd;
-    int message_len = 0;
-
-    while (message_len < num_bytes) {
-        if ((bytes_rxd = recv(socket_fd, buffer, num_bytes, 0)) <= 0) {
-            return 0;
-        }
-        message_len += bytes_rxd;
-    }
-
-    return 1;
-}
-
-
-
-void VncCls(vnc_color_t color)
-{
-    /* Clear the frame buffer */
-    int i, j;
-
-    for (i = 0; i < CONFIG_VNC_SERVER_FRAME_HEIGHT; i++) {
-        for (j = 0; j < CONFIG_VNC_SERVER_FRAME_WIDTH; j++) {
-	    VncDrawPixel(j, i, color);
-        }
-    }
-}
-
-
-
-void IRAM_ATTR VncDrawPixel(uint16_t x, uint16_t y, vnc_color_t color)
-{
-    if (x >= CONFIG_VNC_SERVER_FRAME_WIDTH || y >= CONFIG_VNC_SERVER_FRAME_HEIGHT) {
-	printf("write_frame(%d, %d) tile %d/%d\n", x, y, x/TILE_SIZE, y/TILE_SIZE);
-	return;
-    }
-
-    /* Set that pixel to 'colour' */
-    frame_buffer[y][x] = color;
-
-    /* Mark the tile for update */
-    tile_updated[y/TILE_SIZE][x/TILE_SIZE] = 1;
-}
-
-
-
-void IRAM_ATTR VncDrawHorzLine(uint16_t x1, uint16_t x2, uint16_t y, vnc_color_t color)
-{
-    int i;
-
-    /* Draw the line */
-    for (i = x1; i <= x2; i++) {
-	VncDrawPixel(i, y, color);
-    }
-}
-
-
-
-void IRAM_ATTR VncDrawVertLine(uint16_t x, uint16_t y1, uint16_t y2, vnc_color_t color)
-{
-    int i;
-
-    /* Draw the line */
-    for (i = y1; i <= y2; i++) {
-	VncDrawPixel(x, i, color);
-    }
-}
-
-
-
-void IRAM_ATTR VncFillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, vnc_color_t color)
-{
-    /* Draw a solid rectangle */
-    int i, j;
-
-    for (i = y1; i <= y2; i++) {
-        for (j = x1; j <= x2; j++) {
-	    VncDrawPixel(j, i, color);
-        }
-    }
-}
-
-
-
-void VncSoundBell(void)
-{
-    if (xSemaphoreTake(SoundBell_lock, 10) == pdTRUE) {
-    	SoundBellCount++;
-	xSemaphoreGive(SoundBell_lock);
-    }
-}
-
-
-
-/**
- * @brief Websocket task. Created on a websocket connection.
- */
-void task_WS(void *pvParameter)
-{
-    int			i, j, num_of_encodings;
-    uint16_t		*ptr_to_uint16;
-    struct strMessage   _msg;
-
-    VNC_WS_run = true;
-
-    while (VNC_WS_run) {
-
-	/*
-	 * Wait until something is received from the client. Exit the queue receiver
-	 * each 5 milliseconds to allow to evaluate the VNC_WS_run flag and to allow
-	 * a clean exit of this task.
-	 */
-	if (xQueueReceive(message_queue, &_msg, 5 / portTICK_PERIOD_MS) == pdTRUE) {
-
-	    switch (_msg.message[0]) {
-
-	    	case SET_PIXEL_FORMAT:
-		    /* Check total message length */
-		    if (_msg.length >= 20) {
-			/* Check pixel format is as expected */
-			i = 0;
-			if (_msg.message[4] != BITS_PER_PIXEL) {
-			    ESP_LOGI(TAG, "SetPixelFormat client wants %d bits-per-pixel", _msg.message[4]);
-			    i++;
-			}
-
-			if (_msg.message[5] != PIXEL_DEPTH) {
-			    ESP_LOGI(TAG, "SetPixelFormat client wants %d pixel-depth", _msg.message[5]);
-			    i++;
-			}
-
-			if ((_msg.message[7] & 0x01) != TRUE_COLOUR_FLAG) {
-			    ESP_LOGI(TAG, "SetPixelFormat client wants %d true-colour-flag", _msg.message[7]);
-			    i++;
-			}
-
-			ptr_to_uint16 = (uint16_t *)&(_msg.message[8]);
-			if (htons(*ptr_to_uint16) != Red_Max) {
-			    Red_Max = htons(*ptr_to_uint16);
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d red-max", Red_Max);
-			}
-
-			ptr_to_uint16 = (uint16_t *)&(_msg.message[10]);
-			if (htons(*ptr_to_uint16) != Green_Max) {
-			    Green_Max = htons(*ptr_to_uint16);
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d green-max", Green_Max);
-			}
-
-			ptr_to_uint16 = (uint16_t *)&(_msg.message[12]);
-			if (htons(*ptr_to_uint16) != Blue_Max) {
-			    Blue_Max = htons(*ptr_to_uint16);
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d blue-max", Blue_Max);
-			}
-
-			if (_msg.message[14] != Red_Shift) {
-			    Red_Shift = _msg.message[14];
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d red-shift", Red_Shift);
-			}
-
-			if (_msg.message[15] != Green_Shift) {
-			    Green_Shift = _msg.message[15];
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d green-shift", Green_Shift);
-			}
-
-			if (_msg.message[16] != Blue_Shift) {
-			    Blue_Shift = _msg.message[16];
-			    AltPixels = true;
-			    ESP_LOGI(TAG, "SetPixelFormat client granted %d blue-shift", Blue_Shift);
-			}
-
-			if (i) {
-			    ESP_LOGI(TAG, "SetPixelFormat %d errors, disconnect client", i);
-			    ESP_LOGI(TAG, "Ensure the 'Auto select' is not enabled in your vncviewer options,");
-			    _msg.length = 0;
-			    ws_server_remove_client(VNC_WS_num);
-			}
-		    }
-		    break;
-
-	    	case FIX_COLOUR_MAP_ENTRIES:
-		    printf("FIX_COLOUR_MAP_ENTRIES\n");
-		    break;
-
-	    	case SET_ENCODINGS:
-		    if (_msg.length >= 3) {
-			// Get the total encodings
-			num_of_encodings = _msg.message[2]*255 + _msg.message[3];
-
-			/* Clear the encoding type structure */
-			encoding_type.raw = 0;
-			encoding_type.copy_rectangle = 0;
-			encoding_type.rre = 0;
-			encoding_type.corre = 0;
-			encoding_type.hextile = 0;
-
-			for (i = 0; i < num_of_encodings; i++) {
-			    switch(_msg.message[3 + (i*4)]) {
-				case 0:  /* Raw encoding */
-					encoding_type.raw = i + 1;
-					break;
-				case 1:  /* Copy rectangle encoding */
-					encoding_type.copy_rectangle = i + 1;
-					break;
-				case 2:  /* RRE encoding */
-					encoding_type.rre = i + 1;
-					break;
-				case 4:  /* CoRRE encoding */
-					encoding_type.corre = i + 1;
-					break;
-				case 5:  /* Hextile encoding */
-					encoding_type.hextile = i + 1;
-					break;
-				default:  /* Unknown coding type - do nothing */
-					break;
-			    }
-			}
-		    }
-		    break;
-
-	    	case FRAME_BUFFER_UPDATE_REQ:
-		    if (_msg.length == 10) {
-			if (!_msg.message[1]) {
-			    /* Non-incremental mode - mark the squares that need to be updated */
-			    for (i = (_msg.message[2]*255 + _msg.message[3])/TILE_SIZE;
-				i <= (_msg.message[2]*255 + _msg.message[3] + _msg.message[6]*255 + _msg.message[7])/TILE_SIZE;
-				i++) {
-				for (j = (_msg.message[4]*255 + _msg.message[5])/TILE_SIZE;
-				    j <= (_msg.message[4]*255 + _msg.message[5] + _msg.message[8]*255 + _msg.message[9])/TILE_SIZE;
-				    j++) {
-					tile_updated[j][i] = 1;
-				}
-			    }
-			}
-
-			/* Signal that there is now a pending update request */
-			xEventGroupSetBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ);
-		    }
-		    break;
-
-	    	case KEY_EVENT:
-		    printf("KEY_EVENT\n");
-		    /* Handle the key event, ignored for brewboard */
-		    /* Get the remainder of message (7 bytes) */
-		    break;
-
-	    	case POINTER_EVENT:
-		    /* Handle the pointer event, simulate the touch screen. */
-		    if (_msg.length == 6) {
-			/* Set global variables that will be read by another task. */
-			VNC_pointer_button = _msg.message[1];
-			VNC_pointer_x = _msg.message[2]*255 + _msg.message[3];
-			VNC_pointer_y = _msg.message[4]*255 + _msg.message[5];
-		    }
-		    _msg.length = 0;
-		    break;
-
-	    	case CLIENT_CUT_TEXT:
-		    printf("CLIENT_CUT_TEXT\n");
-		    break;
-
-	    	default:
-		    ESP_LOGI(TAG, "Unknown message %d from client", _msg.message[0]);
-	    }
-	}
-    }
-
-    VNC_WS_num = -1;
-    xEventGroupClearBits(xEventGroupVNC, VNC_CLIENT_UPDATE_REQ);
-    ESP_LOGI(TAG, "task_WS finished");
-    vTaskDelete(NULL);
-}
-
-
-
-int VncStartWS(int num)
-{
-    char		protocol_ver[8], message_buffer[MESSAGE_BUFFER_SIZE];
-    int			i, ProtocolOkay;
-    uint32_t		*ptr_to_uint32;
-    uint16_t		*ptr_to_uint16;
-    struct strMessage	_msg;
-
-    ESP_LOGI(TAG, "Start VNC WebSocket connection %d", num);
-    message_queue = xQueueCreate(message_queue_size, sizeof(struct strMessage));
-
-    /*
-     * Initial handshake
-     */
-    ws_server_send_bin_client(num, "RFB 003.003\n", 12);
-    ProtocolOkay = 1;
-    if (xQueueReceive(message_queue, &_msg, 5000 / portTICK_PERIOD_MS) == pdTRUE) {
-//	dump_msg((char *)_msg.message, _msg.length, "pull");
-
-	for (i = 0; i < 8; i++) {
-	    if (_msg.message[i] != server_ProtocolVersion[i]) {
-		ProtocolOkay = 0;
-	    }
-	    /* Store the protocol version - ignoring thr 'RFB ' part */
-	    protocol_ver[i] = _msg.message[i + 4];
-	}
-	protocol_ver[7] = 0;
-    } else {
-	ESP_LOGE(TAG, "Client timeout after initial message");
-	return -5;
-    }
-    
-    if (ProtocolOkay == 0) {
-	/* Generate the Bad ProtocolVerion message */
-	ESP_LOGI(TAG, "Start VNC WebSocket task failed, bad protocol.");
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-	*ptr_to_uint32 = htonl(0);
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[4]);
-	*ptr_to_uint32 = htonl(strlen(bad_protocol));
-	strcpy(&(message_buffer[8]), bad_protocol);
-	ws_server_send_bin_client(num, message_buffer, 8 + strlen(bad_protocol));
-	vTaskDelay(500 / portTICK_PERIOD_MS);
-	ws_server_remove_client(num);
-	return -2;
-    }
-    /* ProtocolVerion is okay - connect with no authentication*/
-
-    /* Server is busy with another client */
-    if (VNC_WS_run || vnc_client_connected) {
-	ESP_LOGI(TAG, "Start VNC WebSocket task failed, server busy.");
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-	*ptr_to_uint32 = htonl(0);
-	ptr_to_uint32 = (uint32_t *) &(message_buffer[4]);
-	*ptr_to_uint32 = htonl(strlen(server_busy));
-	strcpy(&(message_buffer[8]), server_busy);
-	ws_server_send_bin_client(num, message_buffer, 8 + strlen(server_busy));
-	vTaskDelay(500 / portTICK_PERIOD_MS);
-	ws_server_remove_client(num);
-	return -1;
-    }
-
-    /* Generate the No Authentication message */
-    ptr_to_uint32 = (uint32_t *) &(message_buffer[0]);
-    *ptr_to_uint32 = htonl((uint32_t)1);
-    ws_server_send_bin_client(num, message_buffer, 4);
-    /* Authentication - end */
-
-    /* ClientInitialisation - begin */
-    /* Receive initialisation message from client (1 byte) */
-    if (xQueueReceive(message_queue, &_msg, 5000 / portTICK_PERIOD_MS) == pdFALSE) {
-	ESP_LOGE(TAG, "Client timeout after auth message");
-	return -5;
-    }
-    /* Do nothing with this as we only support 1 Client at a time */
-    /* ClientInitialisation - end */
-
-    /* Initial default RGB332 */
-    Red_Max     = RED_MAX;
-    Green_Max   = GREEN_MAX;
-    Blue_Max    = BLUE_MAX;
-    Red_Shift   = RED_SHIFT;
-    Green_Shift = GREEN_SHIFT;
-    Blue_Shift  = BLUE_SHIFT;
-    AltPixels   = false;
-
-    /* ServerInitialisation - begin */
-    /* Create Initialisation message for client */
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[0]);
-    *ptr_to_uint16 = htons((uint16_t)CONFIG_VNC_SERVER_FRAME_WIDTH);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[2]);
-    *ptr_to_uint16 = htons((uint16_t)CONFIG_VNC_SERVER_FRAME_HEIGHT);
-
-    message_buffer[4] = (uint8_t)BITS_PER_PIXEL;
-    message_buffer[5] = (uint8_t)PIXEL_DEPTH;
-    message_buffer[6] = (uint8_t)BIG_ENDIAN_FLAG;
-    message_buffer[7] = (uint8_t)TRUE_COLOUR_FLAG;
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[8]);
-    *ptr_to_uint16 = htons(Red_Max);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[10]);
-    *ptr_to_uint16 = htons(Green_Max);
-
-    ptr_to_uint16 = (uint16_t *) &(message_buffer[12]);
-    *ptr_to_uint16 = htons(Blue_Max);
-
-    message_buffer[14] = Red_Shift;
-    message_buffer[15] = Green_Shift;
-    message_buffer[16] = Blue_Shift;
-
-    ptr_to_uint32 = (uint32_t *) &(message_buffer[20]);
-    *ptr_to_uint32 = htonl(strlen(desktop_name));
-    strcpy(&(message_buffer[24]), desktop_name);
-
-//  dump_msg(message_buffer, 24 + strlen(desktop_name), (char *)"send");
-    ws_server_send_bin_client(num, message_buffer, 24 + strlen(desktop_name));
-
-    /* ServerInitialisation - end */
-    ESP_LOGI(TAG, "VNC WebSocket client connected (RFB Protocol Ver: %s)", protocol_ver);
-
-    VNC_WS_num = num;
-    xTaskCreate(&task_WS, "WSclient",    MIN_STACK_SIZE, NULL, 5, &xTaskWSclient);
-    return 0;
-}
-
-
-
-void VncStopWS(int num)
-{
-    if (! VNC_WS_run) {
-	ESP_LOGI(TAG, "Stop VNC WebSocket, not running.");
-	return;
-    }
-
-    if (num != VNC_WS_num) {
-	ESP_LOGI(TAG, "Stop VNC WebSocket, %d is running, requested %d", VNC_WS_num, num);
-	return;
-    }
-
-    ESP_LOGI(TAG, "Stop VNC WebSocket task connection %d", num);
-    VNC_WS_run = false;
-    xQueueReset(message_queue);
-}
-
-
-
-void VncGetWSmessage(char *msg, uint16_t len)
-{
-    int			max;
-    struct strMessage	_msg;
- 
-    if (len == 0)
-	return;
-
-    max = len;
-    if (max > MESSAGE_BUFFER_SIZE) {
-	    ESP_LOGE(TAG, "VncGetWSmessage need %d bytes in a %d length buffer", len, MESSAGE_BUFFER_SIZE);
-	    max = MESSAGE_BUFFER_SIZE;
-    }
-
-    for (int i = 0; i < max; i++) {
-	    _msg.message[i] = msg[i];
-    }
-    _msg.length = max;
-    if (xQueueSendToBack(message_queue, &_msg, 200 / portTICK_PERIOD_MS) == pdFALSE) {
-	ESP_LOGE(TAG, "VncGetWSmessage() Queue full, message lost");
-    }
-}
-
--- a/components/vnc_server/vnc-server.h	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/**
- * @file vnc-server.h
- * @brief VNC server original written for eCos.
- *
- * The VNC server runs on the target platform and waits for a client 
- * (vncviewer program running on a PC) to connect via an ethernet connection
- * (port 5900). Once a client has connected, the target platform has a 
- * virtual screen, keyboard and mouse.
- *
- * This port of the VNC server has been designed with some limitations in 
- * order to keep memory and processor power requirements to a minimum.
- *
- * The VNC client must accept the settings that the VNC server suggests (bits-per-pixel, 
- * number-of-colours and so on as specified at build time with the eCos configuration 
- * tool) or the VNC server will just disconnect.
- *
- * The VNC server only supports CoRRE encoding and RAW encoding for sending 
- * display data to the client.
- *
- * The VNC server does not support password authentication, the client is able 
- * to connect without the user typing in a password.
- *
- * Only one VNC client may connect to the VNC server at a time.
- *
- * In reality these limitations are not a problem.
- *
- * @author Chris Garry <cgarry@sweeneydesign.co.uk>
- * @author Michiel Broek.
- */
-
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <sys/unistd.h>
-#include "lwip/sockets.h"
-#include "lwip/netdb.h"
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "freertos/semphr.h"
-#include "freertos/event_groups.h"
-
-
-
-/**
- * @brief Type to hold the frame format details
- */
-typedef struct
-{
-    uint16_t	frame_width;			///< Frame width
-    uint16_t	frame_height;			///< Frame height
-    void	*frame_buffer;			///< Frame buffer data
-    bool	rgb332;				///< 8 bits RGB format (only one is set).
-    bool	rgb555;				///< 15 bits RGB
-    bool	rgb565;				///< 16 bits RGB
-    bool	bgr233;				///< 8 bits BGR format
-    bool	truecolor0888;			///< 24 bits truecolor.
-} vnc_frame_format_t;
-
-
-
-typedef uint8_t vnc_color_t;
-
-
-
-/**
- * @brief Start the VNC server. Two tasks are started, one to handle the
- *        clients and one that serves the updates of the framebuffer.
- */
-void VncStartup(void);
-
-/**
- * @brief Clear the display and set a background color.
- * @param color Then RGB color for the background.
- */
-void  VncCls(vnc_color_t color);
-
-/**
- * @brief Draw a pixel on the display.
- * @param x The horizontal position of the pixel.
- * @param y The vertical position of the pixel.
- * @param color The RGB value of the pixel.
- */
-void VncDrawPixel(uint16_t x, uint16_t y, vnc_color_t color);
-
-/**
- * @brief Draw a horizontal line on the display.
- * @param x1 Start horizontal position.
- * @param x2 End of the horizontal position.
- * @param y The vertical position of the line.
- * @param color The RGB color of the line.
- */
-void VncDrawHorzLine(uint16_t x1, uint16_t x2, uint16_t y, vnc_color_t color);
-
-/**
- * @brief Draw a vertical line on the display.
- * @param x The jprizontal position of the line.
- * @param y1 The vertical top position of the line.
- * @param y2 The vertical bottom position of the line.
- * @param color The RGB color of the line.
- */
-void VncDrawVertLine(uint16_t x, uint16_t y1, uint16_t y2, vnc_color_t color);
-
-/**
- * @brief Fill a rectangle with the given color.
- * @param x1 The top-left horizontal start position.
- * @param y1 The top-left vertical start position.
- * @param x2 The bottom-right horizontal end position.
- * @param y2 The bottom-right vertical end position.
- * @param color The RGB color of the line.
- */
-void VncFillRect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, vnc_color_t color);
-
-/**
- * @brief Sound the bell on the client computer.
- */
-void VncSoundBell(void);
-
-
-/**
- * @brief Macro to convert from RGB to colour values
- */
-#define VNC_RGB2COL(r,g,b) (vnc_color_t)(((((uint8_t)r)&0xE0) >> 0) | ((((uint8_t)g)&0xE0) >> 3) | ((((uint8_t)b)&0xC0) >> 6))
-
-
-/**
- * @brief Start task for a websocket client.
- */
-int VncStartWS(int num);
-
-/**
- * @brief Stop task for a websocket client.
- */
-void VncStopWS(int num);
-
-/**
- * @brief Remote websocket message to the VNC server.
- */
-void VncGetWSmessage(char *msg, uint16_t len);
-
--- a/image/files.list	Thu May 02 11:52:36 2019 +0200
+++ b/image/files.list	Wed May 08 15:46:50 2019 +0200
@@ -3,73 +3,13 @@
 fonts/Grotesk24x48.fon
 fonts/SmallFont.fon
 fonts/Ubuntu.fon
-w/app/error-handler.js.gz
-w/app/localization.js.gz
-w/app/ui.js.gz
-w/app/webutil.js.gz
-w/app/images/clipboard.svg.gz
-w/app/images/connect.svg.gz
-w/app/images/disconnect.svg.gz
-w/app/images/drag.svg.gz
-w/app/images/error.svg.gz
-w/app/images/expander.svg.gz
-w/app/images/fullscreen.svg.gz
-w/app/images/handle.svg.gz
-w/app/images/handle_bg.svg.gz
-w/app/images/info.svg.gz
-w/app/images/mouse_left.svg.gz
-w/app/images/mouse_middle.svg.gz
-w/app/images/mouse_none.svg.gz
-w/app/images/mouse_right.svg.gz
-w/app/images/settings.svg.gz
-w/app/images/warning.svg.gz
-w/app/locale/de.json
-w/app/locale/el.json
-w/app/locale/es.json
-w/app/locale/nl.json
-w/app/locale/pl.json
-w/app/locale/sv.json
-w/app/locale/tr.json
-w/app/locale/zh.json
-w/app/sounds/bell.mp3
-w/app/sounds/bell.oga
-w/app/styles/base.css
-w/app/styles/web.css
-w/core/base64.js.gz
-w/core/des.js.gz
-w/core/display.js.gz
-w/core/encodings.js.gz
-w/core/inflator.js.gz
-w/core/rfb.js.gz
-w/core/websock.js.gz
-w/core/input/mouse.js.gz
-w/core/util/browser.js.gz
-w/core/util/events.js.gz
-w/core/util/eventtarget.js.gz
-w/core/util/logging.js.gz
-w/core/util/polyfill.js.gz
-w/core/util/strings.js.gz
-w/css/style.css
+w/css/web.css
+w/css/webui.css
 w/js/Chart.min.js.gz
 w/js/ch-plug-anno.min.js.gz
 w/js/jquery-1.12.4.min.js.gz
 w/js/webui.js
-w/js/modl/babel.js.gz
-w/js/modl/brloader.js.gz
-w/js/utils/common.js.gz
-w/js/zlib/adler32.js.gz
-w/js/zlib/constants.js.gz
-w/js/zlib/crc32.js.gz
-w/js/zlib/deflate.js.gz
-w/js/zlib/gzheader.js.gz
-w/js/zlib/inffast.js.gz
-w/js/zlib/inflate.js.gz
-w/js/zlib/inftrees.js.gz
-w/js/zlib/messages.js.gz
-w/js/zlib/trees.js.gz
-w/js/zlib/zstream.js.gz
 w/chart.html
 w/index.html.gz
 w/logs.html
-w/vnc.html.gz
 w/webui.html
--- a/image/version.txt	Thu May 02 11:52:36 2019 +0200
+++ b/image/version.txt	Wed May 08 15:46:50 2019 +0200
@@ -1,1 +1,1 @@
-0.0.g
+0.1.cp
Binary file image/w/app/error-handler.js.gz has changed
Binary file image/w/app/images/clipboard.svg.gz has changed
Binary file image/w/app/images/connect.svg.gz has changed
Binary file image/w/app/images/disconnect.svg.gz has changed
Binary file image/w/app/images/drag.svg.gz has changed
Binary file image/w/app/images/error.svg.gz has changed
Binary file image/w/app/images/expander.svg.gz has changed
Binary file image/w/app/images/fullscreen.svg.gz has changed
Binary file image/w/app/images/handle.svg.gz has changed
Binary file image/w/app/images/handle_bg.svg.gz has changed
Binary file image/w/app/images/info.svg.gz has changed
Binary file image/w/app/images/mouse_left.svg.gz has changed
Binary file image/w/app/images/mouse_middle.svg.gz has changed
Binary file image/w/app/images/mouse_none.svg.gz has changed
Binary file image/w/app/images/mouse_right.svg.gz has changed
Binary file image/w/app/images/settings.svg.gz has changed
Binary file image/w/app/images/warning.svg.gz has changed
--- a/image/w/app/locale/de.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-{
-    "Connecting...": "Verbinden...",
-    "Disconnecting...": "Verbindung trennen...",
-    "Reconnecting...": "Verbindung wiederherstellen...",
-    "Internal error": "Interner Fehler",
-    "Must set host": "Richten Sie den Server ein",
-    "Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ",
-    "Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ",
-    "Something went wrong, connection is closed": "Etwas lief schief, Verbindung wurde getrennt",
-    "Disconnected": "Verbindung zum Server getrennt",
-    "New connection has been rejected with reason: ": "Verbindung wurde aus folgendem Grund abgelehnt: ",
-    "New connection has been rejected": "Verbindung wurde abgelehnt",
-    "Password is required": "Passwort ist erforderlich",
-    "noVNC encountered an error:": "Ein Fehler ist aufgetreten:",
-    "Hide/Show the control bar": "Kontrollleiste verstecken/anzeigen",
-    "Move/Drag Viewport": "Ansichtsfenster verschieben/ziehen",
-    "viewport drag": "Ansichtsfenster ziehen",
-    "Active Mouse Button": "Aktive Maustaste",
-    "No mousebutton": "Keine Maustaste",
-    "Left mousebutton": "Linke Maustaste",
-    "Middle mousebutton": "Mittlere Maustaste",
-    "Right mousebutton": "Rechte Maustaste",
-    "Keyboard": "Tastatur",
-    "Show Keyboard": "Tastatur anzeigen",
-    "Extra keys": "Zusatztasten",
-    "Show Extra Keys": "Zusatztasten anzeigen",
-    "Ctrl": "Strg",
-    "Toggle Ctrl": "Strg umschalten",
-    "Alt": "Alt",
-    "Toggle Alt": "Alt umschalten",
-    "Send Tab": "Tab senden",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "Escape senden",
-    "Ctrl+Alt+Del": "Strg+Alt+Entf",
-    "Send Ctrl-Alt-Del": "Strg+Alt+Entf senden",
-    "Shutdown/Reboot": "Herunterfahren/Neustarten",
-    "Shutdown/Reboot...": "Herunterfahren/Neustarten...",
-    "Power": "Energie",
-    "Shutdown": "Herunterfahren",
-    "Reboot": "Neustarten",
-    "Reset": "Zurücksetzen",
-    "Clipboard": "Zwischenablage",
-    "Clear": "Löschen",
-    "Fullscreen": "Vollbild",
-    "Settings": "Einstellungen",
-    "Shared Mode": "Geteilter Modus",
-    "View Only": "Nur betrachten",
-    "Clip to Window": "Auf Fenster begrenzen",
-    "Scaling Mode:": "Skalierungsmodus:",
-    "None": "Keiner",
-    "Local Scaling": "Lokales skalieren",
-    "Remote Resizing": "Serverseitiges skalieren",
-    "Advanced": "Erweitert",
-    "Repeater ID:": "Repeater ID:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Verschlüsselt",
-    "Host:": "Server:",
-    "Port:": "Port:",
-    "Path:": "Pfad:",
-    "Automatic Reconnect": "Automatisch wiederverbinden",
-    "Reconnect Delay (ms):": "Wiederverbindungsverzögerung (ms):",
-    "Logging:": "Protokollierung:",
-    "Disconnect": "Verbindung trennen",
-    "Connect": "Verbinden",
-    "Password:": "Passwort:",
-    "Cancel": "Abbrechen",
-    "Canvas not supported.": "Canvas nicht unterstützt."
-}
\ No newline at end of file
--- a/image/w/app/locale/el.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-{
-    "Connecting...": "Συνδέεται...",
-    "Disconnecting...": "Aποσυνδέεται...",
-    "Reconnecting...": "Επανασυνδέεται...",
-    "Internal error": "Εσωτερικό σφάλμα",
-    "Must set host": "Πρέπει να οριστεί ο διακομιστής",
-    "Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ",
-    "Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ",
-    "Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε",
-    "Disconnected": "Αποσυνδέθηκε",
-    "New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ",
-    "New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ",
-    "Password is required": "Απαιτείται ο κωδικός πρόσβασης",
-    "noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:",
-    "Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου",
-    "Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου",
-    "viewport drag": "σύρσιμο θεατού πεδίου",
-    "Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού",
-    "No mousebutton": "Χωρίς Πλήκτρο Ποντικιού",
-    "Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού",
-    "Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού",
-    "Right mousebutton": "Δεξί Πλήκτρο Ποντικιού",
-    "Keyboard": "Πληκτρολόγιο",
-    "Show Keyboard": "Εμφάνιση Πληκτρολογίου",
-    "Extra keys": "Επιπλέον πλήκτρα",
-    "Show Extra Keys": "Εμφάνιση Επιπλέον Πλήκτρων",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Εναλλαγή Ctrl",
-    "Alt": "Alt",
-    "Toggle Alt": "Εναλλαγή Alt",
-    "Send Tab": "Αποστολή Tab",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "Αποστολή Escape",
-    "Ctrl+Alt+Del": "Ctrl+Alt+Del",
-    "Send Ctrl-Alt-Del": "Αποστολή Ctrl-Alt-Del",
-    "Shutdown/Reboot": "Κλείσιμο/Επανεκκίνηση",
-    "Shutdown/Reboot...": "Κλείσιμο/Επανεκκίνηση...",
-    "Power": "Απενεργοποίηση",
-    "Shutdown": "Κλείσιμο",
-    "Reboot": "Επανεκκίνηση",
-    "Reset": "Επαναφορά",
-    "Clipboard": "Πρόχειρο",
-    "Clear": "Καθάρισμα",
-    "Fullscreen": "Πλήρης Οθόνη",
-    "Settings": "Ρυθμίσεις",
-    "Shared Mode": "Κοινόχρηστη Λειτουργία",
-    "View Only": "Μόνο Θέαση",
-    "Clip to Window": "Αποκοπή στο όριο του Παράθυρου",
-    "Scaling Mode:": "Λειτουργία Κλιμάκωσης:",
-    "None": "Καμία",
-    "Local Scaling": "Τοπική Κλιμάκωση",
-    "Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους",
-    "Advanced": "Για προχωρημένους",
-    "Repeater ID:": "Repeater ID:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Κρυπτογράφηση",
-    "Host:": "Όνομα διακομιστή:",
-    "Port:": "Πόρτα διακομιστή:",
-    "Path:": "Διαδρομή:",
-    "Automatic Reconnect": "Αυτόματη επανασύνδεση",
-    "Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):",
-    "Logging:": "Καταγραφή:",
-    "Disconnect": "Αποσύνδεση",
-    "Connect": "Σύνδεση",
-    "Password:": "Κωδικός Πρόσβασης:",
-    "Cancel": "Ακύρωση",
-    "Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas"
-}
\ No newline at end of file
--- a/image/w/app/locale/es.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-{
-    "Connecting...": "Conectando...",
-    "Connected (encrypted) to ": "Conectado (con encriptación) a",
-    "Connected (unencrypted) to ": "Conectado (sin encriptación) a",
-    "Disconnecting...": "Desconectando...",
-    "Disconnected": "Desconectado",
-    "Must set host": "Debes configurar el host",
-    "Reconnecting...": "Reconectando...",
-    "Password is required": "Contraseña es obligatoria",
-    "Disconnect timeout": "Tiempo de desconexión agotado",
-    "noVNC encountered an error:": "noVNC ha encontrado un error:",
-    "Hide/Show the control bar": "Ocultar/Mostrar la barra de control",
-    "Move/Drag Viewport": "Mover/Arrastrar la ventana",
-    "viewport drag": "Arrastrar la ventana",
-    "Active Mouse Button": "Botón activo del ratón",
-    "No mousebutton": "Ningún botón del ratón",
-    "Left mousebutton": "Botón izquierdo del ratón",
-    "Middle mousebutton": "Botón central del ratón",
-    "Right mousebutton": "Botón derecho del ratón",
-    "Keyboard": "Teclado",
-    "Show Keyboard": "Mostrar teclado",
-    "Extra keys": "Teclas adicionales",
-    "Show Extra Keys": "Mostrar Teclas Adicionales",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Pulsar/Soltar Ctrl",
-    "Alt": "Alt",
-    "Toggle Alt": "Pulsar/Soltar Alt",
-    "Send Tab": "Enviar Tabulación",
-    "Tab": "Tabulación",
-    "Esc": "Esc",
-    "Send Escape": "Enviar Escape",
-    "Ctrl+Alt+Del": "Ctrl+Alt+Del",
-    "Send Ctrl-Alt-Del": "Enviar Ctrl+Alt+Del",
-    "Shutdown/Reboot": "Apagar/Reiniciar",
-    "Shutdown/Reboot...": "Apagar/Reiniciar...",
-    "Power": "Encender",
-    "Shutdown": "Apagar",
-    "Reboot": "Reiniciar",
-    "Reset": "Restablecer",
-    "Clipboard": "Portapapeles",
-    "Clear": "Vaciar",
-    "Fullscreen": "Pantalla Completa",
-    "Settings": "Configuraciones",
-    "Shared Mode": "Modo Compartido",
-    "View Only": "Solo visualización",
-    "Clip to Window": "Recortar al tamaño de la ventana",
-    "Scaling Mode:": "Modo de escalado:",
-    "None": "Ninguno",
-    "Local Scaling": "Escalado Local",
-    "Local Downscaling": "Reducción de escala local",
-    "Remote Resizing": "Cambio de tamaño remoto",
-    "Advanced": "Avanzado",
-    "Local Cursor": "Cursor Local",
-    "Repeater ID:": "ID del Repetidor",
-    "WebSocket": "WebSocket",
-    "Encrypt": "",
-    "Host:": "Host",
-    "Port:": "Puesto",
-    "Path:": "Ruta",
-    "Automatic Reconnect": "Reconexión automática",
-    "Reconnect Delay (ms):": "Retraso en la reconexión (ms)",
-    "Logging:": "Logging",
-    "Disconnect": "Desconectar",
-    "Connect": "Conectar",
-    "Password:": "Contraseña",
-    "Cancel": "Cancelar",
-    "Canvas not supported.": "Canvas no está soportado"
-}
\ No newline at end of file
--- a/image/w/app/locale/nl.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-{
-    "Connecting...": "Verbinden...",
-    "Connected (encrypted) to ": "Verbonden (versleuteld) met ",
-    "Connected (unencrypted) to ": "Verbonden (onversleuteld) met ",
-    "Disconnecting...": "Verbinding verbreken...",
-    "Disconnected": "Verbinding verbroken",
-    "Must set host": "Host moeten worden ingesteld",
-    "Reconnecting...": "Opnieuw verbinding maken...",
-    "Password is required": "Wachtwoord is vereist",
-    "Disconnect timeout": "Timeout tijdens verbreken van verbinding",
-    "noVNC encountered an error:": "noVNC heeft een fout bemerkt:",
-    "Hide/Show the control bar": "Verberg/Toon de bedieningsbalk",
-    "Move/Drag Viewport": "Verplaats/Versleep Kijkvenster",
-    "viewport drag": "kijkvenster slepen",
-    "Active Mouse Button": "Actieve Muisknop",
-    "No mousebutton": "Geen muisknop",
-    "Left mousebutton": "Linker muisknop",
-    "Middle mousebutton": "Middelste muisknop",
-    "Right mousebutton": "Rechter muisknop",
-    "Keyboard": "Toetsenbord",
-    "Show Keyboard": "Toon Toetsenbord",
-    "Extra keys": "Extra toetsen",
-    "Show Extra Keys": "Toon Extra Toetsen",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Ctrl aan/uitzetten",
-    "Alt": "Alt",
-    "Toggle Alt": "Alt aan/uitzetten",
-    "Send Tab": "Tab Sturen",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "Escape Sturen",
-    "Ctrl+Alt+Del": "Ctrl-Alt-Del",
-    "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Sturen",
-    "Shutdown/Reboot": "Uitschakelen/Herstarten",
-    "Shutdown/Reboot...": "Uitschakelen/Herstarten...",
-    "Power": "Systeem",
-    "Shutdown": "Uitschakelen",
-    "Reboot": "Herstarten",
-    "Reset": "Resetten",
-    "Clipboard": "Klembord",
-    "Clear": "Wissen",
-    "Fullscreen": "Volledig Scherm",
-    "Settings": "Instellingen",
-    "Shared Mode": "Gedeelde Modus",
-    "View Only": "Alleen Kijken",
-    "Clip to Window": "Randen buiten venster afsnijden",
-    "Scaling Mode:": "Schaalmodus:",
-    "None": "Geen",
-    "Local Scaling": "Lokaal Schalen",
-    "Local Downscaling": "Lokaal Neerschalen",
-    "Remote Resizing": "Op Afstand Formaat Wijzigen",
-    "Advanced": "Geavanceerd",
-    "Local Cursor": "Lokale Cursor",
-    "Repeater ID:": "Repeater ID:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Versleutelen",
-    "Host:": "Host:",
-    "Port:": "Poort:",
-    "Path:": "Pad:",
-    "Automatic Reconnect": "Automatisch Opnieuw Verbinden",
-    "Reconnect Delay (ms):": "Vertraging voor Opnieuw Verbinden (ms):",
-    "Logging:": "Logmeldingen:",
-    "Disconnect": "Verbinding verbreken",
-    "Connect": "Verbinden",
-    "Password:": "Wachtwoord:",
-    "Cancel": "Annuleren",
-    "Canvas not supported.": "Canvas wordt niet ondersteund."
-}
\ No newline at end of file
--- a/image/w/app/locale/pl.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-{
-    "Connecting...": "Łączenie...",
-    "Disconnecting...": "Rozłączanie...",
-    "Reconnecting...": "Łączenie...",
-    "Internal error": "Błąd wewnętrzny",
-    "Must set host": "Host i port są wymagane",
-    "Connected (encrypted) to ": "Połączenie (szyfrowane) z ",
-    "Connected (unencrypted) to ": "Połączenie (nieszyfrowane) z ",
-    "Something went wrong, connection is closed": "Coś poszło źle, połączenie zostało zamknięte",
-    "Disconnected": "Rozłączony",
-    "New connection has been rejected with reason: ": "Nowe połączenie zostało odrzucone z powodu: ",
-    "New connection has been rejected": "Nowe połączenie zostało odrzucone",
-    "Password is required": "Hasło jest wymagane",
-    "noVNC encountered an error:": "noVNC napotkało błąd:",
-    "Hide/Show the control bar": "Pokaż/Ukryj pasek ustawień",
-    "Move/Drag Viewport": "Ruszaj/Przeciągaj Viewport",
-    "viewport drag": "przeciągnij viewport",
-    "Active Mouse Button": "Aktywny Przycisk Myszy",
-    "No mousebutton": "Brak przycisku myszy",
-    "Left mousebutton": "Lewy przycisk myszy",
-    "Middle mousebutton": "Środkowy przycisk myszy",
-    "Right mousebutton": "Prawy przycisk myszy",
-    "Keyboard": "Klawiatura",
-    "Show Keyboard": "Pokaż klawiaturę",
-    "Extra keys": "Przyciski dodatkowe",
-    "Show Extra Keys": "Pokaż przyciski dodatkowe",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Przełącz Ctrl",
-    "Alt": "Alt",
-    "Toggle Alt": "Przełącz Alt",
-    "Send Tab": "Wyślij Tab",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "Wyślij Escape",
-    "Ctrl+Alt+Del": "Ctrl+Alt+Del",
-    "Send Ctrl-Alt-Del": "Wyślij Ctrl-Alt-Del",
-    "Shutdown/Reboot": "Wyłącz/Uruchom ponownie",
-    "Shutdown/Reboot...": "Wyłącz/Uruchom ponownie...",
-    "Power": "Włączony",
-    "Shutdown": "Wyłącz",
-    "Reboot": "Uruchom ponownie",
-    "Reset": "Resetuj",
-    "Clipboard": "Schowek",
-    "Clear": "Wyczyść",
-    "Fullscreen": "Pełny ekran",
-    "Settings": "Ustawienia",
-    "Shared Mode": "Tryb Współdzielenia",
-    "View Only": "Tylko Podgląd",
-    "Clip to Window": "Przytnij do Okna",
-    "Scaling Mode:": "Tryb Skalowania:",
-    "None": "Brak",
-    "Local Scaling": "Skalowanie lokalne",
-    "Remote Resizing": "Skalowanie zdalne",
-    "Advanced": "Zaawansowane",
-    "Repeater ID:": "ID Repeatera:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Szyfrowanie",
-    "Host:": "Host:",
-    "Port:": "Port:",
-    "Path:": "Ścieżka:",
-    "Automatic Reconnect": "Automatycznie wznawiaj połączenie",
-    "Reconnect Delay (ms):": "Opóźnienie wznawiania (ms):",
-    "Logging:": "Poziom logowania:",
-    "Disconnect": "Rozłącz",
-    "Connect": "Połącz",
-    "Password:": "Hasło:",
-    "Cancel": "Anuluj",
-    "Canvas not supported.": "Element Canvas nie jest wspierany."
-}
\ No newline at end of file
--- a/image/w/app/locale/sv.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-{
-    "Connecting...": "Ansluter...",
-    "Connected (encrypted) to ": "Ansluten (krypterat) till ",
-    "Connected (unencrypted) to ": "Ansluten (okrypterat) till ",
-    "Disconnecting...": "Kopplar ner...",
-    "Disconnected": "Frånkopplad",
-    "Must set host": "Du måste specifiera en värd",
-    "Reconnecting...": "Återansluter...",
-    "Password is required": "Lösenord krävs",
-    "Disconnect timeout": "Det tog för lång tid att koppla ner",
-    "noVNC encountered an error:": "noVNC stötte på ett problem:",
-    "Hide/Show the control bar": "Göm/Visa kontrollbaren",
-    "Move/Drag Viewport": "Flytta/Dra Vyn",
-    "viewport drag": "dra vy",
-    "Active Mouse Button": "Aktiv musknapp",
-    "No mousebutton": "Ingen musknapp",
-    "Left mousebutton": "Vänster musknapp",
-    "Middle mousebutton": "Mitten-musknapp",
-    "Right mousebutton": "Höger musknapp",
-    "Keyboard": "Tangentbord",
-    "Show Keyboard": "Visa Tangentbord",
-    "Extra keys": "Extraknappar",
-    "Show Extra Keys": "Visa Extraknappar",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Växla Ctrl",
-    "Alt": "Alt",
-    "Toggle Alt": "Växla Alt",
-    "Send Tab": "Skicka Tab",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "Skicka Escape",
-    "Ctrl+Alt+Del": "Ctrl+Alt+Del",
-    "Send Ctrl-Alt-Del": "Skicka Ctrl-Alt-Del",
-    "Shutdown/Reboot": "Stäng av/Boota om",
-    "Shutdown/Reboot...": "Stäng av/Boota om...",
-    "Power": "Ström",
-    "Shutdown": "Stäng av",
-    "Reboot": "Boota om",
-    "Reset": "Återställ",
-    "Clipboard": "Urklipp",
-    "Clear": "Rensa",
-    "Fullscreen": "Fullskärm",
-    "Settings": "Inställningar",
-    "Shared Mode": "Delat Läge",
-    "View Only": "Endast Visning",
-    "Clip to Window": "Begränsa till Fönster",
-    "Scaling Mode:": "Skalningsläge:",
-    "None": "Ingen",
-    "Local Scaling": "Lokal Skalning",
-    "Local Downscaling": "Lokal Nedskalning",
-    "Remote Resizing": "Ändra Storlek",
-    "Advanced": "Avancerat",
-    "Local Cursor": "Lokal Muspekare",
-    "Repeater ID:": "Repeater-ID:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Kryptera",
-    "Host:": "Värd:",
-    "Port:": "Port:",
-    "Path:": "Sökväg:",
-    "Automatic Reconnect": "Automatisk Återanslutning",
-    "Reconnect Delay (ms):": "Fördröjning (ms):",
-    "Logging:": "Loggning:",
-    "Disconnect": "Koppla från",
-    "Connect": "Anslut",
-    "Password:": "Lösenord:",
-    "Cancel": "Avbryt",
-    "Canvas not supported.": "Canvas stöds ej"
-}
\ No newline at end of file
--- a/image/w/app/locale/tr.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-{
-    "Connecting...": "Bağlanıyor...",
-    "Disconnecting...": "Bağlantı kesiliyor...",
-    "Reconnecting...": "Yeniden bağlantı kuruluyor...",
-    "Internal error": "İç hata",
-    "Must set host": "Sunucuyu kur",
-    "Connected (encrypted) to ": "Bağlı (şifrelenmiş)",
-    "Connected (unencrypted) to ": "Bağlandı (şifrelenmemiş)",
-    "Something went wrong, connection is closed": "Bir şeyler ters gitti, bağlantı kesildi",
-    "Disconnected": "Bağlantı kesildi",
-    "New connection has been rejected with reason: ": "Bağlantı aşağıdaki nedenlerden dolayı reddedildi: ",
-    "New connection has been rejected": "Bağlantı reddedildi",
-    "Password is required": "Şifre gerekli",
-    "noVNC encountered an error:": "Bir hata oluştu:",
-    "Hide/Show the control bar": "Denetim masasını Gizle/Göster",
-    "Move/Drag Viewport": "Görünümü Taşı/Sürükle",
-    "viewport drag": "Görüntü penceresini sürükle",
-    "Active Mouse Button": "Aktif Fare Düğmesi",
-    "No mousebutton": "Fare düğmesi yok",
-    "Left mousebutton": "Farenin sol düğmesi",
-    "Middle mousebutton": "Farenin orta düğmesi",
-    "Right mousebutton": "Farenin sağ düğmesi",
-    "Keyboard": "Klavye",
-    "Show Keyboard": "Klavye Düzenini Göster",
-    "Extra keys": "Ekstra tuşlar",
-    "Show Extra Keys": "Ekstra tuşları göster",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "Ctrl Değiştir ",
-    "Alt": "Alt",
-    "Toggle Alt": "Alt Değiştir",
-    "Send Tab": "Sekme Gönder",
-    "Tab": "Sekme",
-    "Esc": "Esc",
-    "Send Escape": "Boşluk Gönder",
-    "Ctrl+Alt+Del": "Ctrl + Alt + Del",
-    "Send Ctrl-Alt-Del": "Ctrl-Alt-Del Gönder",
-    "Shutdown/Reboot": "Kapat/Yeniden Başlat",
-    "Shutdown/Reboot...": "Kapat/Yeniden Başlat...",
-    "Power": "Güç",
-    "Shutdown": "Kapat",
-    "Reboot": "Yeniden Başlat",
-    "Reset": "Sıfırla",
-    "Clipboard": "Pano",
-    "Clear": "Temizle",
-    "Fullscreen": "Tam Ekran",
-    "Settings": "Ayarlar",
-    "Shared Mode": "Paylaşım Modu",
-    "View Only": "Sadece Görüntüle",
-    "Clip to Window": "Pencereye Tıkla",
-    "Scaling Mode:": "Ölçekleme Modu:",
-    "None": "Bilinmeyen",
-    "Local Scaling": "Yerel Ölçeklendirme",
-    "Remote Resizing": "Uzaktan Yeniden Boyutlandırma",
-    "Advanced": "Gelişmiş",
-    "Repeater ID:": "Tekralayıcı ID:",
-    "WebSocket": "WebSocket",
-    "Encrypt": "Şifrele",
-    "Host:": "Ana makine:",
-    "Port:": "Port:",
-    "Path:": "Yol:",
-    "Automatic Reconnect": "Otomatik Yeniden Bağlan",
-    "Reconnect Delay (ms):": "Yeniden Bağlanma Süreci (ms):",
-    "Logging:": "Giriş yapılıyor:",
-    "Disconnect": "Bağlantıyı Kes",
-    "Connect": "Bağlan",
-    "Password:": "Parola:",
-    "Cancel": "Vazgeç",
-    "Canvas not supported.": "Tuval desteklenmiyor."
-}
\ No newline at end of file
--- a/image/w/app/locale/zh.json	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-{
-    "Connecting...": "連線中...",
-    "Disconnecting...": "正在中斷連線...",
-    "Reconnecting...": "重新連線中...",
-    "Internal error": "內部錯誤",
-    "Must set host": "請提供主機資訊",
-    "Connected (encrypted) to ": "已加密連線到",
-    "Connected (unencrypted) to ": "未加密連線到",
-    "Something went wrong, connection is closed": "發生錯誤,連線已關閉",
-    "Failed to connect to server": "無法連線到伺服器",
-    "Disconnected": "連線已中斷",
-    "New connection has been rejected with reason: ": "連線被拒絕,原因:",
-    "New connection has been rejected": "連線被拒絕",
-    "Password is required": "請提供密碼",
-    "noVNC encountered an error:": "noVNC 遇到一個錯誤:",
-    "Hide/Show the control bar": "顯示/隱藏控制列",
-    "Move/Drag Viewport": "拖放顯示範圍",
-    "viewport drag": "顯示範圍拖放",
-    "Active Mouse Button": "啟用滑鼠按鍵",
-    "No mousebutton": "無滑鼠按鍵",
-    "Left mousebutton": "滑鼠左鍵",
-    "Middle mousebutton": "滑鼠中鍵",
-    "Right mousebutton": "滑鼠右鍵",
-    "Keyboard": "鍵盤",
-    "Show Keyboard": "顯示鍵盤",
-    "Extra keys": "額外按鍵",
-    "Show Extra Keys": "顯示額外按鍵",
-    "Ctrl": "Ctrl",
-    "Toggle Ctrl": "切換 Ctrl",
-    "Alt": "Alt",
-    "Toggle Alt": "切換 Alt",
-    "Send Tab": "送出 Tab 鍵",
-    "Tab": "Tab",
-    "Esc": "Esc",
-    "Send Escape": "送出 Escape 鍵",
-    "Ctrl+Alt+Del": "Ctrl-Alt-Del",
-    "Send Ctrl-Alt-Del": "送出 Ctrl-Alt-Del 快捷鍵",
-    "Shutdown/Reboot": "關機/重新啟動",
-    "Shutdown/Reboot...": "關機/重新啟動...",
-    "Power": "電源",
-    "Shutdown": "關機",
-    "Reboot": "重新啟動",
-    "Reset": "重設",
-    "Clipboard": "剪貼簿",
-    "Clear": "清除",
-    "Fullscreen": "全螢幕",
-    "Settings": "設定",
-    "Shared Mode": "分享模式",
-    "View Only": "僅檢視",
-    "Clip to Window": "限制/裁切視窗大小",
-    "Scaling Mode:": "縮放模式:",
-    "None": "無",
-    "Local Scaling": "本機縮放",
-    "Remote Resizing": "遠端調整大小",
-    "Advanced": "進階",
-    "Repeater ID:": "中繼站 ID",
-    "WebSocket": "WebSocket",
-    "Encrypt": "加密",
-    "Host:": "主機:",
-    "Port:": "連接埠:",
-    "Path:": "路徑:",
-    "Automatic Reconnect": "自動重新連線",
-    "Reconnect Delay (ms):": "重新連線間隔 (ms):",
-    "Logging:": "日誌級別:",
-    "Disconnect": "中斷連線",
-    "Connect": "連線",
-    "Password:": "密碼:",
-    "Cancel": "取消"
-}
\ No newline at end of file
Binary file image/w/app/localization.js.gz has changed
Binary file image/w/app/sounds/bell.mp3 has changed
Binary file image/w/app/sounds/bell.oga has changed
--- a/image/w/app/styles/base.css	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,893 +0,0 @@
-/*
- * noVNC base CSS
- * Copyright (C) 2012 Joel Martin
- * Copyright (C) 2016 Samuel Mannehed for Cendio AB
- * Copyright (C) 2016 Pierre Ossman for Cendio AB
- * noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
- * This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
- */
-
-/*
- * Z index layers:
- *
- * 0: Main screen
- * 10: Control bar
- * 50: Transition blocker
- * 60: Connection popups
- * 100: Status bar
- * ...
- * 1000: Javascript crash
- * ...
- * 10000: Max (used for polyfills)
- */
-
-body {
-  margin:0;
-  padding:0;
-  font-family: Helvetica;
-  /*Background image with light grey curve.*/
-  background-color:#494949;
-  background-repeat:no-repeat;
-  background-position:right bottom;
-  height:100%;
-  touch-action: none;
-}
-
-html {
-  height:100%;
-}
-
-.noVNC_only_touch.noVNC_hidden {
-  display: none;
-}
-
-.noVNC_disabled {
-  color: rgb(128, 128, 128);
-}
-
-/* ----------------------------------------
- * Spinner
- * ----------------------------------------
- */
-
-.noVNC_spinner {
-  position: relative;
-}
-.noVNC_spinner, .noVNC_spinner::before, .noVNC_spinner::after {
-  width: 10px;
-  height: 10px;
-  border-radius: 2px;
-  box-shadow: -60px 10px 0 rgba(255, 255, 255, 0);
-  animation: noVNC_spinner 1.0s linear infinite;
-}
-.noVNC_spinner::before {
-  content: "";
-  position: absolute;
-  left: 0px;
-  top: 0px;
-  animation-delay: -0.1s;
-}
-.noVNC_spinner::after {
-  content: "";
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  animation-delay: 0.1s;
-}
-@keyframes noVNC_spinner {
-  0% { box-shadow: -60px 10px 0 rgba(255, 255, 255, 0); width: 20px; }
-  25% { box-shadow: 20px 10px 0 rgba(255, 255, 255, 1); width: 10px; }
-  50% { box-shadow: 60px 10px 0 rgba(255, 255, 255, 0); width: 10px; }
-}
-
-/* ----------------------------------------
- * Input Elements
- * ----------------------------------------
- */
-
-input[type=input], input[type=password], input[type=number],
-input:not([type]), textarea {
-  /* Disable default rendering */
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  background: none;
-
-  margin: 2px;
-  padding: 2px;
-  border: 1px solid rgb(192, 192, 192);
-  border-radius: 5px;
-  color: black;
-  background: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240));
-}
-
-input[type=button], input[type=submit], select {
-  /* Disable default rendering */
-  -webkit-appearance: none;
-  -moz-appearance: none;
-  background: none;
-
-  margin: 2px;
-  padding: 2px;
-  border: 1px solid rgb(192, 192, 192);
-  border-bottom-width: 2px;
-  border-radius: 5px;
-  color: black;
-  background: linear-gradient(to top, rgb(255, 255, 255), rgb(240, 240, 240));
-
-  /* This avoids it jumping around when :active */
-  vertical-align: middle;
-}
-
-input[type=button], input[type=submit] {
-  padding-left: 20px;
-  padding-right: 20px;
-}
-
-option {
-  color: black;
-  background: white;
-}
-
-input[type=input]:focus, input[type=password]:focus,
-input:not([type]):focus, input[type=button]:focus,
-input[type=submit]:focus,
-textarea:focus, select:focus {
-  box-shadow: 0px 0px 3px rgba(74, 144, 217, 0.5);
-  border-color: rgb(74, 144, 217);
-  outline: none;
-}
-
-input[type=button]::-moz-focus-inner,
-input[type=submit]::-moz-focus-inner {
-  border: none;
-}
-
-input[type=input]:disabled, input[type=password]:disabled,
-input:not([type]):disabled, input[type=button]:disabled,
-input[type=submit]:disabled, input[type=number]:disabled,
-textarea:disabled, select:disabled {
-  color: rgb(128, 128, 128);
-  background: rgb(240, 240, 240);
-}
-
-input[type=button]:active, input[type=submit]:active,
-select:active {
-  border-bottom-width: 1px;
-  margin-top: 3px;
-}
-
-:root:not(.noVNC_touch) input[type=button]:hover:not(:disabled),
-:root:not(.noVNC_touch) input[type=submit]:hover:not(:disabled),
-:root:not(.noVNC_touch) select:hover:not(:disabled) {
-  background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250));
-}
-
-/* ----------------------------------------
- * WebKit centering hacks
- * ----------------------------------------
- */
-
-.noVNC_center {
-  /*
-   * This is a workaround because webkit misrenders transforms and
-   * uses non-integer coordinates, resulting in blurry content.
-   * Ideally we'd use "top: 50%; transform: translateY(-50%);" on
-   * the objects instead.
-   */
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  pointer-events: none;
-}
-.noVNC_center > * {
-  pointer-events: auto;
-}
-.noVNC_vcenter {
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  position: fixed;
-  top: 0;
-  left: 0;
-  height: 100%;
-  pointer-events: none;
-}
-.noVNC_vcenter > * {
-  pointer-events: auto;
-}
-
-/* ----------------------------------------
- * Layering
- * ----------------------------------------
- */
-
-.noVNC_connect_layer {
-  z-index: 60;
-}
-
-/* ----------------------------------------
- * Fallback error
- * ----------------------------------------
- */
-
-#noVNC_fallback_error {
-  z-index: 1000;
-  visibility: hidden;
-}
-#noVNC_fallback_error.noVNC_open {
-  visibility: visible;
-}
-
-#noVNC_fallback_error > div {
-  max-width: 90%;
-  padding: 15px;
-
-  transition: 0.5s ease-in-out;
-
-  transform: translateY(-50px);
-  opacity: 0;
-
-  text-align: center;
-  font-weight: bold;
-  color: #fff;
-
-  border-radius: 10px;
-  box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-  background: rgba(200,55,55,0.8);
-}
-#noVNC_fallback_error.noVNC_open > div {
-  transform: translateY(0);
-  opacity: 1;
-}
-
-#noVNC_fallback_errormsg {
-  font-weight: normal;
-}
-
-#noVNC_fallback_errormsg .noVNC_message {
-  display: inline-block;
-  text-align: left;
-  font-family: monospace;
-  white-space: pre-wrap;
-}
-
-#noVNC_fallback_error .noVNC_location {
-  font-style: italic;
-  font-size: 0.8em;
-  color: rgba(255, 255, 255, 0.8);
-}
-
-#noVNC_fallback_error .noVNC_stack {
-  max-height: 50vh;
-  padding: 10px;
-  margin: 10px;
-  font-size: 0.8em;
-  text-align: left;
-  font-family: monospace;
-  white-space: pre;
-  border: 1px solid rgba(0, 0, 0, 0.5);
-  background: rgba(0, 0, 0, 0.2);
-  overflow: auto;
-}
-
-/* ----------------------------------------
- * Control Bar
- * ----------------------------------------
- */
-
-#noVNC_control_bar_anchor {
-  /* The anchor is needed to get z-stacking to work */
-  position: fixed;
-  z-index: 10;
-
-  transition: 0.5s ease-in-out;
-
-  /* Edge misrenders animations wihthout this */
-  transform: translateX(0);
-}
-:root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle {
-  opacity: 0.8;
-}
-#noVNC_control_bar_anchor.noVNC_right {
-  left: auto;
-  right: 0;
-}
-
-#noVNC_control_bar {
-  position: relative;
-  left: -100%;
-
-  transition: 0.5s ease-in-out;
-
-  background-color: rgb(110, 132, 163);
-  border-radius: 0 10px 10px 0;
-
-}
-#noVNC_control_bar.noVNC_open {
-  box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-  left: 0;
-}
-#noVNC_control_bar::before {
-  /* This extra element is to get a proper shadow */
-  content: "";
-  position: absolute;
-  z-index: -1;
-  height: 100%;
-  width: 30px;
-  left: -30px;
-  transition: box-shadow 0.5s ease-in-out;
-}
-#noVNC_control_bar.noVNC_open::before {
-  box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-}
-.noVNC_right #noVNC_control_bar {
-  left: 100%;
-  border-radius: 10px 0 0 10px;
-}
-.noVNC_right #noVNC_control_bar.noVNC_open {
-  left: 0;
-}
-.noVNC_right #noVNC_control_bar::before {
-  visibility: hidden;
-}
-
-#noVNC_control_bar_handle {
-  position: absolute;
-  left: -15px;
-  top: 0;
-  transform: translateY(35px);
-  width: calc(100% + 30px);
-  height: 50px;
-  z-index: -1;
-  cursor: pointer;
-  border-radius: 5px;
-  background-color: rgb(83, 99, 122);
-  background-image: url("../images/handle_bg.svg");
-  background-repeat: no-repeat;
-  background-position: right;
-  box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5);
-}
-#noVNC_control_bar_handle:after {
-  content: "";
-  transition: transform 0.5s ease-in-out;
-  background: url("../images/handle.svg");
-  position: absolute;
-  top: 22px; /* (50px-6px)/2 */
-  right: 5px;
-  width: 5px;
-  height: 6px;
-}
-#noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
-  transform: translateX(1px) rotate(180deg);
-}
-:root:not(.noVNC_connected) #noVNC_control_bar_handle {
-  display: none;
-}
-.noVNC_right #noVNC_control_bar_handle {
-  background-position: left;
-}
-.noVNC_right #noVNC_control_bar_handle:after {
-  left: 5px;
-  right: 0;
-  transform: translateX(1px) rotate(180deg);
-}
-.noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
-  transform: none;
-}
-#noVNC_control_bar_handle div {
-  position: absolute;
-  right: -35px;
-  top: 0;
-  width: 50px;
-  height: 50px;
-}
-:root:not(.noVNC_touch) #noVNC_control_bar_handle div {
-  display: none;
-}
-.noVNC_right #noVNC_control_bar_handle div {
-  left: -35px;
-  right: auto;
-}
-
-#noVNC_control_bar .noVNC_scroll {
-  max-height: 100vh; /* Chrome is buggy with 100% */
-  overflow-x: hidden;
-  overflow-y: auto;
-  padding: 0 10px 0 5px;
-}
-.noVNC_right #noVNC_control_bar .noVNC_scroll {
-  padding: 0 5px 0 10px;
-}
-
-/* Control bar hint */
-#noVNC_control_bar_hint {
-  position: fixed;
-  left: calc(100vw - 50px);
-  right: auto;
-  top: 50%;
-  transform: translateY(-50%) scale(0);
-  width: 100px;
-  height: 50%;
-  max-height: 600px;
-
-  visibility: hidden;
-  opacity: 0;
-  transition: 0.2s ease-in-out;
-  background: transparent;
-  box-shadow: 0 0 10px black, inset 0 0 10px 10px rgba(110, 132, 163, 0.8);
-  border-radius: 10px;
-  transition-delay: 0s;
-}
-#noVNC_control_bar_anchor.noVNC_right #noVNC_control_bar_hint{
-  left: auto;
-  right: calc(100vw - 50px);
-}
-#noVNC_control_bar_hint.noVNC_active {
-  visibility: visible;
-  opacity: 1;
-  transition-delay: 0.2s;
-  transform: translateY(-50%) scale(1);
-}
-
-/* General button style */
-.noVNC_button {
-  display: block;
-  padding: 4px 4px;
-  margin: 10px 0;
-  vertical-align: middle;
-  border:1px solid rgba(255, 255, 255, 0.2);
-  border-radius: 6px;
-}
-.noVNC_button.noVNC_selected {
-  border-color: rgba(0, 0, 0, 0.8);
-  background: rgba(0, 0, 0, 0.5);
-}
-.noVNC_button:disabled {
-  opacity: 0.4;
-}
-.noVNC_button:focus {
-  outline: none;
-}
-.noVNC_button:active {
-  padding-top: 5px;
-  padding-bottom: 3px;
-}
-/* Android browsers don't properly update hover state if touch events
- * are intercepted, but focus should be safe to display */
-:root:not(.noVNC_touch) .noVNC_button.noVNC_selected:hover,
-.noVNC_button.noVNC_selected:focus {
-  border-color: rgba(0, 0, 0, 0.4);
-  background: rgba(0, 0, 0, 0.2);
-}
-:root:not(.noVNC_touch) .noVNC_button:hover,
-.noVNC_button:focus {
-  background: rgba(255, 255, 255, 0.2);
-}
-.noVNC_button.noVNC_hidden {
-  display: none;
-}
-
-/* Panels */
-.noVNC_panel {
-  transform: translateX(25px);
-
-  transition: 0.5s ease-in-out;
-
-  max-height: 100vh; /* Chrome is buggy with 100% */
-  overflow-x: hidden;
-  overflow-y: auto;
-
-  visibility: hidden;
-  opacity: 0;
-
-  padding: 15px;
-
-  background: #fff;
-  border-radius: 10px;
-  color: #000;
-  border: 2px solid #E0E0E0;
-  box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-}
-.noVNC_panel.noVNC_open {
-  visibility: visible;
-  opacity: 1;
-  transform: translateX(75px);
-}
-.noVNC_right .noVNC_vcenter {
-  left: auto;
-  right: 0;
-}
-.noVNC_right .noVNC_panel {
-  transform: translateX(-25px);
-}
-.noVNC_right .noVNC_panel.noVNC_open {
-  transform: translateX(-75px);
-}
-
-.noVNC_panel hr {
-  border: none;
-  border-top: 1px solid rgb(192, 192, 192);
-}
-
-.noVNC_panel label {
-  display: block;
-  white-space: nowrap;
-}
-
-.noVNC_panel .noVNC_heading {
-  background-color: rgb(110, 132, 163);
-  border-radius: 5px;
-  padding: 5px;
-  /* Compensate for padding in image */
-  padding-right: 8px;
-  color: white;
-  font-size: 20px;
-  margin-bottom: 10px;
-  white-space: nowrap;
-}
-.noVNC_panel .noVNC_heading img {
-  vertical-align: bottom;
-}
-
-.noVNC_submit {
-  float: right;
-}
-
-/* Expanders */
-.noVNC_expander {
-  cursor: pointer;
-}
-.noVNC_expander::before {
-  content: url("../images/expander.svg");
-  display: inline-block;
-  margin-right: 5px;
-  transition: 0.2s ease-in-out;
-}
-.noVNC_expander.noVNC_open::before {
-  transform: rotateZ(90deg);
-}
-.noVNC_expander ~ * {
-  margin: 5px;
-  margin-left: 10px;
-  padding: 5px;
-  background: rgba(0, 0, 0, 0.05);
-  border-radius: 5px;
-}
-.noVNC_expander:not(.noVNC_open) ~ * {
-  display: none;
-}
-
-/* Control bar content */
-
-#noVNC_control_bar .noVNC_logo {
-  font-size: 13px;
-}
-
-:root:not(.noVNC_connected) #noVNC_view_drag_button {
-  display: none;
-}
-
-/* noVNC Touch Device only buttons */
-:root:not(.noVNC_connected) #noVNC_mobile_buttons {
-  display: none;
-}
-:root:not(.noVNC_touch) #noVNC_mobile_buttons {
-  display: none;
-}
-
-/* Extra manual keys */
-:root:not(.noVNC_connected) #noVNC_extra_keys {
-  display: none;
-}
-
-#noVNC_modifiers {
-  background-color: rgb(92, 92, 92);
-  border: none;
-  padding: 0 10px;
-}
-
-/* Shutdown/Reboot */
-:root:not(.noVNC_connected) #noVNC_power_button {
-  display: none;
-}
-#noVNC_power {
-}
-#noVNC_power_buttons {
-  display: none;
-}
-
-#noVNC_power input[type=button] {
-  width: 100%;
-}
-
-/* Clipboard */
-:root:not(.noVNC_connected) #noVNC_clipboard_button {
-  display: none;
-}
-#noVNC_clipboard {
-  /* Full screen, minus padding and left and right margins */
-  max-width: calc(100vw - 2*15px - 75px - 25px);
-}
-#noVNC_clipboard_text {
-  width: 500px;
-  max-width: 100%;
-}
-
-/* Settings */
-#noVNC_settings {
-}
-#noVNC_settings ul {
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-}
-#noVNC_setting_port {
-  width: 80px;
-}
-#noVNC_setting_path {
-  width: 100px;
-}
-
-/* Connection Controls */
-:root:not(.noVNC_connected) #noVNC_disconnect_button {
-  display: none;
-}
-
-/* ----------------------------------------
- * Status Dialog
- * ----------------------------------------
- */
-
-#noVNC_status {
-  position: fixed;
-  top: 0;
-  left: 0;
-  width: 100%;
-  z-index: 100;
-  transform: translateY(-100%);
-
-  cursor: pointer;
-
-  transition: 0.5s ease-in-out;
-
-  visibility: hidden;
-  opacity: 0;
-
-  padding: 5px;
-
-  display: flex;
-  flex-direction: row;
-  justify-content: center;
-  align-content: center;
-
-  line-height: 25px;
-  word-wrap: break-word;
-  color: #fff;
-
-  border-bottom: 1px solid rgba(0, 0, 0, 0.9);
-}
-#noVNC_status.noVNC_open {
-  transform: translateY(0);
-  visibility: visible;
-  opacity: 1;
-}
-
-#noVNC_status::before {
-  content: "";
-  display: inline-block;
-  width: 25px;
-  height: 25px;
-  margin-right: 5px;
-}
-
-#noVNC_status.noVNC_status_normal {
-  background: rgba(128,128,128,0.9);
-}
-#noVNC_status.noVNC_status_normal::before {
-  content: url("../images/info.svg") " ";
-}
-#noVNC_status.noVNC_status_error {
-  background: rgba(200,55,55,0.9);
-}
-#noVNC_status.noVNC_status_error::before {
-  content: url("../images/error.svg") " ";
-}
-#noVNC_status.noVNC_status_warn {
-  background: rgba(180,180,30,0.9);
-}
-#noVNC_status.noVNC_status_warn::before {
-  content: url("../images/warning.svg") " ";
-}
-
-/* ----------------------------------------
- * Connect Dialog
- * ----------------------------------------
- */
-
-#noVNC_connect_dlg {
-  transition: 0.5s ease-in-out;
-
-  transform: scale(0, 0);
-  visibility: hidden;
-  opacity: 0;
-}
-#noVNC_connect_dlg.noVNC_open {
-  transform: scale(1, 1);
-  visibility: visible;
-  opacity: 1;
-}
-#noVNC_connect_dlg .noVNC_logo {
-  transition: 0.5s ease-in-out;
-  padding: 10px;
-  margin-bottom: 10px;
-
-  font-size: 80px;
-  text-align: center;
-
-  border-radius: 5px;
-}
-@media (max-width: 440px) {
-  #noVNC_connect_dlg {
-    max-width: calc(100vw - 100px);
-  }
-  #noVNC_connect_dlg .noVNC_logo {
-    font-size: calc(25vw - 30px);
-  }
-}
-#noVNC_connect_button {
-  cursor: pointer;
-
-  padding: 10px;
-
-  color: white;
-  background-color: rgb(110, 132, 163);
-  border-radius: 12px;
-
-  text-align: center;
-  font-size: 20px;
-
-  box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
-}
-#noVNC_connect_button div {
-  margin: 2px;
-  padding: 5px 30px;
-  border: 1px solid rgb(83, 99, 122);
-  border-bottom-width: 2px;
-  border-radius: 5px;
-  background: linear-gradient(to top, rgb(110, 132, 163), rgb(99, 119, 147));
-
-  /* This avoids it jumping around when :active */
-  vertical-align: middle;
-}
-#noVNC_connect_button div:active {
-  border-bottom-width: 1px;
-  margin-top: 3px;
-}
-:root:not(.noVNC_touch) #noVNC_connect_button div:hover {
-  background: linear-gradient(to top, rgb(110, 132, 163), rgb(105, 125, 155));
-}
-
-#noVNC_connect_button img {
-  vertical-align: bottom;
-  height: 1.3em;
-}
-
-/* ----------------------------------------
- * Password Dialog
- * ----------------------------------------
- */
-
-#noVNC_password_dlg {
-  position: relative;
-
-  transform: translateY(-50px);
-}
-#noVNC_password_dlg.noVNC_open {
-  transform: translateY(0);
-}
-#noVNC_password_dlg ul {
-  list-style: none;
-  margin: 0px;
-  padding: 0px;
-}
-
-/* ----------------------------------------
- * Main Area
- * ----------------------------------------
- */
-
-/* Transition screen */
-#noVNC_transition {
-  display: none;
-
-  position: fixed;
-  top: 0;
-  left: 0;
-  bottom: 0;
-  right: 0;
-
-  color: white;
-  background: rgba(0, 0, 0, 0.5);
-  z-index: 50;
-
-  /*display: flex;*/
-  align-items: center;
-  justify-content: center;
-  flex-direction: column;
-}
-:root.noVNC_loading #noVNC_transition,
-:root.noVNC_connecting #noVNC_transition,
-:root.noVNC_disconnecting #noVNC_transition,
-:root.noVNC_reconnecting #noVNC_transition {
-  display: flex;
-}
-:root:not(.noVNC_reconnecting) #noVNC_cancel_reconnect_button {
-  display: none;
-}
-#noVNC_transition_text {
-  font-size: 1.5em;
-}
-
-/* Main container */
-#noVNC_container {
-  width: 100%;
-  height: 100%;
-  background-color: #313131;
-  border-bottom-right-radius: 800px 600px;
-  /*border-top-left-radius: 800px 600px;*/
-}
-
-#noVNC_keyboardinput {
-  width: 1px;
-  height: 1px;
-  background-color: #fff;
-  color: #fff;
-  border: 0;
-  position: absolute;
-  left: -40px;
-  z-index: -1;
-  ime-mode: disabled;
-}
-
-/*Default noVNC logo.*/
-.noVNC_logo {
-  color:yellow;
-  font-family: sans-serif;
-  line-height:90%;
-  text-shadow: 0.1em 0.1em 0 black;
-}
-.noVNC_logo span{
-  color:green;
-}
-
-#noVNC_bell {
-  display: none;
-}
-
-/* ----------------------------------------
- * Media sizing
- * ----------------------------------------
- */
-
-@media screen and (max-width: 640px){
-  #noVNC_logo {
-    font-size: 150px;
-  }
-}
-
-@media screen and (min-width: 321px) and (max-width: 480px) {
-  #noVNC_logo {
-    font-size: 110px;
-  }
-}
-
-@media screen and (max-width: 320px) {
-  #noVNC_logo {
-    font-size: 90px;
-  }
-}
--- a/image/w/app/styles/web.css	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-
-body {
-  margin:0;
-  padding:0;
-  font-family: Helvetica;
-  /*Background image with light grey curve.*/
-  background-color:#494949;
-  background-repeat:no-repeat;
-  background-position:right bottom;
-  height:100%;
-/*  touch-action: none; */
-}
-
-html {
-  height:100%;
-}
-
-
-/* ----------------------------------------
- * Main Area
- * ----------------------------------------
- */
-
-
-.menu {
-  width: 270px;
-  margin: auto;
-}
-
-.menu input[type=none] {
-  background-color: #0077bb;
-  border: none;
-  color: yellow;
-  font-weight: bold;
-  width: 250px;
-  padding: 10px 0px;
-  text-decoration: none;
-  font-size: 16px;
-  margin: 8px;
-  text-align: center;
-  border-radius: 10px;
-}
-
-.menu input[type=submit] {
-  background-color: #33b5e5;
-  border: none;
-  color: white;
-  font-weight: bold;
-  width: 250px;
-  padding: 15px 32px;
-  text-decoration: none;
-  font-size: 16px;
-  cursor: pointer;
-  margin: 8px;
-  text-align: center;
-  border-radius: 10px;
-}
-
-.menu input[type=submit]:hover {
-  background-color: #0099cc;
-}
-
-
-.menu ul {
-  list-style-type: none;
-  margin: 0;
-  padding: 0;
-}
-
-table.directory {
-  width:  90%;
-  border-collapse : collapse;
-  margin          : auto;
-  padding         : 0px;
-  background: yellow;
-}
-
-tr.directory:nth-child(odd) {
-  background      : #FFFFFF;
-}
-
-tr.directory:nth-child(even) {
-  background      : #CCFFFF;
-}
-
-
Binary file image/w/app/ui.js.gz has changed
Binary file image/w/app/webutil.js.gz has changed
Binary file image/w/core/base64.js.gz has changed
Binary file image/w/core/des.js.gz has changed
Binary file image/w/core/display.js.gz has changed
Binary file image/w/core/encodings.js.gz has changed
Binary file image/w/core/inflator.js.gz has changed
Binary file image/w/core/input/mouse.js.gz has changed
Binary file image/w/core/rfb.js.gz has changed
--- a/image/w/core/rfb.js.orig	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2554 +0,0 @@
-/*
- * noVNC: HTML5 VNC client
- * Copyright (C) 2012 Joel Martin
- * Copyright (C) 2017 Samuel Mannehed for Cendio AB
- * Licensed under MPL 2.0 (see LICENSE.txt)
- *
- * See README.md for usage and integration instructions.
- *
- * TIGHT decoder portion:
- * (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca)
- */
-
-import * as Log from './util/logging.js';
-import { decodeUTF8 } from './util/strings.js';
-import { supportsCursorURIs, isTouchDevice } from './util/browser.js';
-import EventTargetMixin from './util/eventtarget.js';
-import Display from "./display.js";
-import Keyboard from "./input/keyboard.js";
-import Mouse from "./input/mouse.js";
-import Websock from "./websock.js";
-import DES from "./des.js";
-import KeyTable from "./input/keysym.js";
-import XtScancode from "./input/xtscancodes.js";
-import Inflator from "./inflator.js";
-import { encodings, encodingName } from "./encodings.js";
-import "./util/polyfill.js";
-
-/*jslint white: false, browser: true */
-/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES, KeyTable, Inflator, XtScancode */
-
-// How many seconds to wait for a disconnect to finish
-var DISCONNECT_TIMEOUT = 3;
-
-export default function RFB(target, url, options) {
-    if (!target) {
-        throw Error("Must specify target");
-    }
-    if (!url) {
-        throw Error("Must specify URL");
-    }
-
-    this._target = target;
-    this._url = url;
-
-    // Connection details
-    options = options || {};
-    this._rfb_credentials = options.credentials || {};
-    this._shared = 'shared' in options ? !!options.shared : true;
-    this._repeaterID = options.repeaterID || '';
-
-    // Internal state
-    this._rfb_connection_state = '';
-    this._rfb_init_state = '';
-    this._rfb_auth_scheme = '';
-    this._rfb_clean_disconnect = true;
-
-    // Server capabilities
-    this._rfb_version = 0;
-    this._rfb_max_version = 3.8;
-    this._rfb_tightvnc = false;
-    this._rfb_xvp_ver = 0;
-
-    this._fb_width = 0;
-    this._fb_height = 0;
-
-    this._fb_name = "";
-
-    this._capabilities = { power: false };
-
-    this._supportsFence = false;
-
-    this._supportsContinuousUpdates = false;
-    this._enabledContinuousUpdates = false;
-
-    this._supportsSetDesktopSize = false;
-    this._screen_id = 0;
-    this._screen_flags = 0;
-
-    this._qemuExtKeyEventSupported = false;
-
-    // Internal objects
-    this._sock = null;              // Websock object
-    this._display = null;           // Display object
-    this._flushing = false;         // Display flushing state
-    this._keyboard = null;          // Keyboard input handler object
-    this._mouse = null;             // Mouse input handler object
-
-    // Timers
-    this._disconnTimer = null;      // disconnection timer
-    this._resizeTimeout = null;     // resize rate limiting
-
-    // Decoder states and stats
-    this._encHandlers = {};
-    this._encStats = {};
-
-    this._FBU = {
-        rects: 0,
-        subrects: 0,            // RRE and HEXTILE
-        lines: 0,               // RAW
-        tiles: 0,               // HEXTILE
-        bytes: 0,
-        x: 0,
-        y: 0,
-        width: 0,
-        height: 0,
-        encoding: 0,
-        subencoding: -1,
-        background: null,
-        zlibs: []               // TIGHT zlib streams
-    };
-    for (var i = 0; i < 4; i++) {
-        this._FBU.zlibs[i] = new Inflator();
-    }
-
-    this._destBuff = null;
-    this._paletteBuff = new Uint8Array(1024);  // 256 * 4 (max palette size * max bytes-per-pixel)
-
-    this._rre_chunk_sz = 100;
-
-    this._timing = {
-        last_fbu: 0,
-        fbu_total: 0,
-        fbu_total_cnt: 0,
-        full_fbu_total: 0,
-        full_fbu_cnt: 0,
-
-        fbu_rt_start: 0,
-        fbu_rt_total: 0,
-        fbu_rt_cnt: 0,
-        pixels: 0
-    };
-
-    // Mouse state
-    this._mouse_buttonMask = 0;
-    this._mouse_arr = [];
-    this._viewportDragging = false;
-    this._viewportDragPos = {};
-    this._viewportHasMoved = false;
-
-    // Bound event handlers
-    this._eventHandlers = {
-        focusCanvas: this._focusCanvas.bind(this),
-        windowResize: this._windowResize.bind(this),
-    };
-
-    // main setup
-    Log.Debug(">> RFB.constructor");
-
-    // Create DOM elements
-    this._screen = document.createElement('div');
-    this._screen.style.display = 'flex';
-    this._screen.style.width = '100%';
-    this._screen.style.height = '100%';
-    this._screen.style.overflow = 'auto';
-    this._screen.style.backgroundColor = 'rgb(40, 40, 40)';
-    this._canvas = document.createElement('canvas');
-    this._canvas.style.margin = 'auto';
-    // Some browsers add an outline on focus
-    this._canvas.style.outline = 'none';
-    // IE miscalculates width without this :(
-    this._canvas.style.flexShrink = '0';
-    this._canvas.width = 0;
-    this._canvas.height = 0;
-    this._canvas.tabIndex = -1;
-    this._screen.appendChild(this._canvas);
-
-    // populate encHandlers with bound versions
-    this._encHandlers[encodings.encodingRaw] = RFB.encodingHandlers.RAW.bind(this);
-    this._encHandlers[encodings.encodingCopyRect] = RFB.encodingHandlers.COPYRECT.bind(this);
-    this._encHandlers[encodings.encodingRRE] = RFB.encodingHandlers.RRE.bind(this);
-    this._encHandlers[encodings.encodingHextile] = RFB.encodingHandlers.HEXTILE.bind(this);
-    this._encHandlers[encodings.encodingTight] = RFB.encodingHandlers.TIGHT.bind(this);
-
-    this._encHandlers[encodings.pseudoEncodingDesktopSize] = RFB.encodingHandlers.DesktopSize.bind(this);
-    this._encHandlers[encodings.pseudoEncodingLastRect] = RFB.encodingHandlers.last_rect.bind(this);
-    this._encHandlers[encodings.pseudoEncodingCursor] = RFB.encodingHandlers.Cursor.bind(this);
-    this._encHandlers[encodings.pseudoEncodingQEMUExtendedKeyEvent] = RFB.encodingHandlers.QEMUExtendedKeyEvent.bind(this);
-    this._encHandlers[encodings.pseudoEncodingExtendedDesktopSize] = RFB.encodingHandlers.ExtendedDesktopSize.bind(this);
-
-    // NB: nothing that needs explicit teardown should be done
-    // before this point, since this can throw an exception
-    try {
-        this._display = new Display(this._canvas);
-    } catch (exc) {
-        Log.Error("Display exception: " + exc);
-        throw exc;
-    }
-    this._display.onflush = this._onFlush.bind(this);
-    this._display.clear();
-
-    this._keyboard = new Keyboard(this._canvas);
-    this._keyboard.onkeyevent = this._handleKeyEvent.bind(this);
-
-    this._mouse = new Mouse(this._canvas);
-    this._mouse.onmousebutton = this._handleMouseButton.bind(this);
-    this._mouse.onmousemove = this._handleMouseMove.bind(this);
-
-    this._sock = new Websock();
-    this._sock.on('message', this._handle_message.bind(this));
-    this._sock.on('open', function () {
-        if ((this._rfb_connection_state === 'connecting') &&
-            (this._rfb_init_state === '')) {
-            this._rfb_init_state = 'ProtocolVersion';
-            Log.Debug("Starting VNC handshake");
-        } else {
-            this._fail("Unexpected server connection while " +
-                       this._rfb_connection_state);
-        }
-    }.bind(this));
-    this._sock.on('close', function (e) {
-        Log.Debug("WebSocket on-close event");
-        var msg = "";
-        if (e.code) {
-            msg = "(code: " + e.code;
-            if (e.reason) {
-                msg += ", reason: " + e.reason;
-            }
-            msg += ")";
-        }
-        switch (this._rfb_connection_state) {
-            case 'connecting':
-                this._fail("Connection closed " + msg);
-                break;
-            case 'connected':
-                // Handle disconnects that were initiated server-side
-                this._updateConnectionState('disconnecting');
-                this._updateConnectionState('disconnected');
-                break;
-            case 'disconnecting':
-                // Normal disconnection path
-                this._updateConnectionState('disconnected');
-                break;
-            case 'disconnected':
-                this._fail("Unexpected server disconnect " +
-                           "when already disconnected " + msg);
-                break;
-            default:
-                this._fail("Unexpected server disconnect before connecting " +
-                           msg);
-                break;
-        }
-        this._sock.off('close');
-    }.bind(this));
-    this._sock.on('error', function (e) {
-        Log.Warn("WebSocket on-error event");
-    });
-
-    // Slight delay of the actual connection so that the caller has
-    // time to set up callbacks
-    setTimeout(this._updateConnectionState.bind(this, 'connecting'));
-
-    Log.Debug("<< RFB.constructor");
-};
-
-RFB.prototype = {
-    // ===== PROPERTIES =====
-
-    dragViewport: false,
-    focusOnClick: true,
-
-    _viewOnly: false,
-    get viewOnly() { return this._viewOnly; },
-    set viewOnly(viewOnly) {
-        this._viewOnly = viewOnly;
-
-        if (this._rfb_connection_state === "connecting" ||
-            this._rfb_connection_state === "connected") {
-            if (viewOnly) {
-                this._keyboard.ungrab();
-                this._mouse.ungrab();
-            } else {
-                this._keyboard.grab();
-                this._mouse.grab();
-            }
-        }
-    },
-
-    get capabilities() { return this._capabilities; },
-
-    get touchButton() { return this._mouse.touchButton; },
-    set touchButton(button) { this._mouse.touchButton = button; },
-
-    _clipViewport: false,
-    get clipViewport() { return this._clipViewport; },
-    set clipViewport(viewport) {
-        this._clipViewport = viewport;
-        this._updateClip();
-    },
-
-    _scaleViewport: false,
-    get scaleViewport() { return this._scaleViewport; },
-    set scaleViewport(scale) {
-        this._scaleViewport = scale;
-        // Scaling trumps clipping, so we may need to adjust
-        // clipping when enabling or disabling scaling
-        if (scale && this._clipViewport) {
-            this._updateClip();
-        }
-        this._updateScale();
-        if (!scale && this._clipViewport) {
-            this._updateClip();
-        }
-    },
-
-    _resizeSession: false,
-    get resizeSession() { return this._resizeSession; },
-    set resizeSession(resize) {
-        this._resizeSession = resize;
-        if (resize) {
-            this._requestRemoteResize();
-        }
-    },
-
-    // ===== PUBLIC METHODS =====
-
-    disconnect: function () {
-        this._updateConnectionState('disconnecting');
-        this._sock.off('error');
-        this._sock.off('message');
-        this._sock.off('open');
-    },
-
-    sendCredentials: function (creds) {
-        this._rfb_credentials = creds;
-        setTimeout(this._init_msg.bind(this), 0);
-    },
-
-    sendCtrlAltDel: function () {
-        if (this._rfb_connection_state !== 'connected' || this._viewOnly) { return; }
-        Log.Info("Sending Ctrl-Alt-Del");
-
-        this.sendKey(KeyTable.XK_Control_L, "ControlLeft", true);
-        this.sendKey(KeyTable.XK_Alt_L, "AltLeft", true);
-        this.sendKey(KeyTable.XK_Delete, "Delete", true);
-        this.sendKey(KeyTable.XK_Delete, "Delete", false);
-        this.sendKey(KeyTable.XK_Alt_L, "AltLeft", false);
-        this.sendKey(KeyTable.XK_Control_L, "ControlLeft", false);
-    },
-
-    machineShutdown: function () {
-        this._xvpOp(1, 2);
-    },
-
-    machineReboot: function () {
-        this._xvpOp(1, 3);
-    },
-
-    machineReset: function () {
-        this._xvpOp(1, 4);
-    },
-
-    // Send a key press. If 'down' is not specified then send a down key
-    // followed by an up key.
-    sendKey: function (keysym, code, down) {
-        if (this._rfb_connection_state !== 'connected' || this._viewOnly) { return; }
-
-        if (down === undefined) {
-            this.sendKey(keysym, code, true);
-            this.sendKey(keysym, code, false);
-            return;
-        }
-
-        var scancode = XtScancode[code];
-
-        if (this._qemuExtKeyEventSupported && scancode) {
-            // 0 is NoSymbol
-            keysym = keysym || 0;
-
-            Log.Info("Sending key (" + (down ? "down" : "up") + "): keysym " + keysym + ", scancode " + scancode);
-
-            RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode);
-        } else {
-            if (!keysym) {
-                return;
-            }
-            Log.Info("Sending keysym (" + (down ? "down" : "up") + "): " + keysym);
-            RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0);
-        }
-    },
-
-    focus: function () {
-        this._canvas.focus();
-    },
-
-    blur: function () {
-        this._canvas.blur();
-    },
-
-    clipboardPasteFrom: function (text) {
-        if (this._rfb_connection_state !== 'connected' || this._viewOnly) { return; }
-        RFB.messages.clientCutText(this._sock, text);
-    },
-
-    // ===== PRIVATE METHODS =====
-
-    _connect: function () {
-        Log.Debug(">> RFB.connect");
-
-        Log.Info("connecting to " + this._url);
-
-        try {
-            // WebSocket.onopen transitions to the RFB init states
-            this._sock.open(this._url, ['binary']);
-        } catch (e) {
-            if (e.name === 'SyntaxError') {
-                this._fail("Invalid host or port (" + e + ")");
-            } else {
-                this._fail("Error when opening socket (" + e + ")");
-            }
-        }
-
-        // Make our elements part of the page
-        this._target.appendChild(this._screen);
-
-        // Monitor size changes of the screen
-        // FIXME: Use ResizeObserver, or hidden overflow
-        window.addEventListener('resize', this._eventHandlers.windowResize);
-
-        // Always grab focus on some kind of click event
-        this._canvas.addEventListener("mousedown", this._eventHandlers.focusCanvas);
-        this._canvas.addEventListener("touchstart", this._eventHandlers.focusCanvas);
-
-        Log.Debug("<< RFB.connect");
-    },
-
-    _disconnect: function () {
-        Log.Debug(">> RFB.disconnect");
-        this._canvas.removeEventListener("mousedown", this._eventHandlers.focusCanvas);
-        this._canvas.removeEventListener("touchstart", this._eventHandlers.focusCanvas);
-        window.removeEventListener('resize', this._eventHandlers.windowResize);
-        this._keyboard.ungrab();
-        this._mouse.ungrab();
-        this._sock.close();
-        this._print_stats();
-        try {
-            this._target.removeChild(this._screen);
-        } catch (e) {
-            if (e.name === 'NotFoundError') {
-                // Some cases where the initial connection fails
-                // can disconnect before the _screen is created
-            } else {
-                throw e;
-            }
-        }
-        clearTimeout(this._resizeTimeout);
-        Log.Debug("<< RFB.disconnect");
-    },
-
-    _print_stats: function () {
-        var stats = this._encStats;
-
-        Log.Info("Encoding stats for this connection:");
-        Object.keys(stats).forEach(function (key) {
-            var s = stats[key];
-            if (s[0] + s[1] > 0) {
-                Log.Info("    " + encodingName(key) + ": " + s[0] + " rects");
-            }
-        });
-
-        Log.Info("Encoding stats since page load:");
-        Object.keys(stats).forEach(function (key) {
-            var s = stats[key];
-            Log.Info("    " + encodingName(key) + ": " + s[1] + " rects");
-        });
-    },
-
-    _focusCanvas: function(event) {
-        // Respect earlier handlers' request to not do side-effects
-        if (event.defaultPrevented) {
-            return;
-        }
-
-        if (!this.focusOnClick) {
-            return;
-        }
-
-        this.focus();
-    },
-
-    _windowResize: function (event) {
-        // If the window resized then our screen element might have
-        // as well. Update the viewport dimensions.
-        window.requestAnimationFrame(function () {
-            this._updateClip();
-            this._updateScale();
-        }.bind(this));
-
-        if (this._resizeSession) {
-            // Request changing the resolution of the remote display to
-            // the size of the local browser viewport.
-
-            // In order to not send multiple requests before the browser-resize
-            // is finished we wait 0.5 seconds before sending the request.
-            clearTimeout(this._resizeTimeout);
-            this._resizeTimeout = setTimeout(this._requestRemoteResize.bind(this), 500);
-        }
-    },
-
-    // Update state of clipping in Display object, and make sure the
-    // configured viewport matches the current screen size
-    _updateClip: function () {
-        var cur_clip = this._display.clipViewport;
-        var new_clip = this._clipViewport;
-
-        if (this._scaleViewport) {
-            // Disable viewport clipping if we are scaling
-            new_clip = false;
-        }
-
-        if (cur_clip !== new_clip) {
-            this._display.clipViewport = new_clip;
-        }
-
-        if (new_clip) {
-            // When clipping is enabled, the screen is limited to
-            // the size of the container.
-            let size = this._screenSize();
-            this._display.viewportChangeSize(size.w, size.h);
-            this._fixScrollbars();
-        }
-    },
-
-    _updateScale: function () {
-        if (!this._scaleViewport) {
-            this._display.scale = 1.0;
-        } else {
-            let size = this._screenSize();
-            this._display.autoscale(size.w, size.h);
-        }
-        this._fixScrollbars();
-    },
-
-    // Requests a change of remote desktop size. This message is an extension
-    // and may only be sent if we have received an ExtendedDesktopSize message
-    _requestRemoteResize: function () {
-        clearTimeout(this._resizeTimeout);
-        this._resizeTimeout = null;
-
-        if (!this._resizeSession || this._viewOnly ||
-            !this._supportsSetDesktopSize) {
-            return;
-        }
-
-        let size = this._screenSize();
-        RFB.messages.setDesktopSize(this._sock, size.w, size.h,
-                                    this._screen_id, this._screen_flags);
-
-        Log.Debug('Requested new desktop size: ' +
-                   size.w + 'x' + size.h);
-    },
-
-    // Gets the the size of the available screen
-    _screenSize: function () {
-        return { w: this._screen.offsetWidth,
-                 h: this._screen.offsetHeight };
-    },
-
-    _fixScrollbars: function () {
-        // This is a hack because Chrome screws up the calculation
-        // for when scrollbars are needed. So to fix it we temporarily
-        // toggle them off and on.
-        var orig = this._screen.style.overflow;
-        this._screen.style.overflow = 'hidden';
-        // Force Chrome to recalculate the layout by asking for
-        // an element's dimensions
-        this._screen.getBoundingClientRect();
-        this._screen.style.overflow = orig;
-    },
-
-    /*
-     * Connection states:
-     *   connecting
-     *   connected
-     *   disconnecting
-     *   disconnected - permanent state
-     */
-    _updateConnectionState: function (state) {
-        var oldstate = this._rfb_connection_state;
-
-        if (state === oldstate) {
-            Log.Debug("Already in state '" + state + "', ignoring");
-            return;
-        }
-
-        // The 'disconnected' state is permanent for each RFB object
-        if (oldstate === 'disconnected') {
-            Log.Error("Tried changing state of a disconnected RFB object");
-            return;
-        }
-
-        // Ensure proper transitions before doing anything
-        switch (state) {
-            case 'connected':
-                if (oldstate !== 'connecting') {
-                    Log.Error("Bad transition to connected state, " +
-                               "previous connection state: " + oldstate);
-                    return;
-                }
-                break;
-
-            case 'disconnected':
-                if (oldstate !== 'disconnecting') {
-                    Log.Error("Bad transition to disconnected state, " +
-                               "previous connection state: " + oldstate);
-                    return;
-                }
-                break;
-
-            case 'connecting':
-                if (oldstate !== '') {
-                    Log.Error("Bad transition to connecting state, " +
-                               "previous connection state: " + oldstate);
-                    return;
-                }
-                break;
-
-            case 'disconnecting':
-                if (oldstate !== 'connected' && oldstate !== 'connecting') {
-                    Log.Error("Bad transition to disconnecting state, " +
-                               "previous connection state: " + oldstate);
-                    return;
-                }
-                break;
-
-            default:
-                Log.Error("Unknown connection state: " + state);
-                return;
-        }
-
-        // State change actions
-
-        this._rfb_connection_state = state;
-
-        var smsg = "New state '" + state + "', was '" + oldstate + "'.";
-        Log.Debug(smsg);
-
-        if (this._disconnTimer && state !== 'disconnecting') {
-            Log.Debug("Clearing disconnect timer");
-            clearTimeout(this._disconnTimer);
-            this._disconnTimer = null;
-
-            // make sure we don't get a double event
-            this._sock.off('close');
-        }
-
-        switch (state) {
-            case 'connecting':
-                this._connect();
-                break;
-
-            case 'connected':
-                var event = new CustomEvent("connect", { detail: {} });
-                this.dispatchEvent(event);
-                break;
-
-            case 'disconnecting':
-                this._disconnect();
-
-                this._disconnTimer = setTimeout(function () {
-                    Log.Error("Disconnection timed out.");
-                    this._updateConnectionState('disconnected');
-                }.bind(this), DISCONNECT_TIMEOUT * 1000);
-                break;
-
-            case 'disconnected':
-                event = new CustomEvent(
-                    "disconnect", { detail:
-                                    { clean: this._rfb_clean_disconnect } });
-                this.dispatchEvent(event);
-                break;
-        }
-    },
-
-    /* Print errors and disconnect
-     *
-     * The parameter 'details' is used for information that
-     * should be logged but not sent to the user interface.
-     */
-    _fail: function (details) {
-        switch (this._rfb_connection_state) {
-            case 'disconnecting':
-                Log.Error("Failed when disconnecting: " + details);
-                break;
-            case 'connected':
-                Log.Error("Failed while connected: " + details);
-                break;
-            case 'connecting':
-                Log.Error("Failed when connecting: " + details);
-                break;
-            default:
-                Log.Error("RFB failure: " + details);
-                break;
-        }
-        this._rfb_clean_disconnect = false; //This is sent to the UI
-
-        // Transition to disconnected without waiting for socket to close
-        this._updateConnectionState('disconnecting');
-        this._updateConnectionState('disconnected');
-
-        return false;
-    },
-
-    _setCapability: function (cap, val) {
-        this._capabilities[cap] = val;
-        var event = new CustomEvent("capabilities",
-                                    { detail: { capabilities: this._capabilities } });
-        this.dispatchEvent(event);
-    },
-
-    _handle_message: function () {
-        if (this._sock.rQlen() === 0) {
-            Log.Warn("handle_message called on an empty receive queue");
-            return;
-        }
-
-        switch (this._rfb_connection_state) {
-            case 'disconnected':
-                Log.Error("Got data while disconnected");
-                break;
-            case 'connected':
-                while (true) {
-                    if (this._flushing) {
-                        break;
-                    }
-                    if (!this._normal_msg()) {
-                        break;
-                    }
-                    if (this._sock.rQlen() === 0) {
-                        break;
-                    }
-                }
-                break;
-            default:
-                this._init_msg();
-                break;
-        }
-    },
-
-    _handleKeyEvent: function (keysym, code, down) {
-        this.sendKey(keysym, code, down);
-    },
-
-    _handleMouseButton: function (x, y, down, bmask) {
-        if (down) {
-            this._mouse_buttonMask |= bmask;
-        } else {
-            this._mouse_buttonMask &= ~bmask;
-        }
-
-        if (this.dragViewport) {
-            if (down && !this._viewportDragging) {
-                this._viewportDragging = true;
-                this._viewportDragPos = {'x': x, 'y': y};
-                this._viewportHasMoved = false;
-
-                // Skip sending mouse events
-                return;
-            } else {
-                this._viewportDragging = false;
-
-                // If we actually performed a drag then we are done
-                // here and should not send any mouse events
-                if (this._viewportHasMoved) {
-                    return;
-                }
-
-                // Otherwise we treat this as a mouse click event.
-                // Send the button down event here, as the button up
-                // event is sent at the end of this function.
-                RFB.messages.pointerEvent(this._sock,
-                                          this._display.absX(x),
-                                          this._display.absY(y),
-                                          bmask);
-            }
-        }
-
-        if (this._viewOnly) { return; } // View only, skip mouse events
-
-        if (this._rfb_connection_state !== 'connected') { return; }
-        RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask);
-    },
-
-    _handleMouseMove: function (x, y) {
-        if (this._viewportDragging) {
-            var deltaX = this._viewportDragPos.x - x;
-            var deltaY = this._viewportDragPos.y - y;
-
-            // The goal is to trigger on a certain physical width, the
-            // devicePixelRatio brings us a bit closer but is not optimal.
-            var dragThreshold = 10 * (window.devicePixelRatio || 1);
-
-            if (this._viewportHasMoved || (Math.abs(deltaX) > dragThreshold ||
-                                           Math.abs(deltaY) > dragThreshold)) {
-                this._viewportHasMoved = true;
-
-                this._viewportDragPos = {'x': x, 'y': y};
-                this._display.viewportChangePos(deltaX, deltaY);
-            }
-
-            // Skip sending mouse events
-            return;
-        }
-
-        if (this._viewOnly) { return; } // View only, skip mouse events
-
-        if (this._rfb_connection_state !== 'connected') { return; }
-        RFB.messages.pointerEvent(this._sock, this._display.absX(x), this._display.absY(y), this._mouse_buttonMask);
-    },
-
-    // Message Handlers
-
-    _negotiate_protocol_version: function () {
-        if (this._sock.rQlen() < 12) {
-            return this._fail("Received incomplete protocol version.");
-        }
-
-        var sversion = this._sock.rQshiftStr(12).substr(4, 7);
-        Log.Info("Server ProtocolVersion: " + sversion);
-        var is_repeater = 0;
-        switch (sversion) {
-            case "000.000":  // UltraVNC repeater
-                is_repeater = 1;
-                break;
-            case "003.003":
-            case "003.006":  // UltraVNC
-            case "003.889":  // Apple Remote Desktop
-                this._rfb_version = 3.3;
-                break;
-            case "003.007":
-                this._rfb_version = 3.7;
-                break;
-            case "003.008":
-            case "004.000":  // Intel AMT KVM
-            case "004.001":  // RealVNC 4.6
-            case "005.000":  // RealVNC 5.3
-                this._rfb_version = 3.8;
-                break;
-            default:
-                return this._fail("Invalid server version " + sversion);
-        }
-
-        if (is_repeater) {
-            var repeaterID = "ID:" + this._repeaterID;
-            while (repeaterID.length < 250) {
-                repeaterID += "\0";
-            }
-            this._sock.send_string(repeaterID);
-            return true;
-        }
-
-        if (this._rfb_version > this._rfb_max_version) {
-            this._rfb_version = this._rfb_max_version;
-        }
-
-        var cversion = "00" + parseInt(this._rfb_version, 10) +
-                       ".00" + ((this._rfb_version * 10) % 10);
-        this._sock.send_string("RFB " + cversion + "\n");
-        Log.Debug('Sent ProtocolVersion: ' + cversion);
-
-        this._rfb_init_state = 'Security';
-    },
-
-    _negotiate_security: function () {
-        // Polyfill since IE and PhantomJS doesn't have
-        // TypedArray.includes()
-        function includes(item, array) {
-            for (var i = 0; i < array.length; i++) {
-                if (array[i] === item) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        if (this._rfb_version >= 3.7) {
-            // Server sends supported list, client decides
-            var num_types = this._sock.rQshift8();
-            if (this._sock.rQwait("security type", num_types, 1)) { return false; }
-
-            if (num_types === 0) {
-                return this._handle_security_failure("no security types");
-            }
-
-            var types = this._sock.rQshiftBytes(num_types);
-            Log.Debug("Server security types: " + types);
-
-            // Look for each auth in preferred order
-            this._rfb_auth_scheme = 0;
-            if (includes(1, types)) {
-                this._rfb_auth_scheme = 1; // None
-            } else if (includes(22, types)) {
-                this._rfb_auth_scheme = 22; // XVP
-            } else if (includes(16, types)) {
-                this._rfb_auth_scheme = 16; // Tight
-            } else if (includes(2, types)) {
-                this._rfb_auth_scheme = 2; // VNC Auth
-            } else {
-                return this._fail("Unsupported security types (types: " + types + ")");
-            }
-
-            this._sock.send([this._rfb_auth_scheme]);
-        } else {
-            // Server decides
-            if (this._sock.rQwait("security scheme", 4)) { return false; }
-            this._rfb_auth_scheme = this._sock.rQshift32();
-        }
-
-        this._rfb_init_state = 'Authentication';
-        Log.Debug('Authenticating using scheme: ' + this._rfb_auth_scheme);
-
-        return this._init_msg(); // jump to authentication
-    },
-
-    /*
-     * Get the security failure reason if sent from the server and
-     * send the 'securityfailure' event.
-     *
-     * - The optional parameter context can be used to add some extra
-     *   context to the log output.
-     *
-     * - The optional parameter security_result_status can be used to
-     *   add a custom status code to the event.
-     */
-    _handle_security_failure: function (context, security_result_status) {
-
-        if (typeof context === 'undefined') {
-            context = "";
-        } else {
-            context = " on " + context;
-        }
-
-        if (typeof security_result_status === 'undefined') {
-            security_result_status = 1; // fail
-        }
-
-        if (this._sock.rQwait("reason length", 4)) {
-            return false;
-        }
-        let strlen = this._sock.rQshift32();
-        let reason = "";
-
-        if (strlen > 0) {
-            if (this._sock.rQwait("reason", strlen, 8)) { return false; }
-            reason = this._sock.rQshiftStr(strlen);
-        }
-
-        if (reason !== "") {
-
-            let event = new CustomEvent(
-                "securityfailure",
-                { detail: { status: security_result_status, reason: reason } });
-            this.dispatchEvent(event);
-
-            return this._fail("Security negotiation failed" + context +
-                              " (reason: " + reason + ")");
-        } else {
-
-            let event = new CustomEvent(
-                "securityfailure",
-                { detail: { status: security_result_status } });
-            this.dispatchEvent(event);
-
-            return this._fail("Security negotiation failed" + context);
-        }
-    },
-
-    // authentication
-    _negotiate_xvp_auth: function () {
-        if (!this._rfb_credentials.username ||
-            !this._rfb_credentials.password ||
-            !this._rfb_credentials.target) {
-            var event = new CustomEvent("credentialsrequired",
-                                        { detail: { types: ["username", "password", "target"] } });
-            this.dispatchEvent(event);
-            return false;
-        }
-
-        var xvp_auth_str = String.fromCharCode(this._rfb_credentials.username.length) +
-                           String.fromCharCode(this._rfb_credentials.target.length) +
-                           this._rfb_credentials.username +
-                           this._rfb_credentials.target;
-        this._sock.send_string(xvp_auth_str);
-        this._rfb_auth_scheme = 2;
-        return this._negotiate_authentication();
-    },
-
-    _negotiate_std_vnc_auth: function () {
-        if (this._sock.rQwait("auth challenge", 16)) { return false; }
-
-        if (!this._rfb_credentials.password) {
-            var event = new CustomEvent("credentialsrequired",
-                                        { detail: { types: ["password"] } });
-            this.dispatchEvent(event);
-            return false;
-        }
-
-        // TODO(directxman12): make genDES not require an Array
-        var challenge = Array.prototype.slice.call(this._sock.rQshiftBytes(16));
-        var response = RFB.genDES(this._rfb_credentials.password, challenge);
-        this._sock.send(response);
-        this._rfb_init_state = "SecurityResult";
-        return true;
-    },
-
-    _negotiate_tight_tunnels: function (numTunnels) {
-        var clientSupportedTunnelTypes = {
-            0: { vendor: 'TGHT', signature: 'NOTUNNEL' }
-        };
-        var serverSupportedTunnelTypes = {};
-        // receive tunnel capabilities
-        for (var i = 0; i < numTunnels; i++) {
-            var cap_code = this._sock.rQshift32();
-            var cap_vendor = this._sock.rQshiftStr(4);
-            var cap_signature = this._sock.rQshiftStr(8);
-            serverSupportedTunnelTypes[cap_code] = { vendor: cap_vendor, signature: cap_signature };
-        }
-
-        // choose the notunnel type
-        if (serverSupportedTunnelTypes[0]) {
-            if (serverSupportedTunnelTypes[0].vendor != clientSupportedTunnelTypes[0].vendor ||
-                serverSupportedTunnelTypes[0].signature != clientSupportedTunnelTypes[0].signature) {
-                return this._fail("Client's tunnel type had the incorrect " +
-                                  "vendor or signature");
-            }
-            this._sock.send([0, 0, 0, 0]);  // use NOTUNNEL
-            return false; // wait until we receive the sub auth count to continue
-        } else {
-            return this._fail("Server wanted tunnels, but doesn't support " +
-                              "the notunnel type");
-        }
-    },
-
-    _negotiate_tight_auth: function () {
-        if (!this._rfb_tightvnc) {  // first pass, do the tunnel negotiation
-            if (this._sock.rQwait("num tunnels", 4)) { return false; }
-            var numTunnels = this._sock.rQshift32();
-            if (numTunnels > 0 && this._sock.rQwait("tunnel capabilities", 16 * numTunnels, 4)) { return false; }
-
-            this._rfb_tightvnc = true;
-
-            if (numTunnels > 0) {
-                this._negotiate_tight_tunnels(numTunnels);
-                return false;  // wait until we receive the sub auth to continue
-            }
-        }
-
-        // second pass, do the sub-auth negotiation
-        if (this._sock.rQwait("sub auth count", 4)) { return false; }
-        var subAuthCount = this._sock.rQshift32();
-        if (subAuthCount === 0) {  // empty sub-auth list received means 'no auth' subtype selected
-            this._rfb_init_state = 'SecurityResult';
-            return true;
-        }
-
-        if (this._sock.rQwait("sub auth capabilities", 16 * subAuthCount, 4)) { return false; }
-
-        var clientSupportedTypes = {
-            'STDVNOAUTH__': 1,
-            'STDVVNCAUTH_': 2
-        };
-
-        var serverSupportedTypes = [];
-
-        for (var i = 0; i < subAuthCount; i++) {
-            var capNum = this._sock.rQshift32();
-            var capabilities = this._sock.rQshiftStr(12);
-            serverSupportedTypes.push(capabilities);
-        }
-
-        for (var authType in clientSupportedTypes) {
-            if (serverSupportedTypes.indexOf(authType) != -1) {
-                this._sock.send([0, 0, 0, clientSupportedTypes[authType]]);
-
-                switch (authType) {
-                    case 'STDVNOAUTH__':  // no auth
-                        this._rfb_init_state = 'SecurityResult';
-                        return true;
-                    case 'STDVVNCAUTH_': // VNC auth
-                        this._rfb_auth_scheme = 2;
-                        return this._init_msg();
-                    default:
-                        return this._fail("Unsupported tiny auth scheme " +
-                                          "(scheme: " + authType + ")");
-                }
-            }
-        }
-
-        return this._fail("No supported sub-auth types!");
-    },
-
-    _negotiate_authentication: function () {
-        switch (this._rfb_auth_scheme) {
-            case 0:  // connection failed
-                return this._handle_security_failure("authentication scheme");
-
-            case 1:  // no auth
-                if (this._rfb_version >= 3.8) {
-                    this._rfb_init_state = 'SecurityResult';
-                    return true;
-                }
-                this._rfb_init_state = 'ClientInitialisation';
-                return this._init_msg();
-
-            case 22:  // XVP auth
-                return this._negotiate_xvp_auth();
-
-            case 2:  // VNC authentication
-                return this._negotiate_std_vnc_auth();
-
-            case 16:  // TightVNC Security Type
-                return this._negotiate_tight_auth();
-
-            default:
-                return this._fail("Unsupported auth scheme (scheme: " +
-                                  this._rfb_auth_scheme + ")");
-        }
-    },
-
-    _handle_security_result: function () {
-        if (this._sock.rQwait('VNC auth response ', 4)) { return false; }
-
-        let status = this._sock.rQshift32();
-
-        if (status === 0) { // OK
-            this._rfb_init_state = 'ClientInitialisation';
-            Log.Debug('Authentication OK');
-            return this._init_msg();
-        } else {
-            if (this._rfb_version >= 3.8) {
-                return this._handle_security_failure("security result", status);
-            } else {
-                let event = new CustomEvent("securityfailure",
-                                            { detail: { status: status } });
-                this.dispatchEvent(event);
-
-                return this._fail("Security handshake failed");
-            }
-        }
-    },
-
-    _negotiate_server_init: function () {
-        if (this._sock.rQwait("server initialization", 24)) { return false; }
-
-        /* Screen size */
-        var width = this._sock.rQshift16();
-        var height = this._sock.rQshift16();
-
-        /* PIXEL_FORMAT */
-        var bpp         = this._sock.rQshift8();
-        var depth       = this._sock.rQshift8();
-        var big_endian  = this._sock.rQshift8();
-        var true_color  = this._sock.rQshift8();
-
-        var red_max     = this._sock.rQshift16();
-        var green_max   = this._sock.rQshift16();
-        var blue_max    = this._sock.rQshift16();
-        var red_shift   = this._sock.rQshift8();
-        var green_shift = this._sock.rQshift8();
-        var blue_shift  = this._sock.rQshift8();
-        this._sock.rQskipBytes(3);  // padding
-
-        // NB(directxman12): we don't want to call any callbacks or print messages until
-        //                   *after* we're past the point where we could backtrack
-
-        /* Connection name/title */
-        var name_length = this._sock.rQshift32();
-        if (this._sock.rQwait('server init name', name_length, 24)) { return false; }
-        this._fb_name = decodeUTF8(this._sock.rQshiftStr(name_length));
-
-        if (this._rfb_tightvnc) {
-            if (this._sock.rQwait('TightVNC extended server init header', 8, 24 + name_length)) { return false; }
-            // In TightVNC mode, ServerInit message is extended
-            var numServerMessages = this._sock.rQshift16();
-            var numClientMessages = this._sock.rQshift16();
-            var numEncodings = this._sock.rQshift16();
-            this._sock.rQskipBytes(2);  // padding
-
-            var totalMessagesLength = (numServerMessages + numClientMessages + numEncodings) * 16;
-            if (this._sock.rQwait('TightVNC extended server init header', totalMessagesLength, 32 + name_length)) { return false; }
-
-            // we don't actually do anything with the capability information that TIGHT sends,
-            // so we just skip the all of this.
-
-            // TIGHT server message capabilities
-            this._sock.rQskipBytes(16 * numServerMessages);
-
-            // TIGHT client message capabilities
-            this._sock.rQskipBytes(16 * numClientMessages);
-
-            // TIGHT encoding capabilities
-            this._sock.rQskipBytes(16 * numEncodings);
-        }
-
-        // NB(directxman12): these are down here so that we don't run them multiple times
-        //                   if we backtrack
-        Log.Info("Screen: " + width + "x" + height +
-                  ", bpp: " + bpp + ", depth: " + depth +
-                  ", big_endian: " + big_endian +
-                  ", true_color: " + true_color +
-                  ", red_max: " + red_max +
-                  ", green_max: " + green_max +
-                  ", blue_max: " + blue_max +
-                  ", red_shift: " + red_shift +
-                  ", green_shift: " + green_shift +
-                  ", blue_shift: " + blue_shift);
-
-        if (big_endian !== 0) {
-            Log.Warn("Server native endian is not little endian");
-        }
-
-        if (red_shift !== 16) {
-            Log.Warn("Server native red-shift is not 16");
-        }
-
-        if (blue_shift !== 0) {
-            Log.Warn("Server native blue-shift is not 0");
-        }
-
-        // we're past the point where we could backtrack, so it's safe to call this
-        var event = new CustomEvent("desktopname",
-                                    { detail: { name: this._fb_name } });
-        this.dispatchEvent(event);
-
-        this._resize(width, height);
-
-        if (!this._viewOnly) { this._keyboard.grab(); }
-        if (!this._viewOnly) { this._mouse.grab(); }
-
-        this._fb_depth = 24;
-
-        if (this._fb_name === "Intel(r) AMT KVM") {
-            Log.Warn("Intel AMT KVM only supports 8/16 bit depths. Using low color mode.");
-            this._fb_depth = 8;
-        } else if (this._fb_name === "MBSE BrewBoard") {
-	    Log.Warn("MBSE BrewBoard only supports 8 bit depths. Using low color mode.");
-	    this._fb_depth = 8;
-	}
-
-        RFB.messages.pixelFormat(this._sock, this._fb_depth, true);
-        this._sendEncodings();
-        RFB.messages.fbUpdateRequest(this._sock, false, 0, 0, this._fb_width, this._fb_height);
-
-        this._timing.fbu_rt_start = (new Date()).getTime();
-        this._timing.pixels = 0;
-
-        // Cursor will be server side until the server decides to honor
-        // our request and send over the cursor image
-        this._display.disableLocalCursor();
-
-        this._updateConnectionState('connected');
-        return true;
-    },
-
-    _sendEncodings: function () {
-        var encs = [];
-
-        // In preference order
-        encs.push(encodings.encodingCopyRect);
-        // Only supported with full depth support
-        if (this._fb_depth == 24) {
-            encs.push(encodings.encodingTight);
-            encs.push(encodings.encodingHextile);
-            encs.push(encodings.encodingRRE);
-        }
-        encs.push(encodings.encodingRaw);
-
-        // Psuedo-encoding settings
-        encs.push(encodings.pseudoEncodingTightPNG);
-        encs.push(encodings.pseudoEncodingQualityLevel0 + 6);
-        encs.push(encodings.pseudoEncodingCompressLevel0 + 2);
-
-        encs.push(encodings.pseudoEncodingDesktopSize);
-        encs.push(encodings.pseudoEncodingLastRect);
-        encs.push(encodings.pseudoEncodingQEMUExtendedKeyEvent);
-        encs.push(encodings.pseudoEncodingExtendedDesktopSize);
-        encs.push(encodings.pseudoEncodingXvp);
-        encs.push(encodings.pseudoEncodingFence);
-        encs.push(encodings.pseudoEncodingContinuousUpdates);
-
-        if (supportsCursorURIs() &&
-            !isTouchDevice && this._fb_depth == 24) {
-            encs.push(encodings.pseudoEncodingCursor);
-        }
-
-        RFB.messages.clientEncodings(this._sock, encs);
-    },
-
-    /* RFB protocol initialization states:
-     *   ProtocolVersion
-     *   Security
-     *   Authentication
-     *   SecurityResult
-     *   ClientInitialization - not triggered by server message
-     *   ServerInitialization
-     */
-    _init_msg: function () {
-        switch (this._rfb_init_state) {
-            case 'ProtocolVersion':
-                return this._negotiate_protocol_version();
-
-            case 'Security':
-                return this._negotiate_security();
-
-            case 'Authentication':
-                return this._negotiate_authentication();
-
-            case 'SecurityResult':
-                return this._handle_security_result();
-
-            case 'ClientInitialisation':
-                this._sock.send([this._shared ? 1 : 0]); // ClientInitialisation
-                this._rfb_init_state = 'ServerInitialisation';
-                return true;
-
-            case 'ServerInitialisation':
-                return this._negotiate_server_init();
-
-            default:
-                return this._fail("Unknown init state (state: " +
-                                  this._rfb_init_state + ")");
-        }
-    },
-
-    _handle_set_colour_map_msg: function () {
-        Log.Debug("SetColorMapEntries");
-
-        return this._fail("Unexpected SetColorMapEntries message");
-    },
-
-    _handle_server_cut_text: function () {
-        Log.Debug("ServerCutText");
-
-        if (this._sock.rQwait("ServerCutText header", 7, 1)) { return false; }
-        this._sock.rQskipBytes(3);  // Padding
-        var length = this._sock.rQshift32();
-        if (this._sock.rQwait("ServerCutText", length, 8)) { return false; }
-
-        var text = this._sock.rQshiftStr(length);
-
-        if (this._viewOnly) { return true; }
-
-        var event = new CustomEvent("clipboard",
-                                    { detail: { text: text } });
-        this.dispatchEvent(event);
-
-        return true;
-    },
-
-    _handle_server_fence_msg: function() {
-        if (this._sock.rQwait("ServerFence header", 8, 1)) { return false; }
-        this._sock.rQskipBytes(3); // Padding
-        var flags = this._sock.rQshift32();
-        var length = this._sock.rQshift8();
-
-        if (this._sock.rQwait("ServerFence payload", length, 9)) { return false; }
-
-        if (length > 64) {
-            Log.Warn("Bad payload length (" + length + ") in fence response");
-            length = 64;
-        }
-
-        var payload = this._sock.rQshiftStr(length);
-
-        this._supportsFence = true;
-
-        /*
-         * Fence flags
-         *
-         *  (1<<0)  - BlockBefore
-         *  (1<<1)  - BlockAfter
-         *  (1<<2)  - SyncNext
-         *  (1<<31) - Request
-         */
-
-        if (!(flags & (1<<31))) {
-            return this._fail("Unexpected fence response");
-        }
-
-        // Filter out unsupported flags
-        // FIXME: support syncNext
-        flags &= (1<<0) | (1<<1);
-
-        // BlockBefore and BlockAfter are automatically handled by
-        // the fact that we process each incoming message
-        // synchronuosly.
-        RFB.messages.clientFence(this._sock, flags, payload);
-
-        return true;
-    },
-
-    _handle_xvp_msg: function () {
-        if (this._sock.rQwait("XVP version and message", 3, 1)) { return false; }
-        this._sock.rQskip8();  // Padding
-        var xvp_ver = this._sock.rQshift8();
-        var xvp_msg = this._sock.rQshift8();
-
-        switch (xvp_msg) {
-            case 0:  // XVP_FAIL
-                Log.Error("XVP Operation Failed");
-                break;
-            case 1:  // XVP_INIT
-                this._rfb_xvp_ver = xvp_ver;
-                Log.Info("XVP extensions enabled (version " + this._rfb_xvp_ver + ")");
-                this._setCapability("power", true);
-                break;
-            default:
-                this._fail("Illegal server XVP message (msg: " + xvp_msg + ")");
-                break;
-        }
-
-        return true;
-    },
-
-    _normal_msg: function () {
-        var msg_type;
-
-        if (this._FBU.rects > 0) {
-            msg_type = 0;
-        } else {
-            msg_type = this._sock.rQshift8();
-        }
-
-        switch (msg_type) {
-            case 0:  // FramebufferUpdate
-                var ret = this._framebufferUpdate();
-                if (ret && !this._enabledContinuousUpdates) {
-                    RFB.messages.fbUpdateRequest(this._sock, true, 0, 0,
-                                                 this._fb_width, this._fb_height);
-                }
-                return ret;
-
-            case 1:  // SetColorMapEntries
-                return this._handle_set_colour_map_msg();
-
-            case 2:  // Bell
-                Log.Debug("Bell");
-                var event = new CustomEvent("bell", { detail: {} });
-                this.dispatchEvent(event);
-                return true;
-
-            case 3:  // ServerCutText
-                return this._handle_server_cut_text();
-
-            case 150: // EndOfContinuousUpdates
-                var first = !(this._supportsContinuousUpdates);
-                this._supportsContinuousUpdates = true;
-                this._enabledContinuousUpdates = false;
-                if (first) {
-                    this._enabledContinuousUpdates = true;
-                    this._updateContinuousUpdates();
-                    Log.Info("Enabling continuous updates.");
-                } else {
-                    // FIXME: We need to send a framebufferupdaterequest here
-                    // if we add support for turning off continuous updates
-                }
-                return true;
-
-            case 248: // ServerFence
-                return this._handle_server_fence_msg();
-
-            case 250:  // XVP
-                return this._handle_xvp_msg();
-
-            default:
-                this._fail("Unexpected server message (type " + msg_type + ")");
-                Log.Debug("sock.rQslice(0, 30): " + this._sock.rQslice(0, 30));
-                return true;
-        }
-    },
-
-    _onFlush: function() {
-        this._flushing = false;
-        // Resume processing
-        if (this._sock.rQlen() > 0) {
-            this._handle_message();
-        }
-    },
-
-    _framebufferUpdate: function () {
-        var ret = true;
-        var now;
-
-        if (this._FBU.rects === 0) {
-            if (this._sock.rQwait("FBU header", 3, 1)) { return false; }
-            this._sock.rQskip8();  // Padding
-            this._FBU.rects = this._sock.rQshift16();
-            this._FBU.bytes = 0;
-            this._timing.cur_fbu = 0;
-            if (this._timing.fbu_rt_start > 0) {
-                now = (new Date()).getTime();
-                Log.Info("First FBU latency: " + (now - this._timing.fbu_rt_start));
-            }
-
-            // Make sure the previous frame is fully rendered first
-            // to avoid building up an excessive queue
-            if (this._display.pending()) {
-                this._flushing = true;
-                this._display.flush();
-                return false;
-            }
-        }
-
-        while (this._FBU.rects > 0) {
-            if (this._rfb_connection_state !== 'connected') { return false; }
-
-            if (this._sock.rQwait("FBU", this._FBU.bytes)) { return false; }
-            if (this._FBU.bytes === 0) {
-                if (this._sock.rQwait("rect header", 12)) { return false; }
-                /* New FramebufferUpdate */
-
-                var hdr = this._sock.rQshiftBytes(12);
-                this._FBU.x        = (hdr[0] << 8) + hdr[1];
-                this._FBU.y        = (hdr[2] << 8) + hdr[3];
-                this._FBU.width    = (hdr[4] << 8) + hdr[5];
-                this._FBU.height   = (hdr[6] << 8) + hdr[7];
-                this._FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) +
-                                              (hdr[10] << 8) + hdr[11], 10);
-
-                if (!this._encHandlers[this._FBU.encoding]) {
-                    this._fail("Unsupported encoding (encoding: " +
-                               this._FBU.encoding + ")");
-                    return false;
-                }
-            }
-
-            this._timing.last_fbu = (new Date()).getTime();
-
-            ret = this._encHandlers[this._FBU.encoding]();
-
-            now = (new Date()).getTime();
-            this._timing.cur_fbu += (now - this._timing.last_fbu);
-
-            if (ret) {
-                if (!(this._FBU.encoding in this._encStats)) {
-                    this._encStats[this._FBU.encoding] = [0, 0];
-                }
-                this._encStats[this._FBU.encoding][0]++;
-                this._encStats[this._FBU.encoding][1]++;
-                this._timing.pixels += this._FBU.width * this._FBU.height;
-            }
-
-            if (this._timing.pixels >= (this._fb_width * this._fb_height)) {
-                if ((this._FBU.width === this._fb_width && this._FBU.height === this._fb_height) ||
-                    this._timing.fbu_rt_start > 0) {
-                    this._timing.full_fbu_total += this._timing.cur_fbu;
-                    this._timing.full_fbu_cnt++;
-                    Log.Info("Timing of full FBU, curr: " +
-                              this._timing.cur_fbu + ", total: " +
-                              this._timing.full_fbu_total + ", cnt: " +
-                              this._timing.full_fbu_cnt + ", avg: " +
-                              (this._timing.full_fbu_total / this._timing.full_fbu_cnt));
-                }
-
-                if (this._timing.fbu_rt_start > 0) {
-                    var fbu_rt_diff = now - this._timing.fbu_rt_start;
-                    this._timing.fbu_rt_total += fbu_rt_diff;
-                    this._timing.fbu_rt_cnt++;
-                    Log.Info("full FBU round-trip, cur: " +
-                              fbu_rt_diff + ", total: " +
-                              this._timing.fbu_rt_total + ", cnt: " +
-                              this._timing.fbu_rt_cnt + ", avg: " +
-                              (this._timing.fbu_rt_total / this._timing.fbu_rt_cnt));
-                    this._timing.fbu_rt_start = 0;
-                }
-            }
-
-            if (!ret) { return ret; }  // need more data
-        }
-
-        this._display.flip();
-
-        return true;  // We finished this FBU
-    },
-
-    _updateContinuousUpdates: function() {
-        if (!this._enabledContinuousUpdates) { return; }
-
-        RFB.messages.enableContinuousUpdates(this._sock, true, 0, 0,
-                                             this._fb_width, this._fb_height);
-    },
-
-    _resize: function(width, height) {
-        this._fb_width = width;
-        this._fb_height = height;
-
-        this._destBuff = new Uint8Array(this._fb_width * this._fb_height * 4);
-
-        this._display.resize(this._fb_width, this._fb_height);
-
-        // Adjust the visible viewport based on the new dimensions
-        this._updateClip();
-        this._updateScale();
-
-        this._timing.fbu_rt_start = (new Date()).getTime();
-        this._updateContinuousUpdates();
-    },
-
-    _xvpOp: function (ver, op) {
-        if (this._rfb_xvp_ver < ver) { return; }
-        Log.Info("Sending XVP operation " + op + " (version " + ver + ")");
-        RFB.messages.xvpOp(this._sock, ver, op);
-    },
-};
-
-Object.assign(RFB.prototype, EventTargetMixin);
-
-// Class Methods
-RFB.messages = {
-    keyEvent: function (sock, keysym, down) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 4;  // msg-type
-        buff[offset + 1] = down;
-
-        buff[offset + 2] = 0;
-        buff[offset + 3] = 0;
-
-        buff[offset + 4] = (keysym >> 24);
-        buff[offset + 5] = (keysym >> 16);
-        buff[offset + 6] = (keysym >> 8);
-        buff[offset + 7] = keysym;
-
-        sock._sQlen += 8;
-        sock.flush();
-    },
-
-    QEMUExtendedKeyEvent: function (sock, keysym, down, keycode) {
-        function getRFBkeycode(xt_scancode) {
-            var upperByte = (keycode >> 8);
-            var lowerByte = (keycode & 0x00ff);
-            if (upperByte === 0xe0 && lowerByte < 0x7f) {
-                lowerByte = lowerByte | 0x80;
-                return lowerByte;
-            }
-            return xt_scancode;
-        }
-
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 255; // msg-type
-        buff[offset + 1] = 0; // sub msg-type
-
-        buff[offset + 2] = (down >> 8);
-        buff[offset + 3] = down;
-
-        buff[offset + 4] = (keysym >> 24);
-        buff[offset + 5] = (keysym >> 16);
-        buff[offset + 6] = (keysym >> 8);
-        buff[offset + 7] = keysym;
-
-        var RFBkeycode = getRFBkeycode(keycode);
-
-        buff[offset + 8] = (RFBkeycode >> 24);
-        buff[offset + 9] = (RFBkeycode >> 16);
-        buff[offset + 10] = (RFBkeycode >> 8);
-        buff[offset + 11] = RFBkeycode;
-
-        sock._sQlen += 12;
-        sock.flush();
-    },
-
-    pointerEvent: function (sock, x, y, mask) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 5; // msg-type
-
-        buff[offset + 1] = mask;
-
-        buff[offset + 2] = x >> 8;
-        buff[offset + 3] = x;
-
-        buff[offset + 4] = y >> 8;
-        buff[offset + 5] = y;
-
-        sock._sQlen += 6;
-        sock.flush();
-    },
-
-    // TODO(directxman12): make this unicode compatible?
-    clientCutText: function (sock, text) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 6; // msg-type
-
-        buff[offset + 1] = 0; // padding
-        buff[offset + 2] = 0; // padding
-        buff[offset + 3] = 0; // padding
-
-        var n = text.length;
-
-        buff[offset + 4] = n >> 24;
-        buff[offset + 5] = n >> 16;
-        buff[offset + 6] = n >> 8;
-        buff[offset + 7] = n;
-
-        for (var i = 0; i < n; i++) {
-            buff[offset + 8 + i] =  text.charCodeAt(i);
-        }
-
-        sock._sQlen += 8 + n;
-        sock.flush();
-    },
-
-    setDesktopSize: function (sock, width, height, id, flags) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 251;              // msg-type
-        buff[offset + 1] = 0;            // padding
-        buff[offset + 2] = width >> 8;   // width
-        buff[offset + 3] = width;
-        buff[offset + 4] = height >> 8;  // height
-        buff[offset + 5] = height;
-
-        buff[offset + 6] = 1;            // number-of-screens
-        buff[offset + 7] = 0;            // padding
-
-        // screen array
-        buff[offset + 8] = id >> 24;     // id
-        buff[offset + 9] = id >> 16;
-        buff[offset + 10] = id >> 8;
-        buff[offset + 11] = id;
-        buff[offset + 12] = 0;           // x-position
-        buff[offset + 13] = 0;
-        buff[offset + 14] = 0;           // y-position
-        buff[offset + 15] = 0;
-        buff[offset + 16] = width >> 8;  // width
-        buff[offset + 17] = width;
-        buff[offset + 18] = height >> 8; // height
-        buff[offset + 19] = height;
-        buff[offset + 20] = flags >> 24; // flags
-        buff[offset + 21] = flags >> 16;
-        buff[offset + 22] = flags >> 8;
-        buff[offset + 23] = flags;
-
-        sock._sQlen += 24;
-        sock.flush();
-    },
-
-    clientFence: function (sock, flags, payload) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 248; // msg-type
-
-        buff[offset + 1] = 0; // padding
-        buff[offset + 2] = 0; // padding
-        buff[offset + 3] = 0; // padding
-
-        buff[offset + 4] = flags >> 24; // flags
-        buff[offset + 5] = flags >> 16;
-        buff[offset + 6] = flags >> 8;
-        buff[offset + 7] = flags;
-
-        var n = payload.length;
-
-        buff[offset + 8] = n; // length
-
-        for (var i = 0; i < n; i++) {
-            buff[offset + 9 + i] = payload.charCodeAt(i);
-        }
-
-        sock._sQlen += 9 + n;
-        sock.flush();
-    },
-
-    enableContinuousUpdates: function (sock, enable, x, y, width, height) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 150;             // msg-type
-        buff[offset + 1] = enable;      // enable-flag
-
-        buff[offset + 2] = x >> 8;      // x
-        buff[offset + 3] = x;
-        buff[offset + 4] = y >> 8;      // y
-        buff[offset + 5] = y;
-        buff[offset + 6] = width >> 8;  // width
-        buff[offset + 7] = width;
-        buff[offset + 8] = height >> 8; // height
-        buff[offset + 9] = height;
-
-        sock._sQlen += 10;
-        sock.flush();
-    },
-
-    pixelFormat: function (sock, depth, true_color) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        var bpp, bits;
-
-        if (depth > 16) {
-            bpp = 32;
-        } else if (depth > 8) {
-            bpp = 16;
-        } else {
-            bpp = 8;
-        }
-
-        bits = Math.floor(depth/3);
-
-        buff[offset] = 0;  // msg-type
-
-        buff[offset + 1] = 0; // padding
-        buff[offset + 2] = 0; // padding
-        buff[offset + 3] = 0; // padding
-
-        buff[offset + 4] = bpp;                 // bits-per-pixel
-        buff[offset + 5] = depth;               // depth
-        buff[offset + 6] = 0;                   // little-endian
-        buff[offset + 7] = true_color ? 1 : 0;  // true-color
-
-        buff[offset + 8] = 0;    // red-max
-        buff[offset + 10] = 0;   // green-max
-        buff[offset + 12] = 0;   // blue-max
-
-	if (depth == 8) {
-	    buff[offset + 9] = 7;	// red-max
-	    buff[offset + 11] = 7;	// green-max
-	    buff[offset + 13] = 3;	// blue-max
-	    buff[offset + 14] = 5;	// red-shift
-	    buff[offset + 15] = 2;	// green-shift
-	    buff[offset + 16] = 0;	// blue-shift
-	} else {
-	    buff[offset + 9] = (1 << bits) - 1;  // red-max
-	    buff[offset + 11] = (1 << bits) - 1; // green-max
-	    buff[offset + 13] = (1 << bits) - 1; // blue-max
-            buff[offset + 14] = bits * 2; // red-shift
-            buff[offset + 15] = bits * 1; // green-shift
-            buff[offset + 16] = bits * 0; // blue-shift
-	}
-
-        buff[offset + 17] = 0;   // padding
-        buff[offset + 18] = 0;   // padding
-        buff[offset + 19] = 0;   // padding
-
-        sock._sQlen += 20;
-        sock.flush();
-    },
-
-    clientEncodings: function (sock, encodings) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 2; // msg-type
-        buff[offset + 1] = 0; // padding
-
-        buff[offset + 2] = encodings.length >> 8;
-        buff[offset + 3] = encodings.length;
-
-        var i, j = offset + 4;
-        for (i = 0; i < encodings.length; i++) {
-            var enc = encodings[i];
-            buff[j] = enc >> 24;
-            buff[j + 1] = enc >> 16;
-            buff[j + 2] = enc >> 8;
-            buff[j + 3] = enc;
-
-            j += 4;
-        }
-
-        sock._sQlen += j - offset;
-        sock.flush();
-    },
-
-    fbUpdateRequest: function (sock, incremental, x, y, w, h) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        if (typeof(x) === "undefined") { x = 0; }
-        if (typeof(y) === "undefined") { y = 0; }
-
-        buff[offset] = 3;  // msg-type
-        buff[offset + 1] = incremental ? 1 : 0;
-
-        buff[offset + 2] = (x >> 8) & 0xFF;
-        buff[offset + 3] = x & 0xFF;
-
-        buff[offset + 4] = (y >> 8) & 0xFF;
-        buff[offset + 5] = y & 0xFF;
-
-        buff[offset + 6] = (w >> 8) & 0xFF;
-        buff[offset + 7] = w & 0xFF;
-
-        buff[offset + 8] = (h >> 8) & 0xFF;
-        buff[offset + 9] = h & 0xFF;
-
-        sock._sQlen += 10;
-        sock.flush();
-    },
-
-    xvpOp: function (sock, ver, op) {
-        var buff = sock._sQ;
-        var offset = sock._sQlen;
-
-        buff[offset] = 250; // msg-type
-        buff[offset + 1] = 0; // padding
-
-        buff[offset + 2] = ver;
-        buff[offset + 3] = op;
-
-        sock._sQlen += 4;
-        sock.flush();
-    },
-};
-
-RFB.genDES = function (password, challenge) {
-    var passwd = [];
-    for (var i = 0; i < password.length; i++) {
-        passwd.push(password.charCodeAt(i));
-    }
-    return (new DES(passwd)).encrypt(challenge);
-};
-
-RFB.encodingHandlers = {
-    RAW: function () {
-        if (this._FBU.lines === 0) {
-            this._FBU.lines = this._FBU.height;
-        }
-
-        var pixelSize = this._fb_depth == 8 ? 1 : 4;
-        this._FBU.bytes = this._FBU.width * pixelSize;  // at least a line
-        if (this._sock.rQwait("RAW", this._FBU.bytes)) { return false; }
-        var cur_y = this._FBU.y + (this._FBU.height - this._FBU.lines);
-        var curr_height = Math.min(this._FBU.lines,
-                                   Math.floor(this._sock.rQlen() / (this._FBU.width * pixelSize)));
-        var data = this._sock.get_rQ();
-        var index = this._sock.get_rQi();
-        if (this._fb_depth == 8) {
-            var pixels = this._FBU.width * curr_height
-            var newdata = new Uint8Array(pixels * 4);
-            var i;
-            for (i = 0;i < pixels;i++) {
-                //newdata[i * 4 + 0] = ((data[index + i] >> 0) & 0x3) * 255 / 3;
-                //newdata[i * 4 + 1] = ((data[index + i] >> 2) & 0x3) * 255 / 3;
-                //newdata[i * 4 + 2] = ((data[index + i] >> 4) & 0x3) * 255 / 3;
-		// Convert 8 bit RGB332 color to internal RGB888.
-		newdata[i * 4 + 0] = ((data[index + i] >> 0) & 0x3) * 255 / 3;	// blue
-		newdata[i * 4 + 1] = ((data[index + i] >> 2) & 0x7) * 255 / 7;	// green
-		newdata[i * 4 + 2] = ((data[index + i] >> 5) & 0x7) * 255 / 7;	// red
-                newdata[i * 4 + 4] = 0;
-            }
-            data = newdata;
-            index = 0;
-        }
-        this._display.blitImage(this._FBU.x, cur_y, this._FBU.width,
-                                curr_height, data, index);
-        this._sock.rQskipBytes(this._FBU.width * curr_height * pixelSize);
-        this._FBU.lines -= curr_height;
-
-        if (this._FBU.lines > 0) {
-            this._FBU.bytes = this._FBU.width * pixelSize;  // At least another line
-        } else {
-            this._FBU.rects--;
-            this._FBU.bytes = 0;
-        }
-
-        return true;
-    },
-
-    COPYRECT: function () {
-        this._FBU.bytes = 4;
-        if (this._sock.rQwait("COPYRECT", 4)) { return false; }
-        this._display.copyImage(this._sock.rQshift16(), this._sock.rQshift16(),
-                                this._FBU.x, this._FBU.y, this._FBU.width,
-                                this._FBU.height);
-
-        this._FBU.rects--;
-        this._FBU.bytes = 0;
-        return true;
-    },
-
-    RRE: function () {
-        var color;
-        if (this._FBU.subrects === 0) {
-            this._FBU.bytes = 4 + 4;
-            if (this._sock.rQwait("RRE", 4 + 4)) { return false; }
-            this._FBU.subrects = this._sock.rQshift32();
-            color = this._sock.rQshiftBytes(4);  // Background
-            this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, color);
-        }
-
-        while (this._FBU.subrects > 0 && this._sock.rQlen() >= (4 + 8)) {
-            color = this._sock.rQshiftBytes(4);
-            var x = this._sock.rQshift16();
-            var y = this._sock.rQshift16();
-            var width = this._sock.rQshift16();
-            var height = this._sock.rQshift16();
-            this._display.fillRect(this._FBU.x + x, this._FBU.y + y, width, height, color);
-            this._FBU.subrects--;
-        }
-
-        if (this._FBU.subrects > 0) {
-            var chunk = Math.min(this._rre_chunk_sz, this._FBU.subrects);
-            this._FBU.bytes = (4 + 8) * chunk;
-        } else {
-            this._FBU.rects--;
-            this._FBU.bytes = 0;
-        }
-
-        return true;
-    },
-
-    HEXTILE: function () {
-        var rQ = this._sock.get_rQ();
-        var rQi = this._sock.get_rQi();
-
-        if (this._FBU.tiles === 0) {
-            this._FBU.tiles_x = Math.ceil(this._FBU.width / 16);
-            this._FBU.tiles_y = Math.ceil(this._FBU.height / 16);
-            this._FBU.total_tiles = this._FBU.tiles_x * this._FBU.tiles_y;
-            this._FBU.tiles = this._FBU.total_tiles;
-        }
-
-        while (this._FBU.tiles > 0) {
-            this._FBU.bytes = 1;
-            if (this._sock.rQwait("HEXTILE subencoding", this._FBU.bytes)) { return false; }
-            var subencoding = rQ[rQi];  // Peek
-            if (subencoding > 30) {  // Raw
-                this._fail("Illegal hextile subencoding (subencoding: " +
-                           subencoding + ")");
-                return false;
-            }
-
-            var subrects = 0;
-            var curr_tile = this._FBU.total_tiles - this._FBU.tiles;
-            var tile_x = curr_tile % this._FBU.tiles_x;
-            var tile_y = Math.floor(curr_tile / this._FBU.tiles_x);
-            var x = this._FBU.x + tile_x * 16;
-            var y = this._FBU.y + tile_y * 16;
-            var w = Math.min(16, (this._FBU.x + this._FBU.width) - x);
-            var h = Math.min(16, (this._FBU.y + this._FBU.height) - y);
-
-            // Figure out how much we are expecting
-            if (subencoding & 0x01) {  // Raw
-                this._FBU.bytes += w * h * 4;
-            } else {
-                if (subencoding & 0x02) {  // Background
-                    this._FBU.bytes += 4;
-                }
-                if (subencoding & 0x04) {  // Foreground
-                    this._FBU.bytes += 4;
-                }
-                if (subencoding & 0x08) {  // AnySubrects
-                    this._FBU.bytes++;  // Since we aren't shifting it off
-                    if (this._sock.rQwait("hextile subrects header", this._FBU.bytes)) { return false; }
-                    subrects = rQ[rQi + this._FBU.bytes - 1];  // Peek
-                    if (subencoding & 0x10) {  // SubrectsColoured
-                        this._FBU.bytes += subrects * (4 + 2);
-                    } else {
-                        this._FBU.bytes += subrects * 2;
-                    }
-                }
-            }
-
-            if (this._sock.rQwait("hextile", this._FBU.bytes)) { return false; }
-
-            // We know the encoding and have a whole tile
-            this._FBU.subencoding = rQ[rQi];
-            rQi++;
-            if (this._FBU.subencoding === 0) {
-                if (this._FBU.lastsubencoding & 0x01) {
-                    // Weird: ignore blanks are RAW
-                    Log.Debug("     Ignoring blank after RAW");
-                } else {
-                    this._display.fillRect(x, y, w, h, this._FBU.background);
-                }
-            } else if (this._FBU.subencoding & 0x01) {  // Raw
-                this._display.blitImage(x, y, w, h, rQ, rQi);
-                rQi += this._FBU.bytes - 1;
-            } else {
-                if (this._FBU.subencoding & 0x02) {  // Background
-                    this._FBU.background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
-                    rQi += 4;
-                }
-                if (this._FBU.subencoding & 0x04) {  // Foreground
-                    this._FBU.foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
-                    rQi += 4;
-                }
-
-                this._display.startTile(x, y, w, h, this._FBU.background);
-                if (this._FBU.subencoding & 0x08) {  // AnySubrects
-                    subrects = rQ[rQi];
-                    rQi++;
-
-                    for (var s = 0; s < subrects; s++) {
-                        var color;
-                        if (this._FBU.subencoding & 0x10) {  // SubrectsColoured
-                            color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
-                            rQi += 4;
-                        } else {
-                            color = this._FBU.foreground;
-                        }
-                        var xy = rQ[rQi];
-                        rQi++;
-                        var sx = (xy >> 4);
-                        var sy = (xy & 0x0f);
-
-                        var wh = rQ[rQi];
-                        rQi++;
-                        var sw = (wh >> 4) + 1;
-                        var sh = (wh & 0x0f) + 1;
-
-                        this._display.subTile(sx, sy, sw, sh, color);
-                    }
-                }
-                this._display.finishTile();
-            }
-            this._sock.set_rQi(rQi);
-            this._FBU.lastsubencoding = this._FBU.subencoding;
-            this._FBU.bytes = 0;
-            this._FBU.tiles--;
-        }
-
-        if (this._FBU.tiles === 0) {
-            this._FBU.rects--;
-        }
-
-        return true;
-    },
-
-    TIGHT: function () {
-        this._FBU.bytes = 1;  // compression-control byte
-        if (this._sock.rQwait("TIGHT compression-control", this._FBU.bytes)) { return false; }
-
-        var checksum = function (data) {
-            var sum = 0;
-            for (var i = 0; i < data.length; i++) {
-                sum += data[i];
-                if (sum > 65536) sum -= 65536;
-            }
-            return sum;
-        };
-
-        var resetStreams = 0;
-        var streamId = -1;
-        var decompress = function (data, expected) {
-            for (var i = 0; i < 4; i++) {
-                if ((resetStreams >> i) & 1) {
-                    this._FBU.zlibs[i].reset();
-                    Log.Info("Reset zlib stream " + i);
-                }
-            }
-
-            //var uncompressed = this._FBU.zlibs[streamId].uncompress(data, 0);
-            var uncompressed = this._FBU.zlibs[streamId].inflate(data, true, expected);
-            /*if (uncompressed.status !== 0) {
-                Log.Error("Invalid data in zlib stream");
-            }*/
-
-            //return uncompressed.data;
-            return uncompressed;
-        }.bind(this);
-
-        var indexedToRGBX2Color = function (data, palette, width, height) {
-            // Convert indexed (palette based) image data to RGB
-            // TODO: reduce number of calculations inside loop
-            var dest = this._destBuff;
-            var w = Math.floor((width + 7) / 8);
-            var w1 = Math.floor(width / 8);
-
-            /*for (var y = 0; y < height; y++) {
-                var b, x, dp, sp;
-                var yoffset = y * width;
-                var ybitoffset = y * w;
-                var xoffset, targetbyte;
-                for (x = 0; x < w1; x++) {
-                    xoffset = yoffset + x * 8;
-                    targetbyte = data[ybitoffset + x];
-                    for (b = 7; b >= 0; b--) {
-                        dp = (xoffset + 7 - b) * 3;
-                        sp = (targetbyte >> b & 1) * 3;
-                        dest[dp] = palette[sp];
-                        dest[dp + 1] = palette[sp + 1];
-                        dest[dp + 2] = palette[sp + 2];
-                    }
-                }
-
-                xoffset = yoffset + x * 8;
-                targetbyte = data[ybitoffset + x];
-                for (b = 7; b >= 8 - width % 8; b--) {
-                    dp = (xoffset + 7 - b) * 3;
-                    sp = (targetbyte >> b & 1) * 3;
-                    dest[dp] = palette[sp];
-                    dest[dp + 1] = palette[sp + 1];
-                    dest[dp + 2] = palette[sp + 2];
-                }
-            }*/
-
-            for (var y = 0; y < height; y++) {
-                var b, x, dp, sp;
-                for (x = 0; x < w1; x++) {
-                    for (b = 7; b >= 0; b--) {
-                        dp = (y * width + x * 8 + 7 - b) * 4;
-                        sp = (data[y * w + x] >> b & 1) * 3;
-                        dest[dp] = palette[sp];
-                        dest[dp + 1] = palette[sp + 1];
-                        dest[dp + 2] = palette[sp + 2];
-                        dest[dp + 3] = 255;
-                    }
-                }
-
-                for (b = 7; b >= 8 - width % 8; b--) {
-                    dp = (y * width + x * 8 + 7 - b) * 4;
-                    sp = (data[y * w + x] >> b & 1) * 3;
-                    dest[dp] = palette[sp];
-                    dest[dp + 1] = palette[sp + 1];
-                    dest[dp + 2] = palette[sp + 2];
-                    dest[dp + 3] = 255;
-                }
-            }
-
-            return dest;
-        }.bind(this);
-
-        var indexedToRGBX = function (data, palette, width, height) {
-            // Convert indexed (palette based) image data to RGB
-            var dest = this._destBuff;
-            var total = width * height * 4;
-            for (var i = 0, j = 0; i < total; i += 4, j++) {
-                var sp = data[j] * 3;
-                dest[i] = palette[sp];
-                dest[i + 1] = palette[sp + 1];
-                dest[i + 2] = palette[sp + 2];
-                dest[i + 3] = 255;
-            }
-
-            return dest;
-        }.bind(this);
-
-        var rQi = this._sock.get_rQi();
-        var rQ = this._sock.rQwhole();
-        var cmode, data;
-        var cl_header, cl_data;
-
-        var handlePalette = function () {
-            var numColors = rQ[rQi + 2] + 1;
-            var paletteSize = numColors * 3;
-            this._FBU.bytes += paletteSize;
-            if (this._sock.rQwait("TIGHT palette " + cmode, this._FBU.bytes)) { return false; }
-
-            var bpp = (numColors <= 2) ? 1 : 8;
-            var rowSize = Math.floor((this._FBU.width * bpp + 7) / 8);
-            var raw = false;
-            if (rowSize * this._FBU.height < 12) {
-                raw = true;
-                cl_header = 0;
-                cl_data = rowSize * this._FBU.height;
-                //clength = [0, rowSize * this._FBU.height];
-            } else {
-                // begin inline getTightCLength (returning two-item arrays is bad for performance with GC)
-                var cl_offset = rQi + 3 + paletteSize;
-                cl_header = 1;
-                cl_data = 0;
-                cl_data += rQ[cl_offset] & 0x7f;
-                if (rQ[cl_offset] & 0x80) {
-                    cl_header++;
-                    cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
-                    if (rQ[cl_offset + 1] & 0x80) {
-                        cl_header++;
-                        cl_data += rQ[cl_offset + 2] << 14;
-                    }
-                }
-                // end inline getTightCLength
-            }
-
-            this._FBU.bytes += cl_header + cl_data;
-            if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
-
-            // Shift ctl, filter id, num colors, palette entries, and clength off
-            this._sock.rQskipBytes(3);
-            //var palette = this._sock.rQshiftBytes(paletteSize);
-            this._sock.rQshiftTo(this._paletteBuff, paletteSize);
-            this._sock.rQskipBytes(cl_header);
-
-            if (raw) {
-                data = this._sock.rQshiftBytes(cl_data);
-            } else {
-                data = decompress(this._sock.rQshiftBytes(cl_data), rowSize * this._FBU.height);
-            }
-
-            // Convert indexed (palette based) image data to RGB
-            var rgbx;
-            if (numColors == 2) {
-                rgbx = indexedToRGBX2Color(data, this._paletteBuff, this._FBU.width, this._FBU.height);
-                this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
-            } else {
-                rgbx = indexedToRGBX(data, this._paletteBuff, this._FBU.width, this._FBU.height);
-                this._display.blitRgbxImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, rgbx, 0, false);
-            }
-
-
-            return true;
-        }.bind(this);
-
-        var handleCopy = function () {
-            var raw = false;
-            var uncompressedSize = this._FBU.width * this._FBU.height * 3;
-            if (uncompressedSize < 12) {
-                raw = true;
-                cl_header = 0;
-                cl_data = uncompressedSize;
-            } else {
-                // begin inline getTightCLength (returning two-item arrays is for peformance with GC)
-                var cl_offset = rQi + 1;
-                cl_header = 1;
-                cl_data = 0;
-                cl_data += rQ[cl_offset] & 0x7f;
-                if (rQ[cl_offset] & 0x80) {
-                    cl_header++;
-                    cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
-                    if (rQ[cl_offset + 1] & 0x80) {
-                        cl_header++;
-                        cl_data += rQ[cl_offset + 2] << 14;
-                    }
-                }
-                // end inline getTightCLength
-            }
-            this._FBU.bytes = 1 + cl_header + cl_data;
-            if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
-
-            // Shift ctl, clength off
-            this._sock.rQshiftBytes(1 + cl_header);
-
-            if (raw) {
-                data = this._sock.rQshiftBytes(cl_data);
-            } else {
-                data = decompress(this._sock.rQshiftBytes(cl_data), uncompressedSize);
-            }
-
-            this._display.blitRgbImage(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, data, 0, false);
-
-            return true;
-        }.bind(this);
-
-        var ctl = this._sock.rQpeek8();
-
-        // Keep tight reset bits
-        resetStreams = ctl & 0xF;
-
-        // Figure out filter
-        ctl = ctl >> 4;
-        streamId = ctl & 0x3;
-
-        if (ctl === 0x08)       cmode = "fill";
-        else if (ctl === 0x09)  cmode = "jpeg";
-        else if (ctl === 0x0A)  cmode = "png";
-        else if (ctl & 0x04)    cmode = "filter";
-        else if (ctl < 0x04)    cmode = "copy";
-        else return this._fail("Illegal tight compression received (ctl: " +
-                               ctl + ")");
-
-        switch (cmode) {
-            // fill use depth because TPIXELs drop the padding byte
-            case "fill":  // TPIXEL
-                this._FBU.bytes += 3;
-                break;
-            case "jpeg":  // max clength
-                this._FBU.bytes += 3;
-                break;
-            case "png":  // max clength
-                this._FBU.bytes += 3;
-                break;
-            case "filter":  // filter id + num colors if palette
-                this._FBU.bytes += 2;
-                break;
-            case "copy":
-                break;
-        }
-
-        if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
-
-        // Determine FBU.bytes
-        switch (cmode) {
-            case "fill":
-                // skip ctl byte
-                this._display.fillRect(this._FBU.x, this._FBU.y, this._FBU.width, this._FBU.height, [rQ[rQi + 3], rQ[rQi + 2], rQ[rQi + 1]], false);
-                this._sock.rQskipBytes(4);
-                break;
-            case "png":
-            case "jpeg":
-                // begin inline getTightCLength (returning two-item arrays is for peformance with GC)
-                var cl_offset = rQi + 1;
-                cl_header = 1;
-                cl_data = 0;
-                cl_data += rQ[cl_offset] & 0x7f;
-                if (rQ[cl_offset] & 0x80) {
-                    cl_header++;
-                    cl_data += (rQ[cl_offset + 1] & 0x7f) << 7;
-                    if (rQ[cl_offset + 1] & 0x80) {
-                        cl_header++;
-                        cl_data += rQ[cl_offset + 2] << 14;
-                    }
-                }
-                // end inline getTightCLength
-                this._FBU.bytes = 1 + cl_header + cl_data;  // ctl + clength size + jpeg-data
-                if (this._sock.rQwait("TIGHT " + cmode, this._FBU.bytes)) { return false; }
-
-                // We have everything, render it
-                this._sock.rQskipBytes(1 + cl_header);  // shift off clt + compact length
-                data = this._sock.rQshiftBytes(cl_data);
-                this._display.imageRect(this._FBU.x, this._FBU.y, "image/" + cmode, data);
-                break;
-            case "filter":
-                var filterId = rQ[rQi + 1];
-                if (filterId === 1) {
-                    if (!handlePalette()) { return false; }
-                } else {
-                    // Filter 0, Copy could be valid here, but servers don't send it as an explicit filter
-                    // Filter 2, Gradient is valid but not use if jpeg is enabled
-                    this._fail("Unsupported tight subencoding received " +
-                               "(filter: " + filterId + ")");
-                }
-                break;
-            case "copy":
-                if (!handleCopy()) { return false; }
-                break;
-        }
-
-
-        this._FBU.bytes = 0;
-        this._FBU.rects--;
-
-        return true;
-    },
-
-    last_rect: function () {
-        this._FBU.rects = 0;
-        return true;
-    },
-
-    ExtendedDesktopSize: function () {
-        this._FBU.bytes = 1;
-        if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; }
-
-        var firstUpdate = !this._supportsSetDesktopSize;
-        this._supportsSetDesktopSize = true;
-
-        // Normally we only apply the current resize mode after a
-        // window resize event. However there is no such trigger on the
-        // initial connect. And we don't know if the server supports
-        // resizing until we've gotten here.
-        if (firstUpdate) {
-            this._requestRemoteResize();
-        }
-
-        var number_of_screens = this._sock.rQpeek8();
-
-        this._FBU.bytes = 4 + (number_of_screens * 16);
-        if (this._sock.rQwait("ExtendedDesktopSize", this._FBU.bytes)) { return false; }
-
-        this._sock.rQskipBytes(1);  // number-of-screens
-        this._sock.rQskipBytes(3);  // padding
-
-        for (var i = 0; i < number_of_screens; i += 1) {
-            // Save the id and flags of the first screen
-            if (i === 0) {
-                this._screen_id = this._sock.rQshiftBytes(4);    // id
-                this._sock.rQskipBytes(2);                       // x-position
-                this._sock.rQskipBytes(2);                       // y-position
-                this._sock.rQskipBytes(2);                       // width
-                this._sock.rQskipBytes(2);                       // height
-                this._screen_flags = this._sock.rQshiftBytes(4); // flags
-            } else {
-                this._sock.rQskipBytes(16);
-            }
-        }
-
-        /*
-         * The x-position indicates the reason for the change:
-         *
-         *  0 - server resized on its own
-         *  1 - this client requested the resize
-         *  2 - another client requested the resize
-         */
-
-        // We need to handle errors when we requested the resize.
-        if (this._FBU.x === 1 && this._FBU.y !== 0) {
-            var msg = "";
-            // The y-position indicates the status code from the server
-            switch (this._FBU.y) {
-            case 1:
-                msg = "Resize is administratively prohibited";
-                break;
-            case 2:
-                msg = "Out of resources";
-                break;
-            case 3:
-                msg = "Invalid screen layout";
-                break;
-            default:
-                msg = "Unknown reason";
-                break;
-            }
-            Log.Warn("Server did not accept the resize request: "
-                     + msg);
-        } else {
-            this._resize(this._FBU.width, this._FBU.height);
-        }
-
-        this._FBU.bytes = 0;
-        this._FBU.rects -= 1;
-        return true;
-    },
-
-    DesktopSize: function () {
-        this._resize(this._FBU.width, this._FBU.height);
-        this._FBU.bytes = 0;
-        this._FBU.rects -= 1;
-        return true;
-    },
-
-    Cursor: function () {
-        Log.Debug(">> set_cursor");
-        var x = this._FBU.x;  // hotspot-x
-        var y = this._FBU.y;  // hotspot-y
-        var w = this._FBU.width;
-        var h = this._FBU.height;
-
-        var pixelslength = w * h * 4;
-        var masklength = Math.floor((w + 7) / 8) * h;
-
-        this._FBU.bytes = pixelslength + masklength;
-        if (this._sock.rQwait("cursor encoding", this._FBU.bytes)) { return false; }
-
-        this._display.changeCursor(this._sock.rQshiftBytes(pixelslength),
-                                   this._sock.rQshiftBytes(masklength),
-                                   x, y, w, h);
-
-        this._FBU.bytes = 0;
-        this._FBU.rects--;
-
-        Log.Debug("<< set_cursor");
-        return true;
-    },
-
-    QEMUExtendedKeyEvent: function () {
-        this._FBU.rects--;
-
-        // Old Safari doesn't support creating keyboard events
-        try {
-            var keyboardEvent = document.createEvent("keyboardEvent");
-            if (keyboardEvent.code !== undefined) {
-                this._qemuExtKeyEventSupported = true;
-            }
-        } catch (err) {
-        }
-    },
-};
Binary file image/w/core/util/browser.js.gz has changed
Binary file image/w/core/util/events.js.gz has changed
Binary file image/w/core/util/eventtarget.js.gz has changed
Binary file image/w/core/util/logging.js.gz has changed
Binary file image/w/core/util/polyfill.js.gz has changed
Binary file image/w/core/util/strings.js.gz has changed
Binary file image/w/core/websock.js.gz has changed
--- a/image/w/css/style.css	Thu May 02 11:52:36 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-
-
-body {
-    background: #ccc;
-    font-family: Verdana, Arial, sans-serif;
-    margin: 0px;
-}
-
-
-#webui_table {
-    width: 360px;
-    height: 270px;
-    background: #353536;
-    border: 2px solid;
-    border-color: #59b4d4;
-}
-
-
-#mlt_table {
-    width: 178px;
-    height: 90px;
-    margin: auto;
-    background: #303030;
-    border: 1px solid;
-    border-collapse: collapse;
-    color: white;
-    border-color: white;
-}
-
-#hlt_table {
-    width: 178px;
-    height: 90px;
-    margin: auto;
-    background: #3f3f40;
-    border: 1px solid;
-    border-collapse: collapse;
-    color: yellow;
-    border-color: yellow;
-}
-
-.appbutton {
-    width: 60px;
-    height: 36px;
-    border-radius: 4px;
-    background-color: #e7e7e7; color: black;
-}
-
-#timer {
-    color: white;
-    text-align: center;
-    font-family: "Courier New", "Lucida Console";
-    font-size: 34px;
-}
-
-/* LED */
-.LEDred {
-    margin: 5px auto;
-    width: 12px;
-    height: 12px;
-    background-color: #820;	/* On = #F40 */
-    border-radius: 50%;
-}
-
-.LEDgreen {
-    margin: 5px auto;
-    width: 12px;
-    height: 12px;
-    background-color: #270;	/* On = #5E0 */
-    border-radius: 50%;
-}
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/image/w/css/web.css	Wed May 08 15:46:50 2019 +0200
@@ -0,0 +1,86 @@
+
+body {
+  margin:0;
+  padding:0;
+  font-family: Helvetica;
+  /*Background image with light grey curve.*/
+  background-color:#494949;
+  background-repeat:no-repeat;
+  background-position:right bottom;
+  height:100%;
+/*  touch-action: none; */
+}
+
+html {
+  height:100%;
+}
+
+
+/* ----------------------------------------
+ * Main Area
+ * ----------------------------------------
+ */
+
+
+.menu {
+  width: 270px;
+  margin: auto;
+}
+
+.menu input[type=none] {
+  background-color: #0077bb;
+  border: none;
+  color: yellow;
+  font-weight: bold;
+  width: 250px;
+  padding: 10px 0px;
+  text-decoration: none;
+  font-size: 16px;
+  margin: 8px;
+  text-align: center;
+  border-radius: 10px;
+}
+
+.menu input[type=submit] {
+  background-color: #33b5e5;
+  border: none;
+  color: white;
+  font-weight: bold;
+  width: 250px;
+  padding: 15px 32px;
+  text-decoration: none;
+  font-size: 16px;
+  cursor: pointer;
+  margin: 8px;
+  text-align: center;
+  border-radius: 10px;
+}
+
+.menu input[type=submit]:hover {
+  background-color: #0099cc;
+}
+
+
+.menu ul {
+  list-style-type: none;
+  margin: 0;
+  padding: 0;
+}
+
+table.directory {
+  width:  90%;
+  border-collapse : collapse;
+  margin          : auto;
+  padding         : 0px;
+  background: yellow;
+}
+
+tr.directory:nth-child(odd) {
+  background      : #FFFFFF;
+}
+
+tr.directory:nth-child(even) {
+  background      : #CCFFFF;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/image/w/css/webui.css	Wed May 08 15:46:50 2019 +0200
@@ -0,0 +1,130 @@
+
+body {
+    background: #555;
+    font-family: Verdana, Arial, sans-serif;
+    margin: 0px;
+}
+
+#webui_win {
+    width: 360px;
+    height: 270px;
+    background: #353536;
+    border: 2px solid;
+    border-color: #59b4d4;
+}
+
+#topline {
+    width: 100%;
+    height: 24px;
+    background: blue;
+    color: yellow;
+    text-align: center;
+    font-size: 18px;
+}
+
+#mltline,
+#hltline {
+    width: 100%;
+    height: 100px;
+}
+
+#midline {
+    width: 100%;
+    height: 45px;
+}
+
+#mlt_table {
+    width: 178px;
+    height: 90px;
+    margin: auto;
+    background: #303030;
+    border: 1px solid;
+    border-collapse: collapse;
+    color: white;
+    border-color: white;
+}
+
+#hlt_table {
+    width: 178px;
+    height: 90px;
+    margin: auto;
+    background: #3f3f40;
+    border: 1px solid;
+    border-collapse: collapse;
+    color: yellow;
+    border-color: yellow;
+}
+
+#prompt {
+    width: 100%;
+    float: left;
+    text-align: center;
+}
+
+.appbutton {
+    width: 60px;
+    height: 36px;
+    border-radius: 4px;
+    background-color: #e7e7e7; color: black;
+}
+
+.okbutton {
+    width: 60px;
+    height: 36px;
+    border-radius: 4px;
+    background-color: #575757; color: white;
+    position: absolute;
+    left: 150px;
+    top: 230px;
+}
+
+.promptbutton {
+    width: 80px;
+    height: 40px;
+    border-radius: 4px;
+    background-color: #e7e7e7; color: black;
+}
+
+#timer {
+  color: white;
+  text-align: center;
+  font-family: "Courier New", "Lucida Console";
+  font-size: 34px;
+}
+
+/* LED */
+.LEDred {
+  margin: 5px auto;
+  width: 12px;
+  height: 12px;
+  background-color: #820;	/* On = #F40 */
+  border-radius: 50%;
+}
+
+.LEDgreen {
+  margin: 5px auto;
+  width: 12px;
+  height: 12px;
+  background-color: #270;	/* On = #5E0 */
+  border-radius: 50%;
+}
+
+.menu input[type=submit] {
+  background-color: #33b5e5;
+  border: none;
+  color: white;
+  font-weight: bold;
+  width: 250px;
+  padding: 15px 32px;
+  text-decoration: none;
+  font-size: 16px;
+  cursor: pointer;
+  margin: 8px;
+  text-align: center;
+  border-radius: 10px;
+}
+
+.menu input[type=submit]:hover {
+  background-color: #0099cc;
+}
+
Binary file image/w/index.html.gz has changed
Binary file image/w/js/modl/babel.js.gz has changed
Binary file image/w/js/modl/brloader.js.gz has changed
Binary file image/w/js/utils/common.js.gz has changed
--- a/image/w/js/webui.js	Thu May 02 11:52:36 2019 +0200
+++ b/image/w/js/webui.js	Wed May 08 15:46:50 2019 +0200
@@ -1,19 +1,274 @@
 document.getElementById("test").innerHTML = "WebSocket is not connected";
 
 var websocket = new WebSocket('ws://'+location.hostname+'/ws');
-var slider = document.getElementById("myRange");
 
+var Beep= new Audio( "data:audio/wav;base64,//uQRAAAAWMSLwUIYAAsYkXgoQwAEaYLWfkWgAI0wWs/ItAAAGDgYtAgAyN+QWaAAihwMWm4G8QQRDiMcCBcH3Cc+CDv/7xA4Tvh9Rz/y8QADBwMWgQAZG/ILNAARQ4GLTcDeIIIhxGOBAuD7hOfBB3/94gcJ3w+o5/5eIAIAAAVwWgQAVQ2ORaIQwEMAJiDg95G4nQL7mQVWI6GwRcfsZAcsKkJvxgxEjzFUgfHoSQ9Qq7KNwqHwuB13MA4a1q/DmBrHgPcmjiGoh//EwC5nGPEmS4RcfkVKOhJf+WOgoxJclFz3kgn//dBA+ya1GhurNn8zb//9NNutNuhz31f////9vt///z+IdAEAAAK4LQIAKobHItEIYCGAExBwe8jcToF9zIKrEdDYIuP2MgOWFSE34wYiR5iqQPj0JIeoVdlG4VD4XA67mAcNa1fhzA1jwHuTRxDUQ//iYBczjHiTJcIuPyKlHQkv/LHQUYkuSi57yQT//uggfZNajQ3Vmz+ Zt//+mm3Wm3Q576v////+32///5/EOgAAADVghQAAAAA//uQZAUAB1WI0PZugAAAAAoQwAAAEk3nRd2qAAAAACiDgAAAAAAABCqEEQRLCgwpBGMlJkIz8jKhGvj4k6jzRnqasNKIeoh5gI7BJaC1A1AoNBjJgbyApVS4IDlZgDU5WUAxEKDNmmALHzZp0Fkz1FMTmGFl1FMEyodIavcCAUHDWrKAIA4aa2oCgILEBupZgHvAhEBcZ6joQBxS76AgccrFlczBvKLC0QI2cBoCFvfTDAo7eoOQInqDPBtvrDEZBNYN5xwNwxQRfw8ZQ5wQVLvO8OYU+mHvFLlDh05Mdg7BT6YrRPpCBznMB2r//xKJjyyOh+cImr2/4doscwD6neZjuZR4AgAABYAAAABy1xcdQtxYBYYZdifkUDgzzXaXn98Z0oi9ILU5mBjFANmRwlVJ3/6jYDAmxaiDG3/6xjQQCCKkRb/6kg/wW+kSJ5//rLobkLSiKmqP/0ikJuDaSaSf/6JiLYLEYnW/+kXg1WRVJL/9EmQ1YZIsv/6Qzwy5qk7/+tEU0nkls3/zIUMPKNX/6yZLf+kFgAfgGyLFAUwY//uQZAUABcd5UiNPVXAAAApAAAAAE0VZQKw9ISAAACgAAAAAVQIygIElVrFkBS+Jhi+EAuu+lKAkYUEIsmEAEoMeDmCETMvfSHTGkF5RWH7kz/ESHWPAq/kcCRhqBtMdokPdM7vil7RG98A2sc7zO6ZvTdM7pmOUAZTnJW+NXxqmd41dqJ6mLTXxrPpnV8avaIf5SvL7pndPvPpndJR9Kuu8fePvuiuhorgWjp7Mf/PRjxcFCPDkW31srioCExivv9lcwKEaHsf/7ow2Fl1T/9RkXgEhYElAoCLFtMArxwivDJJ+bR1HTKJdlEoTELCIqgEwVGSQ+hIm0NbK8WXcTEI0UPoa2NbG4y2K00JEWbZavJXkYaqo9CRHS55FcZTjKEk3NKoCYUnSQ 0rWxrZbFKbKIhOKPZe1cJKzZSaQrIyULHDZmV5K4xySsDRKWOruanGtjLJXFEmwaIbDLX0hIPBUQPVFVkQkDoUNfSoDgQGKPekoxeGzA4DUvnn4bxzcZrtJyipKfPNy5w+9lnXwgqsiyHNeSVpemw4bWb9psYeq//uQZBoABQt4yMVxYAIAAAkQoAAAHvYpL5m6AAgAACXDAAAAD59jblTirQe9upFsmZbpMudy7Lz1X1DYsxOOSWpfPqNX2WqktK0DMvuGwlbNj44TleLPQ+Gsfb+GOWOKJoIrWb3cIMeeON6lz2umTqMXV8Mj30yWPpjoSa9ujK8SyeJP5y5mOW1D6hvLepeveEAEDo0mgCRClOEgANv3B9a6fikgUSu/DmAMATrGx7nng5p5iimPNZsfQLYB2sDLIkzRKZOHGAaUyDcpFBSLG9MCQALgAIgQs2YunOszLSAyQYPVC2YdGGeHD2dTdJk1pAHGAWDjnkcLKFymS3RQZTInzySoBwMG0QueC3gMsCEYxUqlrcxK6k1LQQcsmyYeQPdC2YfuGPASCBkcVMQQqpVJshui1tkXQJQV0OXGAZMXSOEEBRirXbVRQW7ugq7IM7rPWSZyDlM3IuNEkxzCOJ0ny2ThNkyRai1b6ev//3dzNGzNb//4uAvHT5sURcZCFcuKLhOFs8mLAAEAt4UWAAIABAAAAAB4qbHo0tIjVkUU//uQZAwABfSFz3ZqQAAAAAngwAAAE1HjMp2qAAAAACZDgAAAD5UkTE1UgZEUExqYynN1qZvqIOREEFmBcJQkwdxiFtw0qEOkGYfRDifBui9MQg4QAHAqWtAWHoCxu1Yf4VfWLPIM2mHDFsbQEVGwyqQoQcwnfHeIkNt9YnkiaS1oizycqJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7 FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb//////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=" );
 
 var BBScreen={
 
+    Screen: -1,
+    Subscreen: 0,
+    setTimer: function(v){
+	$("#timer").text('');
+	if (v == 0) {
+            $("#timer").css("font-size", "18px");
+	    $("#timer").css("font-weight", "normal");
+	    $("#timer").css("font-family", "Verdana, Arial, sans-serif");
+	} else {
+	    $("#timer").css("font-size", "36px");
+	    $("#timer").css("font-weight", "bold");
+	    $("#timer").css("font-family", "Courier New, Lucida Console");
+	}
+    },
+    clearScreen: function(){
+	$("#mltline").hide();
+	$("#mlt_table").hide();
+	$("#mlt00").hide();
+        $("#mlt20").hide();
+        $("#mlt01").hide();
+        $("#mlt21").hide();
+        $("#midline").hide();
+	this.setTimer(0);
+        $("#mid00").hide();
+        $("#mid20").hide();
+	$("#mid00").css("background-color", "#e7e7e7");
+        $("#mid00").css("color", "black");
+        $("#hltline").hide();
+	$("#hlt_table").hide();
+	$("#hlt00").hide();
+        $("#hlt20").hide();
+        $("#hlt01").hide();
+        $("#hlt21").hide();
+	$("#hlt01").css("background-color", "#e7e7e7");
+        $("#hlt01").css("color", "black");
+	$("#row_info").hide();
+        $("#prompt").hide();
+	$("#button_nee").css("background-color", "#e7e7e7");
+        $("#button_nee").css("color", "black");
+        $("#note").hide();
+	$("#brew").hide();
+    },
+    setScreen: function(s){
+	Screen = parseInt(s,10);
+	switch (Screen) {
+            case 0:	this.clearScreen();
+			$("#mltline").show();
+			$("#mlt_table").show();
+			$("#but00").text('Hand');
+			$("#but20").text('Auto');
+			$("#mlt00").show();
+                	$("#mlt20").show();
+			$("#midline").show();
+			this.setTimer(0);
+			$("#hltline").show();
+			$("#hlt_table").show();
+			$("#hlt01").show();
+			$("#but04").text('Info');
+			// No tools button on the web.
+			break;
+	    case 2:     this.clearScreen();
+                        $("#row_info").show();
+                        break;
+	    case 96:	break;	// Automaat show recipe and Stop / Start
+	    case 98:	break;	// Delay start
+	    case 99:	this.clearScreen(); // heatup
+			$("#mltline").show();
+			$("#mlt_table").show();
+			$("#midline").show();
+			$("#hltline").show();
+                        $("#hlt_table").show();
+			break;
+	    case 100:	// All handled at Subscreen
+            case 101:
+            case 102:
+            case 103:
+            case 104:
+            case 105:
+            case 106:
+            case 107:	break;
+	    case 108:	this.clearScreen();
+			$("#mltline").show();	// to boil
+			$("#mlt_table").show();
+			$("#mlt00").show();
+                        $("#mlt20").show();
+                        $("#but00").text('+sp');
+                        $("#but20").text('-sp');
+			break;
+            case 109:	this.clearScreen();
+			$("#mltline").show();	// boil
+			$("#mlt_table").show();
+			$("#mlt00").show();
+                        $("#mlt20").show();
+                        $("#but00").text('+sp');
+                        $("#but20").text('-sp');
+			$("#midline").show();
+			$("#mid00").show();
+                        $("#mid20").show();
+                        $("#but02").text('+%');
+                        $("#but22").text('-%');
+			this.setTimer(1);
+			$("#hltline").show();
+			$("#hlt01").show();
+                        $("#hlt21").show();
+                        $("#but04").text('+1m');
+                        $("#but24").text('-1m');
+			break;
+	    case 110:	// whirlpool 9
+	    case 111:	// cooling H
+	    case 112:	// whirlpool 7
+	    case 113:	// cooling M
+	    case 114:	// whirlpool 6
+	    case 115:	// cooling C
+	    case 116:	// whirlpool 2
+			break;
+	    case 117:	this.clearScreen();
+                        $("#note").show();
+			$("#note_msg").text('Brouwen is gereed.');
+			break;
+	    case 118:	this.clearScreen();
+                        $("#note").show();
+                        $("#note_msg").text('Brouwen is afgebroken.');
+			break;
+	    case 97:
+	    case 200:	this.clearScreen();
+			$("#prompt").show();
+			break;
+	    case 201:	this.clearScreen();
+			$("#mltline").show();
+			$("#but00").text('+sp');
+			$("#but20").text('-sp');
+			$("#but01").text('Pomp');
+			$("#but21").text('Aan');
+			$("#midline").show();
+			$("#hltline").show();
+			$("#but03").text('+sp');
+                        $("#but23").text('-sp');
+                        $("#but04").text('Stop');
+                        $("#but24").text('Aan');
+			$("#hlt01").show();
+			$("#hlt01").css("background-color", "#575757");
+			$("#hlt01").css("color", "white");
+			break;
+            default:    this.clearScreen();
+                        console.log("this is default screen "+Screen);
+                        break;
+	}
+    },
+    setSubscreen: function(s){
+        Subscreen = parseInt(s,10);
+        console.log("Screen:"+Screen+" Sub:"+Subscreen);
+	if (Screen == 96) {
+	    this.clearScreen();
+	    if (Subscreen == 0) {
+		$("#prompt").show();
+                $("#button_ja").text('Ja');
+                $("#button_nee").text('Nee');
+	    } else if (Subscreen == 1) {
+		$("#brew").show();
+	    }
+	} else if ((Screen >= 100) && (Screen < 108)) {
+	    this.clearScreen();
+            $("#mltline").show();
+            $("#mlt_table").show();
+	    $("#midline").show();
+            $("#hltline").show();
+	    $("#hlt_table").show();
+            switch (Subscreen) {
+		case 0:	// MASH_NONE
+		case 1:	// MASH_WAITTEMP
+                        $("#mlt00").show();
+                        $("#mlt20").show();
+			$("#but00").text('+sp');
+                        $("#but20").text('-sp');
+                        break;
+		case 2:	// MASH_REST
+			this.setTimer(1);
+			$("#mid00").show();
+                        $("#mid20").show();
+                        $("#but02").text('+1m');
+                        $("#but22").text('-1m');
+			break;
+		case 3:	// MASH_ADD
+		case 4:	// MASH_IODINE
+		case 5:	// MASH_REMOVE
+		case 6:	// MASH_INFUSE
+			this.setTimer(0);
+			$("#mid00").show();
+			$("#mid00").css("background-color", "#575757");
+                        $("#mid00").css("color", "white");
+                        $("#mid20").show();
+			$("#but02").text('Halt');
+                        $("#but22").text('Ok');
+			break;
+	    };
+	} else if ((Screen == 111) || (Screen == 113) || (Screen == 115)) { // cooling H,M,C
+	    this.clearScreen();
+	    if (Subscreen == 0) {
+		$("#prompt").show();
+		$("#button_ja").text('Start');
+                $("#button_nee").text('Stop');
+		$("#button_nee").css("background-color", "#575757");
+                $("#button_nee").css("color", "white");
+	    } else if (Subscreen == 1) {
+		$("#mltline").show();
+                $("#mlt_table").show();
+                $("#mlt00").show();
+                $("#mlt20").show();
+                $("#but00").text('+1');
+                $("#but20").text('-1');
+                $("#hltline").show();
+		$("#hlt01").show();
+                $("#but04").text('Stop');
+		$("#hlt01").css("background-color", "#575757");
+                $("#hlt01").css("color", "white");
+	    }
+	} else if ((Screen == 110) || (Screen == 112) || (Screen == 114) || (Screen == 116)) { // whirlpools
+	    this.clearScreen();
+            if (Subscreen == 0) {
+        	$("#prompt").show();
+                $("#button_ja").text('Start');
+                $("#button_nee").text('Stop');
+		$("#button_nee").css("background-color", "#575757");
+                $("#button_nee").css("color", "white");
+	    } else if (Subscreen == 1) {
+		$("#mltline").show();
+                $("#mlt_table").show();
+		$("#midline").show();
+		this.setTimer(1);
+                $("#mid00").show();
+                $("#mid20").show();
+                $("#but02").text('-1m');
+                $("#but22").text('+1m');
+		$("#hltline").show();
+                $("#hlt21").show();
+                $("#but24").text('Pomp');
+            }
+	};
+    },
     MLT_pv: function(s) {
 	$("#mlt_pv").text(s);
     },
     MLT_sp: function(s) {
 	$("#mlt_sp").text(s);
+	if (Screen == 201) {
+	    if (s != "") {
+		$("#mlt00").show();
+                $("#mlt20").show();
+		$("#mlt01").show();
+                $("#mlt21").show();
+		$("#mlt_table").show();
+	    }
+	}
     },
     MLT_power: function(s) {
 	$("#mlt_power").text(s);
+	if (Screen == 201) {
+	    if (s != "") {
+		$("#but21").text('Uit');
+	    } else {
+		$("#but21").text('Aan');
+	    }
+	}
     },
     MLT_led: function(s) {
 	if (s == 0)
@@ -32,9 +287,24 @@
     },
     HLT_sp: function(s) {
 	$("#hlt_sp").text(s);
+	if (Screen == 201) {
+            if (s != "") {
+                $("#hlt00").show();
+                $("#hlt20").show();
+                $("#hlt21").show();
+		$("#hlt_table").show();
+            }
+	}
     },
     HLT_power: function(s) {
 	$("#hlt_power").text(s);
+	if (Screen == 201) {
+            if (s != "") {
+                $("#but24").text('Uit');
+            } else {
+                $("#but24").text('Aan');
+            }
+        }
     },
     HLT_led: function(s) {
 	if (s == 0)
@@ -48,6 +318,20 @@
     Timer: function(s) {
 	$("#timer").text(s);
     },
+    Brew1: function(s) {
+	$("#brew_msg1").text(s);
+    },
+    Brew2: function(s) {
+        $("#brew_msg2").text(s);
+    },
+    Beep: function(s) {
+	var loop = parseInt(s,10);
+	Beep.pause();
+	Beep.loop = false;
+	for (i = 0; i < loop; i++) {
+	    Beep.play();
+	}
+    },
 };
 
 var BrewBoard = {
@@ -56,6 +340,12 @@
 	var b=this;
 	var a=JSON.parse(e);
 	var c={
+	    main: function(v){
+		BBScreen.setScreen(v)
+	    },
+	    sub: function(v){
+                BBScreen.setSubscreen(v)
+            },
 	    mlt_pv:function(v){
 		BBScreen.MLT_pv(v)
 	    },
@@ -89,8 +379,16 @@
 	    timer:function(v){
 		BBScreen.Timer(v)
 	    },
+	    beep:function(v){
+                BBScreen.Beep(v)
+            },
+	    brew1:function(v){
+		BBScreen.Brew1(v)
+	    },
+	    brew2:function(v){
+                BBScreen.Brew2(v)
+            },
 	};
-	console.log(e);
 	$.each(a,function(k,v){
 	    if (typeof(c[k])!="undefined"){
 		c[k](v)
@@ -100,17 +398,32 @@
 };
 
 
-function sendMsg() {
-	//websocket.send("sup playa!");
-	websocket.send('L50');
-	console.log('Sent message to websocket');
+function sendTouch(x, y) {
+    websocket.send('{"touch":{"x":'+x+',"y":'+y+'}}');
 }
 
 
+/* Define keys in the screens and their actions. */
+$("#ok_info").click( function() { sendTouch(160,220); });
+$("#ok_note").click( function() { sendTouch(160,220); });
+$("#mlt00").click( function()   { sendTouch( 35, 46); });
+$("#mlt20").click( function()   { sendTouch(285, 46); });
+$("#mlt01").click( function()   { sendTouch( 35, 96); });
+$("#mlt21").click( function()   { sendTouch(285, 96); });
+$("#mid00").click( function()   { sendTouch( 35,140); });
+$("#mid20").click( function()   { sendTouch(285,140); });
+$("#hlt00").click( function()   { sendTouch( 35,170); });
+$("#hlt20").click( function()   { sendTouch(285,170); });
+$("#hlt01").click( function()   { sendTouch( 35,220); });
+$("#hlt21").click( function()   { sendTouch(285,220); });
+$("#button_ja").click( function()  { sendTouch( 80,120); });
+$("#button_nee").click( function() { sendTouch(240,120); });
+$("#button_stop").click( function()  { sendTouch( 35,220); });
+$("#button_start").click( function() { sendTouch(285,220); });
+
 websocket.onopen = function(evt) {
-	console.log('WebSocket connection opened');
-//	websocket.send("It's open! Hooray!!!");
-	document.getElementById("test").innerHTML = "WebSocket is connected!";
+  console.log('WebSocket connection opened');
+  document.getElementById("test").innerHTML = "";
 }
 
 /*
Binary file image/w/js/zlib/adler32.js.gz has changed
Binary file image/w/js/zlib/constants.js.gz has changed
Binary file image/w/js/zlib/crc32.js.gz has changed
Binary file image/w/js/zlib/deflate.js.gz has changed
Binary file image/w/js/zlib/gzheader.js.gz has changed
Binary file image/w/js/zlib/inffast.js.gz has changed
Binary file image/w/js/zlib/inflate.js.gz has changed
Binary file image/w/js/zlib/inftrees.js.gz has changed
Binary file image/w/js/zlib/messages.js.gz has changed
Binary file image/w/js/zlib/trees.js.gz has changed
Binary file image/w/js/zlib/zstream.js.gz has changed
--- a/image/w/logs.html	Thu May 02 11:52:36 2019 +0200
+++ b/image/w/logs.html	Wed May 08 15:46:50 2019 +0200
@@ -6,7 +6,7 @@
   <meta http-equiv="X-UA-Compatible" content="IE=edge" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 
   <script src="js/jquery-1.12.4.min.js"></script>
-  <link rel="stylesheet" href="app/styles/web.css">
+  <link rel="stylesheet" href="css/web.css">
 </head>
 <body>
 
@@ -27,7 +27,9 @@
 
 
  <br>
- <form action="index.html"><input type="submit" class="button" value="Hoofdmenu"></form>
+ <div class="menu">
+  <form action="index.html"><input type="submit" class="button" value="Hoofdmenu"></form>
+ </div>
 
  <script>
 
Binary file image/w/vnc.html.gz has changed
--- a/image/w/webui.html	Thu May 02 11:52:36 2019 +0200
+++ b/image/w/webui.html	Wed May 08 15:46:50 2019 +0200
@@ -4,76 +4,151 @@
   <title>Web User Interface</title>
   <meta charset="utf-8" />
   <meta http-equiv="X-UA-Compatible" content="IE=edge" />
-  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=2.5" /> 
   <script src="js/jquery-1.12.4.min.js"></script>
-  <link rel="stylesheet" href="css/style.css">
+  <link rel="stylesheet" href="css/webui.css">
 </head>
 <body>
 
- <div id="webui_table">
-  <table style='width: 100%; padding: 0px;'>
-   <tr style="color: yellow; background-color: blue; height: 26px;">
-    <th colspan="3"><span id="top_msg">top_msg</span></th>
-   </tr>
-   <tr>
-    <td style="width: 20%;">
-     <button style="float: left; margin-left: 5px;" type="button" class="appbutton">Hand</button>
-     <button style="float: left; margin-left: 5px; margin-top: 12px;" type="button" class="appbutton">+sp</button>
-    </td>
-    <td style="width: 60%;">
-     <table id="mlt_table">
-      <tr>
-       <td style="width: 10%; text-align: center;">
-	<div id="pump_led" class="LEDred"></div>
-       </td>
-       <td colspan="2" style='font-size: 10px; text-align: center;'>MLT</td>
-       <td style="width: 10%; text-align: center;">
-	<div  id="mlt_led" class="LEDgreen"></div>
-       </td>
-      </tr>
-      <tr><td colspan="4" style='border: 1px solid; font-size: 40px; text-align: right;'><span id="mlt_pv">---</span></td></tr>
-      <tr><td colspan="2" style='width: 50%; font-size: 10px;'><span id="mlt_sp">44.00</span></td>
-	  <td colspan="2" style='width: 50%; font-size: 10px;'><span id="mlt_power">100%</span></td></tr>
+ <div id="webui_win">
+  <div id="topline"><span id="top_msg">top_msg</span></th>
+  </div>
+
+  <div id="mltline">
+   <table style='width: 100%; padding: 0px;'>
+    <col width="20%"><col width="60%"><col width="20%">
+    <tr style="height: 50%;">
+     <td style="margin-top: 5px;">
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mlt00"><span id="but00">00</span></button>
+     </td>
+     <td rowspan="2">
+      <table id="mlt_table">
+       <tr>
+        <td style="width: 10%; text-align: center;"><div id="pump_led" class="LEDred"></div></td>
+        <td colspan="2" style='font-size: 10px; text-align: center;'>MLT</td>
+        <td style="width: 10%; text-align: center;"><div  id="mlt_led" class="LEDgreen"></div></td>
+       </tr>
+       <tr>
+        <td colspan="4" style='border: 1px solid; font-size: 40px; text-align: right;'><span id="mlt_pv">---</span></td>
+       </tr>
+       <tr>
+        <td colspan="2" style='width: 50%; font-size: 10px;'><span id="mlt_sp">44.00</span></td>
+        <td colspan="2" style='width: 50%; font-size: 10px;'><span id="mlt_power">100%</span></td>
+       </tr>
      </table>
-    </td>
-    <td style="width: 20%;">
-     <button style="float: left; margin-left: 5px;" type="button" class="appbutton">Auto</button>
-     <button style="float: left; margin-left: 5px; margin-top: 12px;" type="button" class="appbutton">-sp</button>
-    </td>
-   </tr>
-   <tr>
-    <td><button style="float: left; margin-left: 5px;" type="button" class="appbutton">+1m</button></td>
-    <td><div id="timer">01:23:45</div></td>
-    <td><button style="float: left; margin-left: 5px;" type="button" class="appbutton">-1m</button></td>
-   </tr>
-   <tr>
-    <td><button style="float: left; margin-left: 5px;" type="button" class="appbutton">+sp</button>
-	<button style="float: left; margin-left: 5px; margin-top: 12px;" type="button" class="appbutton">Info</button></td>
-    <td>
-     <table id="hlt_table">
-      <tr>
-       <td style="width: 10%; text-align: center;">
-       </td>
-       <td colspan="2" style='font-size: 10px; text-align: center;'>HLT</td>
-       <td style="width: 10%; text-align: center;">
-        <div id="hlt_led" class="LEDgreen"></div>
-       </td>
-      </tr>
-      <tr><td colspan="4" style='border: 1px solid; font-size: 40px; text-align: right;'><span id="hlt_pv">---</span></td></tr>
-      <tr><td colspan="2" style='font-size: 10px;'><span id="hlt_sp">44.00</span></td>
-          <td colspan="2" style='font-size: 10px;'><span id="hlt_power">100%</span></td></tr>
-     </table>
-    </td>
-    <td><button style="float: left; margin-left: 5px;" type="button" class="appbutton">-sp</button>
-	<button style="float: left; margin-left: 5px; margin-top: 12px;" type="button" class="appbutton">Tools</button></td>
-   </tr>
-  </table>
+     </td>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mlt20"><span id="but20">20</span></button>
+     </td>
+    </tr>
+    <tr>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mlt01"><span id="but01">01</span></button>
+     </td>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mlt21"><span id="but21">21</span></button>
+     </td>
+    </tr>
+   </table>
+  </div>
+
+  <div id="midline">
+   <table style='width: 100%; padding: 0px;'>
+    <col width="20%"><col width="60%"><col width="20%">
+    <tr>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mid00"><span id="but02">02</span></button>
+     </td>
+     <td>
+      <div id="timer">01:23:45</div>
+     </td>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="mid20"><span id="but22">22</span></button>
+     </td>
+    </tr>
+   </table>
+  </div>
+
+  <div id="hltline" style="margin-bottom: 0;">
+   <table style='width: 100%; padding: 0px;'>
+    <col width="20%"><col width="60%"><col width="20%">
+    <tr>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="hlt00"><span id="but03">03</span></button>
+     </td>
+     <td rowspan="2">
+      <table id="hlt_table">
+       <tr>
+        <td style="width: 10%; text-align: center;"> </td>
+        <td colspan="2" style='font-size: 10px; text-align: center;'>HLT</td>
+        <td style="width: 10%; text-align: center;"><div id="hlt_led" class="LEDgreen"></div></td>
+       </tr>
+       <tr>
+        <td colspan="4" style='border: 1px solid; font-size: 40px; text-align: right;'><span id="hlt_pv">---</span></td>
+       </tr>
+       <tr>
+        <td colspan="2" style='font-size: 10px;'><span id="hlt_sp">44.00</span></td>
+        <td colspan="2" style='font-size: 10px;'><span id="hlt_power">100%</span></td>
+       </tr>
+      </table>
+     </td>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="hlt20"><span id="but23">23</span></button>
+     </td>
+    </tr>
+    <tr style="height: 50%;">
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="hlt01"><span id="but04">04</span></button>
+     </td>
+     <td>
+      <button style="float: left; margin-left: 5px;" type="button" class="appbutton" id="hlt21"><span id="but24">24</span></button>
+     </td>
+    </tr>
+   </table>
+  </div>
+
+  <div id="row_info">
+   <div style="color: yellow; text-align: center;">
+    <p />Written by Michiel Broek &copy; 2018
+   </div>
+   <div style="color: orange; text-align: center;">
+    <p />Parts are written by Chris Morgan, Brett Beauregard, Blake Felt, LoBo and David Antliff.
+   </div>
+   <div>
+    <button type="button" class="okbutton" id="ok_info">Ok</button>
+   </div>
+  </div>
+
+  <div id="prompt">
+   <button style="margin-top: 100px;" type="button" class="promptbutton" id="button_ja">Ja</button>
+   <button style="margin-left: 80px; margin-top: 100px;" type="button" class="promptbutton" id="button_nee">Nee</button>
+  </div>
+
+  <div id="note">
+   <div style="color: yellow; text-align: center; margin-top: 105px;"><span id="note_msg">nm</span></div>
+   <div>
+    <button type="button" class="okbutton" id="ok_note">Ok</button>
+   </div>
+  </div>
+
+  <div id="brew">
+   <div style="color: yellow; margin-top: 20px;">Installatie: <span id="brew_msg1"></span></div>
+   <div style="color: yellow;">Recept: <span id="brew_msg2"></span></div>
+   <div style="color: white; margin-top: 20px;">Zie het display voor de details.</span></div>
+   <div>
+    <button style="position: absolute; left: 5px; top: 230px;" type="button" class="appbutton" id="button_stop">Stop</button>
+    <button style="position: absolute; left: 295px; top: 230px;" type="button" class="appbutton" id="button_start">Start</button>
+   </div>
+  </div>
+
+ </div> <!-- webui_win -->
+
+ <br>
+ <div class="menu" style="margin-left: 45px;">
+  <form action="index.html"><input type="submit" class="button" value="Hoofdmenu"></form>
  </div>
 
- <br>
- <form action="index.html"><input type="submit" class="button" value="Hoofdmenu"></form>
-
-<p id="test"></p>
+<p id="test"></p><p id="output"></p>
 
 <script type="text/javascript" src="js/webui.js"></script>
 
--- a/main/automation.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/automation.c	Wed May 08 15:46:50 2019 +0200
@@ -40,6 +40,7 @@
 extern bool			System_TimeOk;			///< System time is valid
 extern sButton			Buttons[MAXBUTTONS];		///< Buttons definitions
 extern int			Main_Screen;			///< Current screen
+extern int			Sub_Screen;			///< Sub screen during mash
 extern DS18B20_State            *ds18b20_state;			///< DS18B20 state
 extern DRIVER_State             *driver_state;			///< Relays driver state
 extern SemaphoreHandle_t        xSemaphoreDS18B20;		///< DS18B20 lock semaphore
@@ -64,8 +65,10 @@
  */
 bool Automation_Init(void)
 {
+    char	msg[64];
+
     switch (Main_Screen) {
-	case MAIN_AUTO_INIT:
+	case MAIN_AUTO_INIT1:
 #ifdef CONFIG_TEMP_SENSORS_SIMULATOR
 		Fake_MLT = recipe.MashStep[0].Temperature - 10;
 		Fake_HLT = recipe.SpargeTemp - 15;
@@ -136,7 +139,7 @@
                 runtime.UseHLT = _UseHLT = false;
 		runtime.TimeBrewing = 0;
                 TimeBrewing = 0;
-		runtime.StageResume = MAIN_AUTO_INIT;
+		runtime.StageResume = MAIN_AUTO_INIT1;
 		runtime.StageTimeLeft = 0;
 		runtime.HopAddition = 0;
 		runtime.Logfile[0] = '\0';
@@ -147,6 +150,7 @@
 		vTaskDelay(250 / portTICK_PERIOD_MS);	// Allow some time
                 break;
 
+	case MAIN_AUTO_INIT2:
 	case MAIN_AUTO_DELAYSTART:
 		break;
 
@@ -196,7 +200,9 @@
                         MaxMash = 75.0;
                     }
                 }
-                MashState = MASH_NONE;
+                MashState = Sub_Screen = MASH_NONE;
+		snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+		ws_server_send_text_clients("/ws", msg, strlen(msg));
                 pumpTime = 0;
                 pumpRest = false;
 		runtime.StageResume = Main_Screen;
@@ -227,13 +233,14 @@
                 Buttons_Add(255,  30, 60, 40, "-sp",  1);
                 Buttons_Show();
                 ESP_LOGI(TAG, "Mash done, going to boil.");
+		Sub_Screen = 0;
                 break;
 
 	case MAIN_AUTO_BOILING:
                 if (Resume) {
                     TimeLeft = runtime.StageTimeLeft * 60;
                 } else {
-                    // +1 minute for flameout and 2 seconds for a smooth transition.
+                    // +1 minute for flameout and for a smooth transition.
                     runtime.StageTimeLeft = TimeLeft = (recipe.BoilTime * 60) + 60;
                     runtime.StageResume = Main_Screen;
                     runtime.HopAddition = 0;
@@ -257,6 +264,7 @@
                 Buttons_Show();
                 ESP_LOGI(TAG, "Boil temperature reached, boil %d minutes", (TimeLeft / 60) -1);
 		log_annotation(ANNOTATION_STAGE, "Koken");
+		Sub_Screen = 0;
                 break;
 
 	case MAIN_AUTO_COOLING_H:
@@ -285,6 +293,7 @@
 		_Prompt = true;
                 break;
 
+	case MAIN_AUTO_WHIRLPOOL9:
 	case MAIN_AUTO_WHIRLPOOL7:
 	case MAIN_AUTO_WHIRLPOOL6:
 	case MAIN_AUTO_WHIRLPOOL2:
@@ -373,16 +382,20 @@
 bool Automation_Loop(void)
 {
     static bool beeped = false;
-    char	tmp[32];
+    char	tmp[32], msg[256];
     uint16_t	y;
 
     switch (Main_Screen) {
 
-	case MAIN_AUTO_INIT:
+	case MAIN_AUTO_INIT1:
 		/*
 		 * Present selected equipment and recipe.
 		 */
+		Sub_Screen = 1;
 		read_recipe(config.RecipeRec);
+		snprintf(msg, 255, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\",\"brew1\":\"%s\",\"brew2\":\"%s\"}", 
+			Main_Screen, Sub_Screen, equipment.Name, recipe.Name);
+		ws_server_send_text_clients("/ws", msg, strlen(msg));
 		y = 28;
 		TopMessage("Automaat");
 		TFT_setFont(DEFAULT_FONT, NULL);
@@ -462,15 +475,17 @@
 					break;
 
 			case 1:         loop = false;
+					Main_Screen = MAIN_AUTO_INIT2;
 					break;
 
 			default:        break;
 		    }
 		    vTaskDelay(20 / portTICK_PERIOD_MS);
 		}
-		if (Main_Screen == MAIN_AUTO_ABORT)
-		    break;
+		Buttons_Clear();
+		break;
 
+	case MAIN_AUTO_INIT2:
                 _UseHLT = false;
 		_bg = TFT_BLACK;
 		TFT_fillScreen(_bg);
@@ -598,7 +613,9 @@
                         driver_state->mlt_mode = MLT_MODE_PID;
                         xSemaphoreGive(xSemaphoreDriver);
                     }
-                    MashState = MASH_WAITTEMP;
+                    MashState = Sub_Screen = MASH_WAITTEMP;
+		    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+                    ws_server_send_text_clients("/ws", msg, strlen(msg));
                     ESP_LOGI(TAG, "Mash step %d type: %s time: %d temp: %4.1f  min: %4.1f max: %4.1f",
 				    Main_Screen - MAIN_AUTO_MASH_IN, mashTypes[recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Type],
                                     stageTime, stageTemp, MinMash, MaxMash);
@@ -632,7 +649,9 @@
 					recipe.MashStep[Main_Screen - MAIN_AUTO_MASH_IN].Infusion_temp);
 			TFT_print(temp_buf, CENTER, 135);
 			SoundPlay(SOUND_Prompt);
-			MashState = MASH_INFUSE;
+			MashState = Sub_Screen = MASH_INFUSE;
+			snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"%s\"}", Main_Screen, Sub_Screen, temp_buf);
+                	ws_server_send_text_clients("/ws", msg, strlen(msg));
 			if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
 			    // No heating during the infusion.
 			    driver_state->mlt_sp = stageTemp;
@@ -654,7 +673,9 @@
                     if ((temp_MLT >= stageTemp) && (Steady > 10)) {
                         SoundPlay(SOUND_TempReached);
                         TempReached = true;
-                        MashState = MASH_REST;
+                        MashState = Sub_Screen = MASH_REST;
+			snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+                	ws_server_send_text_clients("/ws", msg, strlen(msg));
                         if (Main_Screen == MAIN_AUTO_MASH_IN) {
                             TimerSet(0);
                         } else {
@@ -756,7 +777,9 @@
                             TFT_setFont(DEJAVU24_FONT, NULL);
                             TFT_print("Mout storten?", CENTER, 135);
                             SoundPlay(SOUND_Prompt);
-			    MashState = MASH_ADD;
+			    MashState = Sub_Screen = MASH_ADD;
+			    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout storten?\"}", Main_Screen, Sub_Screen);
+                	    ws_server_send_text_clients("/ws", msg, strlen(msg));
 			    ESP_LOGI(TAG, "Mash add prompt");
 			    break;
                         }
@@ -778,7 +801,9 @@
                             SoundPlay(SOUND_Prompt);
                             beeped = false;
                             TimerSet(config.IodineTime * 60);
-			    MashState = MASH_IODINE;
+			    MashState = Sub_Screen = MASH_IODINE;
+			    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Jodium test?\"}", Main_Screen, Sub_Screen);
+                	    ws_server_send_text_clients("/ws", msg, strlen(msg));
 			    ESP_LOGI(TAG, "Mash iodine test prompt");
 			    break;
                         }
@@ -798,7 +823,9 @@
                             TFT_setFont(DEJAVU18_FONT, NULL);
                             TFT_print("Mout verwijderen?", CENTER, 135);
                             SoundPlay(SOUND_Prompt);
-			    MashState = MASH_REMOVE;
+			    MashState = Sub_Screen = MASH_REMOVE;
+			    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"Mout verwijderen?\"}", Main_Screen, Sub_Screen);
+                	    ws_server_send_text_clients("/ws", msg, strlen(msg));
 			    ESP_LOGI(TAG, "Mash remove prompt");
 			    break;
                         }
@@ -851,7 +878,9 @@
 		    switch (Buttons_Scan()) {
 			case 0:     Main_Screen = MAIN_AUTO_ABORT;
 				    break;
-			case 1:	    MashState = MASH_WAITTEMP;
+			case 1:	    MashState = Sub_Screen = MASH_WAITTEMP;
+				    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+                		    ws_server_send_text_clients("/ws", msg, strlen(msg));
 				    if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
 					// Start PID again.
 					driver_state->mlt_sp = stageTemp;
@@ -1018,6 +1047,7 @@
 			 */
 			Buttons_Clear();
 			TFT_fillScreen(_bg);
+			Sub_Screen = 1;
 			if (Main_Screen == MAIN_AUTO_COOLING_H) {
 			    stageTemp = 77.0;
 			} else if (Main_Screen == MAIN_AUTO_COOLING_M) {
@@ -1025,6 +1055,8 @@
 			} else {
 			    stageTemp = recipe.CoolTemp;
 			}
+			snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+                        ws_server_send_text_clients("/ws", msg, strlen(msg));
 			CoolBeep = false;
 			ESP_LOGI(TAG, "Start cooling from %6.2f to %4.1f", ds18b20_state->mlt_temperature, stageTemp);
 			if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
@@ -1146,6 +1178,7 @@
                     	if (driver_state->mlt_pv <= driver_state->mlt_sp) {
                             SoundPlay(SOUND_TempReached);
                             Main_Screen++;
+			    Sub_Screen = 0;
                     	}
                     	xSemaphoreGive(xSemaphoreDriver);
                     }
@@ -1179,6 +1212,9 @@
 			 */
 			Buttons_Clear();
 			TFT_fillScreen(_bg);
+			Sub_Screen = 1;
+                        snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
+                        ws_server_send_text_clients("/ws", msg, strlen(msg));
 			if (Main_Screen == MAIN_AUTO_WHIRLPOOL9) {
 			    TimeWhirlPool = recipe.Whirlpool9;
 			    if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) {
@@ -1227,7 +1263,7 @@
 			ESP_LOGI(TAG, "Whirlpool %d minutes, sp %4.1f", TimeWhirlPool, driver_state->mlt_sp);
 			Buttons_Add(255, 120, 60, 40, "+1m", 0);
 			Buttons_Add(  5, 120, 60, 40, "-1m", 1);
-			Buttons_Add(130, 200, 60, 40, "Pomp",  2);
+			Buttons_Add(255, 200, 60, 40, "Pomp",  2);
 			Buttons_Show();
 		    }
 		} else {
--- a/main/brewboard.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/brewboard.c	Wed May 08 15:46:50 2019 +0200
@@ -21,8 +21,9 @@
 
 int 				Main_Screen = MAIN_MODE_UNKNOWN;	///< Screen number
 int				Old_Screen = MAIN_MODE_UNKNOWN;		///< Previous screen number
+int				Sub_Screen = 0;				///< Subscreen during mash
 bool				System_TimeOk = false;			///< System time status
-
+const esp_app_desc_t		*app_desc = NULL;
 
 
 void app_main()
@@ -36,7 +37,8 @@
     TFT_setFont(DEJAVU24_FONT, NULL);
     _fg = TFT_YELLOW;
     tempy = TFT_getfontheight() + 4;
-    sprintf(temp, "BrewBoard %s", VERSION);
+    app_desc = esp_ota_get_app_description();
+    sprintf(temp, "BrewBoard %s", app_desc->version);
     TFT_print(temp, CENTER, 4);
 
     TFT_setFont(DEJAVU18_FONT, NULL);
@@ -148,7 +150,7 @@
     SoundPlay(SOUND_StartUp);
 
     /* Do not write to the TFT during VNC startup to avoid race conditions */
-    VncStartup();
+//    VncStartup();
     start_http_websocket();
     vTaskDelay(1000 / portTICK_PERIOD_MS);
     Main_Screen = MAIN_MODE_FREE;
--- a/main/buttons.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/buttons.c	Wed May 08 15:46:50 2019 +0200
@@ -9,13 +9,12 @@
 sButton				Buttons[MAXBUTTONS];	///< 40 buttons on a screen.
 int				level = 1;		///< Keyboard level.
 
-extern uint8_t			VNC_pointer_button;	///< Mouse buttons mask
-extern uint16_t			VNC_pointer_x;		///< Mouse coordinate X
-extern uint16_t			VNC_pointer_y;		///< Mouse coordinate Y
-
 const char 			*mashTypes[] = { "Infusion", "Temperature", "Decoction" };
 const char			*SSR2Types[] = { "Uit", "HLT of MLT", "HLT en MLT", "Idle" };
 
+uint8_t				WS_pressed = 0;		///< Websocket button received
+uint16_t			WS_pointer_x = 0;	///< Websocket coordinate x
+uint16_t			WS_pointer_y = 0;	///< Websocket coordinate y
 
 #define	EDIT_TYPE_TEXT		0			///< Editor type is text
 #define	EDIT_TYPE_INT		1			///< Editor type is integer
@@ -138,11 +137,12 @@
 	return rc;
     }
 
-    if (VNC_pointer_button & 0x07) {
+    if (WS_pressed) {
 	v_pressed = true;
-	vx = VNC_pointer_x;
-	vy = VNC_pointer_y;
-	return -1;
+        vx = WS_pointer_x;
+        vy = WS_pointer_y;
+	WS_pressed = 0;
+        return -1;
     } else if (v_pressed) {
 	rc = Buttons_Search(vx, vy);
 	v_pressed = false;
@@ -155,6 +155,15 @@
 
 
 
+void WS_touched(int x, int y)
+{
+    WS_pointer_x = x;
+    WS_pointer_y = y;
+    WS_pressed = 1;
+}
+
+
+
 static const uint8_t alphalow_tab[] = { 'q','w','e','r','t','y','u','i','o','p',
 					'a','s','d','f','g','h','j','k','l',
 					'z','x','c','v','b','n','m' };
--- a/main/buttons.h	Thu May 02 11:52:36 2019 +0200
+++ b/main/buttons.h	Wed May 08 15:46:50 2019 +0200
@@ -68,6 +68,13 @@
 int Buttons_Scan(void);
 
 /**
+ * @brief Insert button coordinates received from a websocket.
+ * @param x The touched X position.
+ * @param y The touched Y position.
+ */
+void WS_touched(int x, int y);
+
+/**
  * @brief Scan keyboard, all characters, 4 screens.
  * @return The ASCII code of the key, or -1 if no key is pressed.
  */
--- a/main/config.h	Thu May 02 11:52:36 2019 +0200
+++ b/main/config.h	Wed May 08 15:46:50 2019 +0200
@@ -59,7 +59,6 @@
 #include "tftspi.h"
 #include "tft.h"
 #include "PID_v1.h"
-#include "vnc-server.h"
 #include "websocket_server.h"
 
 #include "buttons.h"
@@ -80,9 +79,6 @@
 #include "task_http.h"
 
 
-#define	VERSION		"0.2.10"	///< Application version
-
-
 
 /**
  * @brief Main mode different screens
@@ -111,7 +107,8 @@
     MAIN_TOOLS_FILES_RESTORE,		///< Main files restore.
     MAIN_TOOLS_FILES_BACKUP,		///< Main files backup.
     MAIN_TOOLS_UPDATES,			///< Main Updates.
-    MAIN_AUTO_INIT,			///< Automatic start
+    MAIN_AUTO_INIT1 = 96,		///< Automatic start part 1
+    MAIN_AUTO_INIT2,			///< Automatic start part 2
     MAIN_AUTO_DELAYSTART,		///< Delayed start
     MAIN_AUTO_HEATUP,			///< Heatup the system
     MAIN_AUTO_MASH_IN = 100,		///< Mash-in
--- a/main/task_http.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/task_http.c	Wed May 08 15:46:50 2019 +0200
@@ -6,6 +6,7 @@
 #include "config.h"
 #include "mbedtls/base64.h"
 #include "mbedtls/sha1.h"
+#include "cJSON.h"
 
 
 static const char		*TAG = "task_http";
@@ -14,6 +15,8 @@
 static TaskHandle_t             xTaskHTTP  = NULL;
 static TaskHandle_t             xTaskQueue = NULL;
 
+cJSON				*root = NULL;
+cJSON				*touch = NULL;
 
 
 /**
@@ -21,8 +24,9 @@
  * @param buf The buffer
  * @param buflen Length of the buffer
  */
+#if 0
 void dump_buf(char *buf, uint16_t buflen);
-
+#endif
 
 
 /**
@@ -210,41 +214,12 @@
 
 
 /**
- * @brief Handle VNC websocket events.
- */
-void websockify_callback(uint8_t num, WEBSOCKET_TYPE_t type, char* msg, uint64_t len)
-{
-    switch(type) {
-	case WEBSOCKET_DISCONNECT_EXTERNAL:
-			VncStopWS(num);
-			break;
-
-	case WEBSOCKET_DISCONNECT_INTERNAL:
-			ESP_LOGI(TAG,"Websockify client %i was disconnected",num);
-			VncStopWS(num);
-			break;
-
-	case WEBSOCKET_DISCONNECT_ERROR:
-			ESP_LOGI(TAG,"Websockify client %i was disconnected due to an error",num);
-			VncStopWS(num);
-			break;
-	
-	case WEBSOCKET_BIN:
-			VncGetWSmessage(msg, len);
-			//dump_buf(msg, len);	
-			break;
-
-	default:	break;
-    }
-}
-
-
-
-/**
  * @brief Handle web ui websocket events.
  */
 void websock_callback(uint8_t num, WEBSOCKET_TYPE_t type, char* msg, uint64_t len)
 {
+    char	jbuf[128];
+
     switch(type) {
 	case WEBSOCKET_CONNECT:
 			ESP_LOGI(TAG,"Websocket client %i connected!",num);
@@ -263,13 +238,32 @@
 			break;
 
 	case WEBSOCKET_TEXT:
+			/*
+			 * Handle json actions from the web clients, like button presses.
+			 */
+			if (len < 128) { // Safety, messages are small.
+			    memcpy(jbuf, msg, len);
+                            jbuf[len] = '\0';
+			    if ((root = cJSON_Parse(jbuf))) {
+				if ((touch = cJSON_GetObjectItem(root,"touch"))) {
+				    int x = cJSON_GetObjectItem(touch, "x")->valueint;
+				    int y = cJSON_GetObjectItem(touch, "y")->valueint;
+				    WS_touched(x, y);
+				    break;
+				} else {
+				    ESP_LOGI(TAG,"not json touch");
+				}
+				cJSON_Delete(root);
+			    } else {
+				ESP_LOGI(TAG,"not json");
+			    }
+			}
+			// Log if the message in not processed.
 			ESP_LOGI(TAG,"Websocket client %i sent text message of size %i:\n%s",num,(uint32_t)len,msg);
-			dump_buf(msg, len);
 			break;
 
 	case WEBSOCKET_BIN:
 			ESP_LOGI(TAG,"Websocket client %i sent bin message of size %i:\n",num,(uint32_t)len);
-			dump_buf(msg, len);
 			break;
 
 	case WEBSOCKET_PING:
@@ -284,6 +278,7 @@
 
 
 
+#if 0
 void dump_buf(char *buf, uint16_t buflen)
 {
     int i = 0, l = 1;
@@ -308,6 +303,7 @@
     }
     printf("\n");
 }
+#endif
 
 
 
@@ -419,15 +415,6 @@
 	    return;
 	}
 
-	// websocket for noVNC.
-	if ((strstr(buf,"GET /websockify ") && strstr(buf,"Upgrade: websocket"))) {
-	    int nr = ws_server_add_client_protocol(conn, buf, buflen, "/websockify", "binary", websockify_callback);
-	    ESP_LOGI(TAG, "%s new websocket on /websockify client: %d", ipstr, nr);
-	    netbuf_delete(inbuf);
-	    VncStartWS(nr);
-	    return;
-	}
-
 	// websocket for web UI.
 	if ((strstr(buf,"GET /ws ") && strstr(buf,"Upgrade: websocket"))) {
 	    int nr = ws_server_add_client_protocol(conn, buf, buflen, "/ws", "binary", websock_callback);
@@ -438,7 +425,9 @@
 	    return;
 	}
 
+#if 0
 	dump_buf(buf, buflen);
+#endif
 
 	if (strstr(buf, "GET /")) {
 		ESP_LOGI(TAG, "%s request: %s", ipstr, buf);
--- a/main/task_sound.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/task_sound.c	Wed May 08 15:46:50 2019 +0200
@@ -43,7 +43,13 @@
  */
 void BuzzerPlay(const uint16_t *sound)
 {
+    char	msg[16];
+
     for (int i = 1; i <= sound[0]; i += 2) {
+	if (sound != _sound_Startup) {
+	    snprintf(msg, 15, "{\"beep\":\"1\"}");
+    	    ws_server_send_text_clients("/ws", msg, strlen(msg));
+	}
 	gpio_set_level(PIEZO_BUZZER, 1);
 	vTaskDelay(sound[i] / portTICK_PERIOD_MS);
 	gpio_set_level(PIEZO_BUZZER, 0);
@@ -104,14 +110,11 @@
 	    xEventGroupClearBits(xEventGroupSound, SOUND_STARTUP);
 	}
 	if (uxBits & SOUND_PROMPT) {
-	    VncSoundBell();
 	    BuzzerPlay(_sound_Prompt);
 	    xEventGroupClearBits(xEventGroupSound, SOUND_PROMPT);
 	}
 	if (uxBits & SOUND_TEMPREACHED) {
-	    VncSoundBell();
 	    BuzzerPlay(_sound_TempReached);
-	    VncSoundBell();
 	    xEventGroupClearBits(xEventGroupSound, SOUND_TEMPREACHED);
 	}
 	if (uxBits & SOUND_TIMEOUT) {
@@ -119,11 +122,7 @@
 	    xEventGroupClearBits(xEventGroupSound, SOUND_TIMEOUT);
 	}
 	if (uxBits & SOUND_ADDHOP) {
-	    VncSoundBell();
-	    VncSoundBell();
 	    BuzzerPlay(_sound_AddHop);
-	    VncSoundBell();
-	    VncSoundBell();
 	    xEventGroupClearBits(xEventGroupSound, SOUND_ADDHOP);
 	}
 	if (uxBits & SOUND_END) {
@@ -131,7 +130,6 @@
 	    xEventGroupClearBits(xEventGroupSound, SOUND_END);
 	}
 	if (uxBits & SOUND_WARN) {
-	    VncSoundBell();
 	    BuzzerPlay(_sound_Warn);
 	    xEventGroupClearBits(xEventGroupSound, SOUND_WARN);
 	}
--- a/main/task_tft.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/task_tft.c	Wed May 08 15:46:50 2019 +0200
@@ -13,8 +13,9 @@
 spi_lobo_device_handle_t	tsspi = NULL;			///< Touchscreen SPI handler
 extern sButton			Buttons[MAXBUTTONS];		///< 40 buttons on a screen.
 time_t				now;				///< Current time
+time_t				last = 0;			///< Last time
 struct tm			timeinfo;			///< Current time structure
-char				s_timer[10];			///< Timer sctring buffer
+char				s_timer[10];			///< Timer string buffer
 char				s_top_msg[64];			///< Top message string buffer
 
 extern float			stageTemp;
@@ -30,12 +31,14 @@
 extern bool			_NewMinute;
 extern bool			_UseHLT;
 extern bool			System_TimeOk;
+extern const esp_app_desc_t	*app_desc;
 
 static const char		*TAG = "task_tft";
 
 #define SPI_BUS			TFT_HSPI_HOST			///< SPI bus for the TFT, TFT_VSPI_HOST or TFT_HSPI_HOST
 
 extern int			Main_Screen;
+extern int			Sub_Screen;
 extern int			Old_Screen;
 extern int			MLT_pin;
 extern int			HLT_pin;
@@ -470,10 +473,10 @@
 	    hlt_sp[0] = '\0';
 	    hlt_power[0] = '\0';
 	}
-    	snprintf(msg, 1023, "{\"main\":\"%d\",\"mlt_led\":\"%d\",\"mlt_pv\":\"%7.3f\",\"mlt_sp\":\"%s\",\"mlt_power\":\"%s\"" \
+    	snprintf(msg, 1023, "{\"main\":\"%d\",\"sub\":\"%d\",\"mlt_led\":\"%d\",\"mlt_pv\":\"%7.3f\",\"mlt_sp\":\"%s\",\"mlt_power\":\"%s\"" \
 		    ",\"pump_led\":\"%d\",\"hlt_led\":\"%d\",\"hlt_pv\":\"%7.3f\",\"hlt_sp\":\"%s\",\"hlt_power\":\"%s\"" \
 		    ",\"timer\":\"%s\",\"top_msg\":\"%s\"}",
-		    Main_Screen, (MLT_pin) ? 1:0, driver_state->mlt_pv, mlt_sp, mlt_power,
+		    Main_Screen, Sub_Screen, (MLT_pin) ? 1:0, driver_state->mlt_pv, mlt_sp, mlt_power,
 		    (Pump_pin) ? 1:0, (HLT_pin) ? 1:0, driver_state->hlt_pv, hlt_sp, hlt_power,
 		    s_timer, s_top_msg);
 
@@ -487,7 +490,7 @@
 
 void task_tft(void *pvParameter)
 {
-    char	msg[32];
+    char	msg[64];
 
     ESP_LOGI(TAG, "Initialize TFT/Touch task");
 
@@ -528,7 +531,8 @@
 	    /*
 	     * With each screenchange, remove the timer too.
 	     */
-	    snprintf(msg, 31, "{\"main\":\"%d\",\"timer\":\"\"}", Main_Screen);
+	    Sub_Screen = 0;
+	    snprintf(msg, 63, "{\"main\":\"%d\",\"sub\":\"%d\",\"timer\":\"\"}", Main_Screen, Sub_Screen);
 	    ws_server_send_text_clients("/ws", msg, strlen(msg));
 
 	    ESP_LOGI(TAG, "Change screen %d to %d", Old_Screen, Main_Screen);
@@ -557,7 +561,7 @@
 			break;
 
 		case MAIN_INFO:
-			sprintf(temp_buf, "BrewBoard %s", VERSION);
+			sprintf(temp_buf, "BrewBoard %s", app_desc->version);
 			TopMessage(temp_buf);
 			_fg = TFT_YELLOW;
 			TFT_setFont(UBUNTU16_FONT, NULL);
@@ -565,7 +569,7 @@
 			//         -------------------------------------
 			_fg = TFT_ORANGE;
 			TFT_print("Parts are written by Chris Morgan,\r\n", 0, LASTY);
-			TFT_print("Brett Beauregard, Chris Garry, LoBo,\r\n", 0, LASTY);
+			TFT_print("Brett Beauregard, Blake Felt, LoBo,\r\n", 0, LASTY);
 			TFT_print("and David Antliff.\r\n", 0, LASTY);
 			ShowInteger(1,140, "Free memory", " bytes", esp_get_free_heap_size());
 			ShowText(1,158, "IDF version", (char *)esp_get_idf_version());
@@ -618,7 +622,8 @@
 			Updates_Init();
 			break;
 
-		case MAIN_AUTO_INIT:
+		case MAIN_AUTO_INIT1:
+		case MAIN_AUTO_INIT2:
 		case MAIN_AUTO_DELAYSTART:
 		case MAIN_AUTO_HEATUP:
 		case MAIN_AUTO_MASH_IN:
@@ -666,17 +671,20 @@
 		}
 		switch (Buttons_Scan()) {
 		    case 0:	Main_Screen = MAIN_MANUAL_INIT;	break;
-		    case 1:	Main_Screen = MAIN_AUTO_INIT;	break;
-		    case 2:	Main_Screen = MAIN_INFO;		break;
-		    case 3:	Main_Screen = MAIN_TOOLS;		break;
+		    case 1:	Main_Screen = MAIN_AUTO_INIT1;	break;
+		    case 2:	Main_Screen = MAIN_INFO;	break;
+		    case 3:	Main_Screen = MAIN_TOOLS;	break;
 		    default:	break;
 		}
-		if (System_TimeOk) {
+		if (System_TimeOk && (now != last)) {
+		    last = now;
 		    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
 		    TFT_setFont(DEJAVU18_FONT, NULL);
 		    _bg = TFT_BLACK;
 		    _fg = TFT_ORANGE;
 		    TFT_print(strftime_buf, CENTER, 125);
+		    snprintf(msg, 63, "{\"timer\":\"%s\"}", strftime_buf);	// Fix string termination and only send once/second.
+		    ws_server_send_text_clients("/ws", msg, strlen(msg));
 		}
 		break;
 
@@ -735,7 +743,8 @@
 		}
 		break;
 
-	    case MAIN_AUTO_INIT:
+	    case MAIN_AUTO_INIT1:
+	    case MAIN_AUTO_INIT2:
 	    case MAIN_AUTO_DELAYSTART:
 	    case MAIN_AUTO_HEATUP:
 	    case MAIN_AUTO_MASH_IN:
--- a/main/updates.c	Thu May 02 11:52:36 2019 +0200
+++ b/main/updates.c	Wed May 08 15:46:50 2019 +0200
@@ -219,7 +219,7 @@
 	} else if (data_read == 0) {
 	    break;
 	}
-	vTaskDelay(5 / portTICK_PERIOD_MS);
+	vTaskDelay(10 / portTICK_PERIOD_MS);
     }
     fclose(f);
 
@@ -278,8 +278,6 @@
 	fgets(v2, 11, f);
 	fclose(f);
     }
-//    ESP_LOG_BUFFER_HEXDUMP(TAG, v1, strlen(v1), ESP_LOG_INFO);
-//    ESP_LOG_BUFFER_HEXDUMP(TAG, v2, strlen(v2), ESP_LOG_INFO);
     if (strcmp(v1, v2) == 0) {
 	ESP_LOGI(TAG, "/spiffs is up to date");
 	TFT_print("Ok\r\n", LASTX, LASTY);
--- a/sdkconfig	Thu May 02 11:52:36 2019 +0200
+++ b/sdkconfig	Wed May 08 15:46:50 2019 +0200
@@ -11,7 +11,7 @@
 CONFIG_SDK_PYTHON="python"
 CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y
 CONFIG_APP_COMPILE_TIME_DATE=y
-CONFIG_APP_EXCLUDE_PROJECT_VER_VAR=y
+# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
 # CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
 # CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
 # CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
@@ -226,7 +226,7 @@
 CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
 # CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set
 CONFIG_ESP32_WIFI_IRAM_OPT=y
-CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
+# CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE is not set
 # CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set
 CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
 CONFIG_ESP32_PHY_MAX_TX_POWER=20
@@ -498,9 +498,6 @@
 # CONFIG_SUPPORT_TERMIOS is not set
 CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
 CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
-CONFIG_VNC_SERVER_PORT=5900
-CONFIG_VNC_SERVER_FRAME_WIDTH=320
-CONFIG_VNC_SERVER_FRAME_HEIGHT=240
 # CONFIG_WL_SECTOR_SIZE_512 is not set
 CONFIG_WL_SECTOR_SIZE_4096=y
 CONFIG_WL_SECTOR_SIZE=4096

mercurial