=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java'
--- src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java 2015-05-18 20:48:28 +0000
+++ src/com/goldencode/p2j/ui/client/driver/web/PushMessagesWorker.java 2016-02-09 18:52:59 +0000
@@ -11,6 +11,8 @@
** -#- -I- --Date-- ----------------------Description--------------------------
** 001 MAG 20140220 Created initial version.
** 002 GES 20150308 Moved to a more generic package location.
+** 003 SBI 20160209 Implemented sending messages that can exceed the limit message size defined
+** for the current web socket session.
*/
package com.goldencode.p2j.ui.client.driver.web;
@@ -147,6 +149,43 @@
}
/**
+ * Sends a binary message in packets that don't exceed the maximum binary message size for
+ * the current web socket session.
+ *
+ * @param message
+ * The binary message that should be send in packets.
+ * @throws IOException
+ * The exception that can be thrown during the web socket write operation.
+ */
+ private void sendBytesByPackets(ByteBuffer message) throws IOException
+ {
+ int messageLimit = session.getPolicy().getMaxBinaryMessageSize();
+ boolean isLast;
+ message.position(0);
+ message.limit(message.capacity());
+ while(message.hasRemaining())
+ {
+ System.err.println("message.remaining()=" + message.remaining());
+ if (message.remaining() > messageLimit)
+ {
+ isLast = false;
+ message.limit(messageLimit + message.position());
+ }
+ else
+ {
+ isLast = true;
+ }
+ remote.sendPartialBytes(message, isLast);
+ message.position(message.limit());
+ message.limit(message.capacity());
+ System.err.println("message.position()=" + message.position());
+ System.err.println("message.limit()=" + message.limit());
+ System.err.println("message.remaining()=" + message.remaining());
+ System.err.println("message.hasRemaining()=" + message.hasRemaining());
+ }
+ }
+
+ /**
* Send a message.
*/
private void sendMessage()
@@ -166,6 +205,7 @@
// test message type
if (message instanceof ByteBuffer)
{
+ //sendBytesByPackets((ByteBuffer) message);
remote.sendBytes((ByteBuffer) message);
}
else if (message instanceof String)
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/index.html'
--- src/com/goldencode/p2j/ui/client/driver/web/index.html 2015-12-17 20:00:50 +0000
+++ src/com/goldencode/p2j/ui/client/driver/web/index.html 2016-02-07 17:47:14 +0000
@@ -18,6 +18,7 @@
+
=== added file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js'
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js 1970-01-01 00:00:00 +0000
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.connector.js 2016-02-09 19:52:55 +0000
@@ -0,0 +1,665 @@
+/*
+** Module : p2j.connector.js
+** Abstract : Defines the connection module that is responsible for the web socket management.
+**
+** Copyright (c) 2015-2016, Golden Code Development Corporation.
+** ALL RIGHTS RESERVED. Use is subject to license terms.
+**
+** Golden Code Development Corporation
+** CONFIDENTIAL
+**
+** -#- -I- --Date-- ----------------------Description--------------------------
+** 001 SBI 20160209 Implemented the module that manages web socket connection and is executed by
+** the dedicated web worker thread.
+*/
+"use strict";
+
+importScripts("/common/p2j.io.js");
+
+/** The low level web socket */
+var ws;
+
+/** The connection status */
+var connected = false;
+
+/** Input and output channel that is the helper class for read and write web socket operations */
+var io = InputOutputChannel(
+ function(data)
+ {
+ if (connected)
+ {
+ ws.send(data);
+ }
+ });
+
+/**
+ * The web worker message handler that listens messages from the UI thread.
+ *
+ * @param {MessageEvent} msg
+ * The message from the UI thread.
+ */
+self.onmessage = function(msg)
+{
+ var data = msg.data;
+ switch(data.type)
+ {
+ case MSG.MSG_WEB_SOCKET_OPEN:
+ var url = data.url;
+ try
+ {
+ createWebsocket(url);
+ }
+ catch(ex)
+ {
+ self.postMessage({type : MSG.MSG_WEB_SOCKET_ERROR});
+ }
+ break;
+ case MSG.MSG_WEB_SOCKET_CLOSE:
+ if (connected)
+ {
+ connected = false;
+ ws.close();
+ }
+ break;
+ case MSG.MSG_PAGE_LOADED:
+ // notify the web socket has opened and the page is loaded
+ io.sendNotification(MSG.MSG_PAGE_LOADED);
+ break;
+ case MSG.MSG_WEB_SOCKET_SEND:
+ io.send(data.message);
+ break;
+ }
+};
+
+/** Web socket message handler */
+function messageHandler(message)
+{
+ var type = message[0];
+ switch (type)
+ {
+ case MSG.MSG_CLEAR:
+ case MSG.MSG_BEEP:
+ case MSG.MSG_QUIT:
+ self.postMessage({type : type});
+ break;
+ case MSG.MSG_DRAW:
+ // remove the MD5 code and save it here
+ var md5a = new message.constructor(16);
+ message = io.splice(message, 1, 16, md5a);
+ var md5 = io.createHexString(md5a);
+ console.debug("draw buffer length=" + message.buffer.byteLength);
+ self.postMessage({type : type, md5 : md5, drawBuffer : message.buffer}, [message.buffer]);
+ break;
+ case MSG.MSG_CURSOR_POS:
+ self.postMessage({type : type, col : message[1], row : message[2]});
+ break;
+ case MSG.MSG_CURSOR_STATUS:
+ self.postMessage({type : type, status : message[1]});
+ break;
+ case MSG.MSG_VT100:
+ self.postMessage({type : type, vt100 : (message[1] == 0) ? false : true});
+ break;
+ case MSG.MSG_READ_CLIPBOARD:
+ self.postMessage({type : type});
+ break;
+ case MSG.MSG_WRITE_CLIPBOARD:
+ // The clipboard is changed.
+ var text = io.readStringBinaryMessage(message, 1);
+ self.postMessage({type : type, clipboardText : text});
+ break;
+ case MSG.MSG_CREATE_WINDOW:
+ // create a top-level window with the given id
+ var id = io.readInt32BinaryMessage(message, 1);
+ self.postMessage({type : type, id : id});
+ break;
+ case MSG.MSG_CREATE_CHILD_WINDOW:
+ // create a child window with the given id, owner and title
+ var id = io.readInt32BinaryMessage(message, 1);
+ var owner = io.readInt32BinaryMessage(message, 5);
+ var title = io.readStringBinaryMessage(message, 9);
+ self.postMessage({type : type, id : id, owner : owner, title : title});
+ break;
+ case MSG.MSG_DESTROY_WINDOW:
+ // destroy top-level or child window
+ var id = io.readInt32BinaryMessage(message, 1);
+ var numberImages = io.readInt32BinaryMessage(message, 5);
+ var images = new ArrayBuffer(numberImages * 4);
+ var imagesView = new Int32Array(images);
+
+ for (var i = 0; i < numberImages; i++)
+ {
+ imagesView[i] = io.readInt32BinaryMessage(message, 9 + (i * 4));
+ }
+ self.postMessage({type : type, id : id, numberImages : numberImages, images : images},
+ [images]);
+ break;
+ case MSG.MSG_WINDOW_VISIBILITY:
+ // change visibility for top-level or child window
+ var id = io.readInt32BinaryMessage(message, 1);
+ var visible = message[5] === 0 ? false : true;
+ self.postMessage({type : type, id : id, visible : visible});
+ break;
+ // font and metrics related requests
+ case MSG.MSG_GET_PAR_HEIGHT:
+ // paragraph height
+
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var textLength = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var text = io.readStringBinaryMessageByLength(message, offset, textLength);
+ offset = offset + textLength * 2;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var maxWidth = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ self.postMessage(
+ {
+ type : type, msgId : msgId, textLength : textLength,
+ text : text, font : font, maxWidth : maxWidth
+ });
+ break;
+ case MSG.MSG_GET_TEXT_HEIGHT:
+ // text height
+
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var textLength = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var text = io.readStringBinaryMessageByLength(message, offset, textLength);
+ offset = offset + textLength * 2;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+
+ self.postMessage(
+ {
+ type : type, msgId : msgId, textLength : textLength,
+ text : text, font : font
+ });
+ break;
+ case MSG.MSG_GET_TEXT_WIDTH:
+ // text width
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var textLength = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var text = io.readStringBinaryMessageByLength(message, offset, textLength);
+ offset = offset + textLength * 2;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ self.postMessage(
+ {
+ type : type, msgId : msgId, textLength : textLength,
+ text : text, font : font
+ });
+ break;
+ case MSG.MSG_GET_FONT_HEIGHT:
+ // font height
+
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ self.postMessage(
+ {
+ type : type, msgId : msgId, font : font
+ });
+ break;
+ case MSG.MSG_GET_FONT_WIDTHS:
+ // font widths
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ self.postMessage(
+ {
+ type : type, msgId : msgId, font : font
+ });
+ break;
+ case MSG.MSG_CREATE_FONT:
+ // create font
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var nameLength = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ var name = io.readStringBinaryMessageByLength(message, offset, nameLength);
+ offset = offset + nameLength * 2;
+
+ var size = message[offset];
+ offset = offset + 1;
+
+ var style = message[offset];
+ offset = offset + 1;
+
+ var defLength = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var b64font = "";
+ if (defLength > 0)
+ {
+ var binFont = '';
+ for (var i = 0; i < defLength; i++)
+ {
+ binFont += String.fromCharCode(message[offset]);
+ offset = offset + 1;
+ }
+ b64font = self.btoa(binFont);
+ }
+
+ self.postMessage(
+ {
+ type : type, msgId : msgId, font : font, nameLength : nameLength,
+ name : name, size : size, style : style, b64font : b64font
+ });
+ break;
+ case MSG.MSG_DERIVE_FONT:
+ // derive font
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var font = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ self.postMessage(
+ {
+ type : type, msgId : msgId, font : font
+ });
+ break;
+ case MSG.MSG_SET_CURSOR_STYLE:
+ // set cursor style
+ var styleId = io.readInt32BinaryMessage(message, 1);
+ var wid = io.readInt32BinaryMessage(message, 5);
+ self.postMessage(
+ {
+ type : type, styleId : styleId, wid : wid
+ });
+ break;
+ case MSG.MSG_RESTACK_WINDOWS:
+ // restack windows
+ var num = io.readInt32BinaryMessage(message, 1);
+ var winids = new ArrayBuffer(num * 4);
+ var winidsView = new Int32Array(winids);
+ for (var i = 0; i < num; i++)
+ {
+ winidsView[i] = io.readInt32BinaryMessage(message, 5 + (i * 4));
+ }
+ self.postMessage({type : type, winids : winids}, [winids]);
+ break;
+ case MSG.PROCESS_MOUSE_WIDGETS:
+ // register/deregister widgets for mouse actions
+ var offset = 1;
+
+ // the number of windows with new widgets
+ var windowNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ for (var j = 0; j < windowNo; j++)
+ {
+ // the window ID
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // the number of new widgets in this window
+ var widgetNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ var widgets = new ArrayBuffer(widgetNo * 4);
+ var widgetsView = new Int32Array(widgets);
+
+ var xCoords = new ArrayBuffer(widgetNo * 2);
+ var xCoordsView = new Int16Array(xCoords);
+
+ var yCoords = new ArrayBuffer(widgetNo * 2);
+ var yCoordsView = new Int16Array(yCoords);
+
+ var widths = new ArrayBuffer(widgetNo * 2);
+ var widthsView = new Int16Array(widths);
+
+ var heights = new ArrayBuffer(widgetNo * 2);
+ var heightsView = new Int16Array(heights);
+
+ var actions = new ArrayBuffer(widgetNo * 4);
+ var actionsView = new Int32Array(actions);
+
+ for (var k = 0; k < widgetNo; k++)
+ {
+ // the widget ID
+ widgetsView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // the coordinates
+ xCoordsView[k] = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ yCoordsView[k] = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ // the size
+ widthsView[k] = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ heightsView[k] = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ // bit-encoded mouse ops: each bit from 1 to 11, if set, represents a mouse
+ // operation as defined in p2j.screen.mouseOps
+ actionsView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ }
+ var allWNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+ var zOrder = new ArrayBuffer(allWNo * 4);
+ var zOrderView = new Int32Array(zOrder);
+
+ for (var k = 0; k < allWNo; k++)
+ {
+ zOrderView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ }
+ self.postMessage(
+ {
+ type : type, label : "registerWidgets", windowID : windowID, widgetNo : widgetNo,
+ widgets : widgets,
+ xCoords : xCoords, yCoords : yCoords,
+ widths: widths, heights : heights,
+ actions : actions,
+ zOrder : zOrder
+ }, [widgets, xCoords, yCoords, widths, heights, actions, zOrder]);
+ }
+
+ // the number of windows with dead widgets
+ windowNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ for (var j = 0; j < windowNo; j++)
+ {
+ // the window ID
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // the number of dead widgets in this window
+ var widgetNo = io.readInt16BinaryMessage(message, offset);
+
+ var widgets = new ArrayBuffer(widgetNo * 4);
+ var widgetsView = new Int32Array(widgets);
+
+ offset = offset + 2;
+
+ for (var k = 0; k < widgetNo; k++)
+ {
+ // the widget ID
+ widgetsView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ }
+ self.postMessage(
+ {
+ type : type, label : "deregisterWidgets",
+ windowID : windowID, widgetNo : widgetNo,
+ widgets : widgets
+ }, [widgets]);
+ }
+
+ // the number of windows with new "any widgets"
+ windowNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ for (var j = 0; j < windowNo; j++)
+ {
+ // the window ID
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // the number of new "any widgets" in this window
+ var widgetNo = io.readInt16BinaryMessage(message, offset);
+
+ var widgets = new ArrayBuffer(widgetNo * 4);
+ var widgetsView = new Int32Array(widgets);
+
+ offset = offset + 2;
+
+ for (var k = 0; k < widgetNo; k++)
+ {
+ // the widget ID
+ widgetsView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ }
+ self.postMessage(
+ {
+ type : type, label : "registerAnyWidgets",
+ windowID : windowID, widgetNo : widgetNo,
+ widgets : widgets
+ }, [widgets]);
+ }
+
+ // the number of windows with dead "any widgets"
+ windowNo = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+
+ for (var j = 0; j < windowNo; j++)
+ {
+ // the window ID
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // the number of dead "any widgets" in this window
+ var widgetNo = io.readInt16BinaryMessage(message, offset);
+
+ var widgets = new ArrayBuffer(widgetNo * 4);
+ var widgetsView = new Int32Array(widgets);
+
+ offset = offset + 2;
+
+ for (var k = 0; k < widgetNo; k++)
+ {
+ // the widget ID
+ widgetsView[k] = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ }
+ self.postMessage(
+ {
+ type : type, label : "deregisterAnyWidgets",
+ windowID : windowID, widgetNo : widgetNo,
+ widgets : widgets,
+
+ }, [widgets]);
+ }
+ break;
+ case MSG.CAPTURE_MOUSE:
+ self.postMessage({type : type, capture : (message[1] == 1)});
+ break;
+ case MSG.ENABLE_OS_EVENTS:
+ // enable/disable OS events
+ var wid = io.readInt32BinaryMessage(message, 1);
+ self.postMessage(
+ {
+ type : type,
+ windowID : wid,
+ enable : message[5] == 1
+ });
+ break;
+ case MSG.SET_ICONIFICATION_STATE:
+ // set window iconification state
+ var offset = 1;
+
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ self.postMessage(
+ {
+ type : type,
+ windowID : windowID,
+ iconified : message[5] == 1
+ });
+ break;
+ case MSG.SET_RESIZEABLE_WINDOW:
+ // resizeable window
+ var offset = 1;
+
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var resizeable = (message[offset] == 1);
+ offset = offset + 1;
+
+ var msg = {type : type, windowID : windowID, resizeable : resizeable};
+
+ if (resizeable)
+ {
+ msg.minWidth = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+ msg.minHeight = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+ msg.maxWidth = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+ msg.maxHeight = io.readInt16BinaryMessage(message, offset);
+ offset = offset + 2;
+ }
+ self.postMessage(msg);
+ break;
+ case MSG.MSG_CURRENT_SELECTION:
+ // current editors selection is changed
+ var text = io.readStringBinaryMessage(message, 1);
+ self.postMessage({type : type, clipboardText : text});
+ break;
+ case MSG.MSG_MOVE_TO_TOP:
+ case MSG.MSG_MOVE_TO_BOTTOM:
+ var id = io.readInt32BinaryMessage(message, 1);
+ self.postMessage({type : type, windowID : id});
+ break;
+ case MSG.MSG_WINDOW_SENSITIVITY:
+ // change sensitivity for top-level or child window
+ var id = io.readInt32BinaryMessage(message, 1);
+ var enabled = message[5] === 0 ? false : true;
+ self.postMessage({type : type, windowID : id, enabled : enabled});
+ break;
+ case MSG.MSG_IS_FONT_INSTALLED:
+ // font is installed
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var fontNameLength = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ var fontName = io.readStringBinaryMessageByLength(message, offset, fontNameLength);
+
+ self.postMessage({type : type, msgId : msgId, fontName : fontName});
+ break;
+ case MSG.MSG_REMOVE_EXPIRED_HASH:
+ // remove hashes
+ var offset = 1;
+
+ var msgId = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // window ID
+ var windowID = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+
+ // number of hashes
+ var hashNo = io.readInt32BinaryMessage(message, offset);
+ offset = offset + 4;
+ var hashes = message.slice(offset);
+ console.debug("hashes buffer length=" + hashes.buffer.byteLength);
+ self.postMessage(
+ {
+ type : type, msgId : msgId, windowID : windowID, hashNo : hashNo,
+ hashes : hashes.buffer
+ }, [hashes.buffer]);
+ break;
+ };
+}
+
+/**
+ * Creates a web socket connection and attaches the error, message and close listeners for it.
+ *
+ * @param {String} url
+ * The web socket connection url
+ */
+function createWebsocket(url)
+{
+ ws = new WebSocket(url);
+
+ /**
+ * Handles the web socket open message.
+ */
+ ws.onopen = function()
+ {
+ connected = true;
+ ws.binaryType = 'arraybuffer';
+
+ self.postMessage({type : MSG.MSG_WEB_SOCKET_OPEN});
+
+ };
+
+ /**
+ * Handles the web socket data messages.
+ */
+ ws.onmessage = function(evt)
+ {
+ var data = evt.data;
+ console.debug("evt=" + JSON.stringify(evt));
+ console.debug("data=" + JSON.stringify(data));
+ if (data instanceof ArrayBuffer)
+ {
+ // binary messages
+ var message = new Uint8Array(data);
+ messageHandler(message);
+ }
+ else
+ {
+ // text messages
+ var msg = JSON.parse(data);
+ self.postMessage({type : MSG.MSG_COLOR_PALETTE, msg : msg});
+ }
+ };
+
+ /**
+ * Handles the web socket close message.
+ */
+ ws.onclose = function()
+ {
+ connected = false;
+ self.postMessage({type : MSG.MSG_WEB_SOCKET_CLOSE});
+ };
+
+ /**
+ * Handles the web socket errors.
+ */
+ ws.onerror = function(ex)
+ {
+ console.debug("exception=" + ex);
+ //self.postMessage({type : MSG.MSG_WEB_SOCKET_ERROR});
+ };
+}
\ No newline at end of file
=== added file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js'
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js 1970-01-01 00:00:00 +0000
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.io.js 2016-02-09 17:40:29 +0000
@@ -0,0 +1,667 @@
+/*
+** Module : p2j.io.js
+** Abstract : Defines the common message's types and the helper input and output channel.
+**
+** Copyright (c) 2015-2016, Golden Code Development Corporation.
+** ALL RIGHTS RESERVED. Use is subject to license terms.
+**
+** Golden Code Development Corporation
+** CONFIDENTIAL
+**
+** -#- -I- --Date-- ----------------------Description--------------------------
+** 001 SBI 20160209 Reused the common input and output functions under the input and output
+** channel object.
+*/
+"use strict";
+
+/**
+ * Defines the common message's types.
+ */
+var MSG = {
+ /** Message that the web page has finished loading/initializing. */
+ MSG_PAGE_LOADED : 0xFF,
+
+ /** Progress compatible keyboard message. */
+ MSG_KEY : 0x01,
+
+ /** Virtual VT100 terminal keyboard message. */
+ MSG_KEY_VT100 : 0x02,
+
+ /** Paste message. */
+ MSG_PASTE : 0x03,
+
+ /** Contents from the clipboard. */
+ MSG_CLIPBOARD_CONTENTS : 0x04,
+
+ /** Web client is requesting the current selection text. */
+ MSG_CLIPBOARD_PREPARE : 0x05,
+
+ /** Web client is sending computed paragraph height. */
+ MSG_SENT_PAR_HEIGHT : 0x06,
+
+ /** Web client is sending computed text height. */
+ MSG_SENT_TEXT_HEIGHT : 0x07,
+
+ /** Web client is sending computed text width. */
+ MSG_SENT_TEXT_WIDTH : 0x08,
+
+ /** Web client is sending computed font height. */
+ MSG_SENT_FONT_HEIGHT : 0x09,
+
+ /** Web client is sending computed font widths. */
+ MSG_SENT_FONT_WIDTHS : 0x0A,
+
+ /** Web client is informing the font has been created. */
+ MSG_DONE_CREATE_FONT : 0x0B,
+
+ /** Web client is informing the font has been derived. */
+ MSG_DONE_DERIVE_FONT : 0x0C,
+
+ /** Web client is informing of a mouse event. */
+ MSG_MOUSE_EVENT : 0x0D,
+
+ /** Web client is informing of new window location. */
+ MSG_SET_WINDOW_LOC : 0x0E,
+
+ /** Web client is informing of new top window. */
+ MSG_WINDOW_ACTIVATED : 0x0F,
+
+ /** Web client is informing of new window iconification state. */
+ MSG_WINDOW_ICONIFY : 0x10,
+
+ /** Web client is informing of new window location/dimension after resize. */
+ MSG_WINDOW_RESIZED : 0x11,
+
+ /** Web client is informing it finished removing the hashes. */
+ MSG_DRAW_HASH_REMOVED : 0x12,
+
+ /** Clear screen message. */
+ MSG_CLEAR : 0x80,
+
+ /** Draw text on screen. */
+ MSG_DRAW : 0x81,
+
+ /** Set cursor position. */
+ MSG_CURSOR_POS : 0x82,
+
+ /** Set cursor status. */
+ MSG_CURSOR_STATUS : 0x83,
+
+ /** Beep message. */
+ MSG_BEEP : 0x84,
+
+ /** Quit message. */
+ MSG_QUIT : 0x85,
+
+ /** Switch input processing to virtual VT100 terminal mode. */
+ MSG_VT100 : 0x86,
+
+ /** Request clipboard contents from web client. */
+ MSG_READ_CLIPBOARD : 0x87,
+
+ /** Copy the given text to the web client's clipboard. */
+ MSG_WRITE_CLIPBOARD : 0x88,
+
+ /** Create a new top-level window. */
+ MSG_CREATE_WINDOW : 0x89,
+
+ /** Create a new child window. */
+ MSG_CREATE_CHILD_WINDOW : 0x8A,
+
+ /** Destroy the specified window or child window. */
+ MSG_DESTROY_WINDOW : 0x8B,
+
+ /** Change the visibility for the specified window or child window. */
+ MSG_WINDOW_VISIBILITY : 0x8C,
+
+ /** Ask the client for the paragraph height. */
+ MSG_GET_PAR_HEIGHT : 0x8D,
+
+ /** Ask the client for the text height. */
+ MSG_GET_TEXT_HEIGHT : 0x8E,
+
+ /** Ask the client for the text width. */
+ MSG_GET_TEXT_WIDTH : 0x8F,
+
+ /** Ask the client for the font height. */
+ MSG_GET_FONT_HEIGHT : 0x90,
+
+ /** Ask the client for the font widths. */
+ MSG_GET_FONT_WIDTHS : 0x91,
+
+ /** Ask the client to create a font. */
+ MSG_CREATE_FONT : 0x92,
+
+ /** Ask the client to derive a font. */
+ MSG_DERIVE_FONT : 0x93,
+
+ /** Set the cursor style. */
+ MSG_SET_CURSOR_STYLE : 0x94,
+
+ /** Restack the z-order of all windows. */
+ MSG_RESTACK_WINDOWS : 0x95,
+
+ /** Send the mouse-aware widget details. */
+ PROCESS_MOUSE_WIDGETS : 0x96,
+
+ /** Disable/enable mouse event processing. */
+ CAPTURE_MOUSE : 0x97,
+
+ /** Disable/enable OS event processing. */
+ ENABLE_OS_EVENTS : 0x98,
+
+ /** Window state changed event. */
+ SET_ICONIFICATION_STATE : 0x99,
+
+ /** Resizeable widget. */
+ SET_RESIZEABLE_WINDOW : 0x9A,
+
+ /** Notifies the client about the current selection. */
+ MSG_CURRENT_SELECTION : 0x9B,
+
+ /** Requests the client to move a window to the top of the z-order. */
+ MSG_MOVE_TO_TOP : 0x9C,
+
+ /** Requests the client to move a window to the bottom of the z-order. */
+ MSG_MOVE_TO_BOTTOM : 0x9D,
+
+ /** Change the sensitivity for the specified window or child window. */
+ MSG_WINDOW_SENSITIVITY : 0x9E,
+
+ /** Requests the client if the target font is installed. */
+ MSG_IS_FONT_INSTALLED : 0x9F,
+
+ /** Inform the javascript side to remove the list of expired hashes. */
+ MSG_REMOVE_EXPIRED_HASH : 0xA0,
+
+ /** Color palette message. */
+ MSG_COLOR_PALETTE : 0xA5,
+
+ /** WEB SOCKET CLOSE */
+ MSG_WEB_SOCKET_OPEN : 0xA1,
+
+ /** WEB SOCKET CLOSE */
+ MSG_WEB_SOCKET_CLOSE : 0xA2,
+
+ /** WEB SOCKET ERROR */
+ MSG_WEB_SOCKET_ERROR : 0xA3,
+
+ /** WEB SOCKET SEND */
+ MSG_WEB_SOCKET_SEND : 0xA4,
+
+ };
+
+/**
+ * Input and output channel.
+ *
+ * @param {Function} callback
+ * The callback function to which all output operations are deligated.
+ *
+ * @return {Object}
+ * The helper input and output channel.
+ */
+function InputOutputChannel(callback)
+{
+
+ var me = {};
+
+ /**
+ * Send data.
+ *
+ * @param {array}
+ * data
+ */
+ me.send = function(data)
+ {
+ callback(data);
+ };
+
+ /**
+ * Send a binary message with the given message type as the first and only
+ * byte.
+ *
+ * @param {byte}
+ * type Message type code.
+ */
+ me.sendNotification = function(type)
+ {
+ var msg = new Uint8Array(1);
+ msg[0] = type;
+
+ me.send(msg);
+ };
+
+ /**
+ * Sends the window active event to the server.
+ *
+ * @param {Number}
+ * wid The target window id
+ * @param {Boolean}
+ * active The flag indicating that the target window should be
+ * active or not.
+ * @param {Boolean}
+ * focusOut The true value indicates that the current focus is
+ * moved from a non P2J window to a P2J window for an activation
+ * event or from a P2j window to a non P2j window for a
+ * deactivation event.
+ */
+ me.sendWindowActive = function(wid, active, focusOut)
+ {
+ // send the window activation/deactivation to the java side
+ var msg = new Uint8Array(7);
+
+ // message type
+ msg[0] = 0x0f;
+
+ // 1. the window ID
+ me.writeInt32BinaryMessage(msg, 1, wid);
+
+ msg[5] = active ? 1 : 0;
+ msg[6] = focusOut ? 1 : 0;
+
+ // send the window active event
+ me.send(msg);
+ }
+
+ /**
+ * Sends the window icon state event to the server.
+ *
+ * @param {Number}
+ * wid The target window id.
+ * @param {Boolean}
+ * minimized The target window has been minimized.
+ */
+ me.sendWindowIconState = function(wid, minimized)
+ {
+ var msg = new Uint8Array(6);
+
+ // message type
+ msg[0] = 0x10;
+
+ // 0. the window ID
+ me.writeInt32BinaryMessage(msg, 1, wid);
+
+ // 1. the iconification state
+ msg[5] = minimized ? 1 : 0;
+
+ // send the mouse event
+ me.send(msg);
+ }
+
+ /**
+ * Send a binary message with the given message type and the specified byte array serialized.
+ *
+ * @param {byte} type
+ * Message type code.
+ * @param {int} msgId
+ * The message ID.
+ * @param {c} c
+ * The array to send.
+ */
+ me.sendByteArrayBinaryMessage = function(type, msgId, c)
+ {
+ var msg = new Uint8Array(1 + 4 + 2 + c.length);
+
+ var offset = 0;
+ msg[offset] = type;
+ offset = offset + 1;
+
+ me.writeInt32BinaryMessage(msg, offset, msgId);
+ offset = offset + 4;
+
+ msg[offset] = c.length & 0xff;
+ offset = offset + 1;
+ msg[offset] = (c.length >> 8) & 0xff
+ offset = offset + 1;
+
+ for (var i = 0; i < c.length; i++)
+ {
+ msg[offset] = c[i] & 0xff;
+ offset = offset + 1;
+ }
+
+ me.send(msg);
+ };
+
+ /**
+ * Send a binary message with the given message type and the specified byte as the second byte.
+ *
+ * @param {byte} type
+ * Message type code.
+ * @param {int} msgId
+ * The message ID.
+ * @param {c} c
+ * The byte to send.
+ */
+ me.sendInt8BinaryMessage = function(type, msgId, c)
+ {
+ var msg = new Uint8Array(1 + 4 + 1);
+
+ msg[0] = type;
+ me.writeInt32BinaryMessage(msg, 1, msgId);
+ msg[5] = c;
+
+ me.send(msg);
+ };
+
+ /**
+ * Send a binary message with the given message type and the specified 16bit integer as the
+ * second and third bytes.
+ *
+ * @param {byte} type
+ * Message type code.
+ * @param {int} msgId
+ * The message ID.
+ * @param {c} c
+ * The 16bit integer to send.
+ */
+ me.sendInt16BinaryMessage = function(type, msgId, c)
+ {
+ var msg = new Uint8Array(1 + 4 + 2);
+
+ msg[0] = type;
+ me.writeInt32BinaryMessage(msg, 1, msgId);
+ me.writeInt16BinaryMessage(msg, 5, c);
+
+ me.send(msg);
+ };
+
+ /**
+ * Send a binary message with the given message type and the specified 32bit integer as the
+ * second, third, forth and fifth bytes.
+ *
+ * @param {byte} type
+ * Message type code.
+ * @param {int} msgId
+ * The message ID.
+ * @param {c} c
+ * The 32bit integer to send.
+ */
+ me.sendInt32BinaryMessage = function(type, msgId, c)
+ {
+ var msg = new Uint8Array(1 + 4 + 4);
+
+ msg[0] = type;
+ me.writeInt32BinaryMessage(msg, 1, msgId);
+ me.writeInt32BinaryMessage(msg, 5, c);
+
+ me.send(msg);
+ };
+
+ /**
+ * Send text as a binary message with the given message type as the first byte.
+ *
+ * @param {byte} type
+ * Message type code.
+ * @param {String} text
+ * The text to send.
+ */
+ me.sendStringBinaryMessage = function(type, text)
+ {
+ var msg = new Uint8Array(text.length * 2 + 1);
+ msg[0] = type;
+
+ for (var i = 0, j = 1; i < text.length; i++, j += 2)
+ {
+ var c = text.charCodeAt(i);
+ msg[j + 1] = c & 0xff;
+ c = c >> 8;
+ msg[j] = c & 0xff;
+ }
+
+ me.send(msg);
+ };
+
+ /**
+ * Read text from a binary message with characters interpreted as 16-bit values.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ */
+ me.readStringBinaryMessage = function(message, offset)
+ {
+ var text = "";
+
+ for (var i = offset; i < message.length; i += 2)
+ {
+ var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
+
+ text = text + c;
+ }
+
+ return text;
+ };
+
+ /**
+ * Read text from a binary message with characters interpreted as 16-bit values, with the
+ * specified length
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ * @param {len} length
+ * The length of the string.
+ */
+ me.readStringBinaryMessageByLength = function(message, offset, len)
+ {
+ var text = "";
+
+ for (var i = offset; i < offset + len * 2; i += 2)
+ {
+ var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
+
+ text = text + c;
+ }
+
+ return text;
+ };
+
+ /**
+ * Read a 32-bit integer from a binary message at a specific offset.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ *
+ * @return The number that was read.
+ */
+ me.readInt32BinaryMessage = function(message, offset)
+ {
+ var num = 0;
+
+ for (var i = 0; i < 4; i++)
+ {
+ num |= message[offset + i] << (8 * (3 - i));
+ }
+
+ return num;
+ };
+
+ /**
+ * Write a 64-bit integer to a binary message at a specific offset.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ * @param {int} value
+ * The value to write.
+ */
+ me.writeInt64BinaryMessage = function(message, offset, value)
+ {
+ // javascript keeps all numbers as decimal, with:
+ // - the fraction in bits from 0 to 51
+ // - the exponent in bits from 52 to 62
+ // - the sign in bit 63
+
+ // for this reason, use the hex representation to transform it into 2 32bit integer values
+ // and send the high and low bits separately.
+ var hex = value.toString(16);
+
+ // left-pad with zeros
+ while (hex.length < 16)
+ {
+ hex = "0" + hex;
+ }
+
+ var hexHigh = hex.substring(0, 8);
+ var hexLow = hex.substring(8, 16);
+
+ var ihigh = parseInt(hexHigh, 16);
+ var ilow = parseInt(hexLow, 16);
+
+ // clear high bits 20 to 30 (52 to 62, the exponent)
+ for (var i = 20; i <= 30; i++)
+ {
+ ihigh = ihigh & ~(1 << i);
+ }
+
+ me.writeInt32BinaryMessage(message, offset, ihigh);
+ offset = offset + 4;
+ me.writeInt32BinaryMessage(message, offset, ilow);
+ offset = offset + 4;
+ }
+
+ /**
+ * Write a 32-bit integer to a binary message at a specific offset.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ * @param {int} value
+ * The value to write.
+ */
+ me.writeInt32BinaryMessage = function(message, offset, value)
+ {
+ message[offset] = ((value >> 24) & 0xFF);
+ message[offset + 1] = ((value >> 16) & 0xFF);
+ message[offset + 2] = ((value >> 8) & 0xFF);
+ message[offset + 3] = ( value & 0xFF);
+ }
+
+ /**
+ * Write a 16-bit integer to a binary message at a specific offset.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ * @param {int} value
+ * The value to write.
+ */
+ me.writeInt16BinaryMessage = function(message, offset, value)
+ {
+ message[offset] = ((value >> 8) & 0xFF);
+ message[offset + 1] = ( value & 0xFF);
+ }
+
+ /**
+ * Read a 16-bit integer from a binary message at a specific offset.
+ *
+ * @param {byte[]} message
+ * Message bytes.
+ * @param {int} offset
+ * The location in the message at which the characters start.
+ *
+ * @return The number that was read.
+ */
+ me.readInt16BinaryMessage = function(message, offset)
+ {
+ var num = 0;
+
+ for (var i = 0; i < 2; i++)
+ {
+ num |= message[offset + i] << (8 * (1 - i));
+ }
+
+ return num;
+ };
+
+ /**
+ * Parse a hex string and return its byte array.
+ *
+ * @param {String} str
+ * The hex-encoded string.
+ *
+ * @return {Uint8Array} byte-array for the given string.
+ */
+ me.hexStringToBytes = function(str)
+ {
+ var bytes = new Uint8Array(str.length / 2);
+
+ var idx = 0;
+ for (var c = 0, idx = 0; c < str.length; c += 2, idx++)
+ {
+ bytes[idx] = parseInt(str.substr(c, 2), 16);
+ }
+
+ return bytes;
+ }
+
+ /**
+ * Create a hex string from the given byte array.
+ *
+ * @param {Uint8Array} arr
+ * The byte array.
+ *
+ * @return Hex representation of the given byte array.
+ */
+ me.createHexString = function(arr)
+ {
+ var result = "";
+ for (var i in arr)
+ {
+ var str = arr[i].toString(16);
+ str = str.length == 0 ? "00" :
+ str.length == 1 ? "0" + str :
+ str.length == 2 ? str :
+ str.substring(str.length-2, str.length);
+
+ result += str;
+ }
+
+ return result;
+ }
+
+ /**
+ * Remove the sub-array from the given array and save it in the splice parameter.
+ *
+ * @param {array} arr
+ * The byte array from where elements are removed.
+ * @param {int} starting
+ * The starting position (inclusive).
+ * @param {int} deleteCount
+ * The number of elements to delete.
+ * @param {array} splice
+ * The array where to save the elements (must have enough space).
+ *
+ * @return The original array with the elements removed.
+ */
+ me.splice = function(arr, starting, deleteCount, splice)
+ {
+ if (arguments.length === 1)
+ {
+ return arr;
+ }
+
+ starting = Math.max(starting, 0);
+ deleteCount = Math.max(deleteCount, 0);
+
+ const newSize = arr.length - deleteCount;
+ const splicedArray = new arr.constructor(newSize);
+
+ splicedArray.set(arr.subarray(0, starting));
+ splicedArray.set(arr.subarray(starting + deleteCount), starting);
+
+ splice.set(arr.subarray(starting, starting + deleteCount));
+
+ return splicedArray;
+ };
+
+ return me;
+}
\ No newline at end of file
=== modified file 'src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js'
--- src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js 2016-02-03 21:22:52 +0000
+++ src/com/goldencode/p2j/ui/client/driver/web/res/p2j.socket.js 2016-02-09 20:05:13 +0000
@@ -41,7 +41,9 @@
** SBI 20160107 Supported new message with 0x9F id to test if the target font family is
** available for the browser.
** CA 20160629 Added a drawing cache (and cache management, when the hash was expired by the
-* client-side).
+** client-side).
+** SBi 20160209 Changed to put the web socket processing in the dedicated web worker thread
+** in order to send the large binary messages in packets.
*/
"use strict";
@@ -66,6 +68,24 @@
/** The count of the drawing operations. */
var drawNo = 0;
+ /** Web worker */
+ var webWorker;
+
+ /** Input and output channel */
+ var io = InputOutputChannel(
+ function(data)
+ {
+ if (connected)
+ {
+ webWorker.postMessage({type : MSG.MSG_WEB_SOCKET_SEND, message: data}, [data.buffer]);
+ }
+ else
+ {
+ p2j.sound.beep();
+ }
+ });
+
+
/**
* Send data.
*
@@ -73,14 +93,7 @@
*/
me.send = function(data)
{
- if (connected)
- {
- ws.send(data);
- }
- else
- {
- p2j.sound.beep();
- }
+ io.send(data);
};
/**
@@ -91,10 +104,7 @@
*/
me.sendNotification = function(type)
{
- var msg = new Uint8Array(1);
- msg[0] = type;
-
- me.send(msg);
+ io.sendNotification(type);
};
/**
@@ -111,20 +121,7 @@
*/
me.sendWindowActive = function(wid, active, focusOut)
{
- // send the window activation/deactivation to the java side
- var msg = new Uint8Array(7);
-
- // message type
- msg[0] = 0x0f;
-
- // 1. the window ID
- me.writeInt32BinaryMessage(msg, 1, wid);
-
- msg[5] = active ? 1 : 0;
- msg[6] = focusOut ? 1 : 0;
-
- // send the window active event
- me.send(msg);
+ io.sendWindowActive(wid, active, focusOut);
}
/**
@@ -137,19 +134,7 @@
*/
me.sendWindowIconState = function(wid, minimized)
{
- var msg = new Uint8Array(6);
-
- // message type
- msg[0] = 0x10;
-
- // 0. the window ID
- me.writeInt32BinaryMessage(msg, 1, wid);
-
- // 1. the iconification state
- msg[5] = minimized ? 1 : 0;
-
- // send the mouse event
- me.send(msg);
+ io.sendWindowIconState(wid, minimized);
}
/**
@@ -164,27 +149,7 @@
*/
me.sendByteArrayBinaryMessage = function(type, msgId, c)
{
- var msg = new Uint8Array(1 + 4 + 2 + c.length);
-
- var offset = 0;
- msg[offset] = type;
- offset = offset + 1;
-
- me.writeInt32BinaryMessage(msg, offset, msgId);
- offset = offset + 4;
-
- msg[offset] = c.length & 0xff;
- offset = offset + 1;
- msg[offset] = (c.length >> 8) & 0xff
- offset = offset + 1;
-
- for (var i = 0; i < c.length; i++)
- {
- msg[offset] = c[i] & 0xff;
- offset = offset + 1;
- }
-
- me.send(msg);
+ io.sendByteArrayBinaryMessage(type, msgId, c);
};
/**
@@ -199,13 +164,7 @@
*/
me.sendInt8BinaryMessage = function(type, msgId, c)
{
- var msg = new Uint8Array(1 + 4 + 1);
-
- msg[0] = type;
- me.writeInt32BinaryMessage(msg, 1, msgId);
- msg[5] = c;
-
- me.send(msg);
+ io.sendInt8BinaryMessage(type, msgId, c);
};
/**
@@ -221,13 +180,7 @@
*/
me.sendInt16BinaryMessage = function(type, msgId, c)
{
- var msg = new Uint8Array(1 + 4 + 2);
-
- msg[0] = type;
- me.writeInt32BinaryMessage(msg, 1, msgId);
- me.writeInt16BinaryMessage(msg, 5, c);
-
- me.send(msg);
+ io.sendInt16BinaryMessage(type, msgId, c);
};
/**
@@ -243,13 +196,7 @@
*/
me.sendInt32BinaryMessage = function(type, msgId, c)
{
- var msg = new Uint8Array(1 + 4 + 4);
-
- msg[0] = type;
- me.writeInt32BinaryMessage(msg, 1, msgId);
- me.writeInt32BinaryMessage(msg, 5, c);
-
- me.send(msg);
+ io.sendInt32BinaryMessage(type, msgId, c);
};
/**
@@ -262,18 +209,7 @@
*/
me.sendStringBinaryMessage = function(type, text)
{
- var msg = new Uint8Array(text.length * 2 + 1);
- msg[0] = type;
-
- for (var i = 0, j = 1; i < text.length; i++, j += 2)
- {
- var c = text.charCodeAt(i);
- msg[j + 1] = c & 0xff;
- c = c >> 8;
- msg[j] = c & 0xff;
- }
-
- me.send(msg);
+ io.sendStringBinaryMessage(type, text);
};
/**
@@ -286,16 +222,7 @@
*/
me.readStringBinaryMessage = function(message, offset)
{
- var text = "";
-
- for (var i = offset; i < message.length; i += 2)
- {
- var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
-
- text = text + c;
- }
-
- return text;
+ return io.readStringBinaryMessage(message, offset);
};
/**
@@ -311,16 +238,7 @@
*/
me.readStringBinaryMessageByLength = function(message, offset, len)
{
- var text = "";
-
- for (var i = offset; i < offset + len * 2; i += 2)
- {
- var c = String.fromCharCode((message[i] << 8) | message[i + 1]);
-
- text = text + c;
- }
-
- return text;
+ return io.readStringBinaryMessageByLength(message, offset, len);
};
/**
@@ -335,14 +253,7 @@
*/
me.readInt32BinaryMessage = function(message, offset)
{
- var num = 0;
-
- for (var i = 0; i < 4; i++)
- {
- num |= message[offset + i] << (8 * (3 - i));
- }
-
- return num;
+ return io.readInt32BinaryMessage(message, offset)
};
/**
@@ -357,37 +268,7 @@
*/
me.writeInt64BinaryMessage = function(message, offset, value)
{
- // javascript keeps all numbers as decimal, with:
- // - the fraction in bits from 0 to 51
- // - the exponent in bits from 52 to 62
- // - the sign in bit 63
-
- // for this reason, use the hex representation to transform it into 2 32bit integer values
- // and send the high and low bits separately.
- var hex = value.toString(16);
-
- // left-pad with zeros
- while (hex.length < 16)
- {
- hex = "0" + hex;
- }
-
- var hexHigh = hex.substring(0, 8);
- var hexLow = hex.substring(8, 16);
-
- var ihigh = parseInt(hexHigh, 16);
- var ilow = parseInt(hexLow, 16);
-
- // clear high bits 20 to 30 (52 to 62, the exponent)
- for (var i = 20; i <= 30; i++)
- {
- ihigh = ihigh & ~(1 << i);
- }
-
- me.writeInt32BinaryMessage(message, offset, ihigh);
- offset = offset + 4;
- me.writeInt32BinaryMessage(message, offset, ilow);
- offset = offset + 4;
+ io.writeInt64BinaryMessage(message, offset, value);
}
/**
@@ -402,10 +283,7 @@
*/
me.writeInt32BinaryMessage = function(message, offset, value)
{
- message[offset] = ((value >> 24) & 0xFF);
- message[offset + 1] = ((value >> 16) & 0xFF);
- message[offset + 2] = ((value >> 8) & 0xFF);
- message[offset + 3] = ( value & 0xFF);
+ io.writeInt32BinaryMessage(message, offset, value);
}
/**
@@ -420,8 +298,7 @@
*/
me.writeInt16BinaryMessage = function(message, offset, value)
{
- message[offset] = ((value >> 8) & 0xFF);
- message[offset + 1] = ( value & 0xFF);
+ io.writeInt16BinaryMessage(message, offset, value);
}
/**
@@ -436,15 +313,271 @@
*/
me.readInt16BinaryMessage = function(message, offset)
{
- var num = 0;
+ return io.readInt16BinaryMessage(message, offset);
+ };
+
+ /** Web worker message handler */
+ var messageHandler = function(message)
+ {
+ callNo = callNo + 1;
+ console.log(callNo + ": " + message.type.toString(16));
- for (var i = 0; i < 2; i++)
+ switch (message.type)
{
- num |= message[offset + i] << (8 * (1 - i));
- }
-
- return num;
- };
+ case MSG.MSG_CLEAR:
+ // clear screen
+ p2j.screen.clear();
+ break;
+ case MSG.MSG_DRAW:
+ drawNo = drawNo + 1;
+ // draw screen
+ var t1 = (new Date()).getTime();
+ console.debug("drawBuffer.length=" + message.drawBuffer.byteLength);
+ var binaries = new Uint8Array(message.drawBuffer);
+ p2j.screen.drawRectangles(binaries, message.md5);
+ var t2 = (new Date()).getTime();
+ console.log(callNo + ":" + drawNo + " draw: " + message.drawBuffer.byteLength
+ + " done in " + (t2 - t1) + " with md5: " + message.md5);
+ break;
+ case MSG.MSG_CURSOR_POS:
+ // set cursor position
+ p2j.screen.setCursorPosition(message.col, message.row);
+ break;
+ case MSG.MSG_CURSOR_STATUS:
+ // show cursor
+ p2j.screen.setCursorStatus(message.status);
+ break;
+ case MSG.MSG_BEEP:
+ // message beep
+ p2j.sound.beep();
+ break;
+ case MSG.MSG_QUIT:
+ // quit
+ window.location.replace(referrer);
+ break;
+ case MSG.MSG_VT100:
+ // switch mode p2j/vt100
+ p2j.keyboard.vt100 = (message[1] == 0) ? false : true;
+ break;
+ case MSG.MSG_READ_CLIPBOARD:
+ // server-driven request for clipboard contents
+ p2j.clipboard.sendClipboardContents();
+ break;
+ case MSG.MSG_WRITE_CLIPBOARD:
+ // The clipboard is changed.
+ p2j.clipboard.writeClipboard(message.clipboardText);
+ break;
+ case MSG.MSG_CREATE_WINDOW:
+ // create a top-level window with the given id
+ p2j.screen.createWindow(message.id);
+ break;
+ case MSG.MSG_CREATE_CHILD_WINDOW:
+ // create a child window with the given id, owner and title
+ p2j.screen.createChildWindow(message.id, message.owner);
+ break;
+ case MSG.MSG_DESTROY_WINDOW:
+ // destroy top-level or child window
+ var imagesView = new Int32Array(message.images);
+ p2j.screen.destroyWindow(message.id, imagesView);
+ break;
+ case MSG.MSG_WINDOW_VISIBILITY:
+ // change visibility for top-level or child window
+ p2j.screen.setWindowVisible(message.id, message.visible);
+ break;
+ // font and metrics related requests
+ case MSG.MSG_GET_PAR_HEIGHT:
+ // paragraph height
+ var pheight = p2j.screen.layoutParagraphWorker(null,
+ message.text,
+ message.font,
+ 0,
+ 0,
+ message.maxWidth);
+
+ me.sendInt16BinaryMessage(MSG.MSG_SENT_PAR_HEIGHT, message.msgId, pheight);
+ break;
+ case MSG.MSG_GET_TEXT_HEIGHT:
+ // text height
+ var theight = p2j.fonts.getTextHeight(message.font, message.text);
+
+ me.sendInt8BinaryMessage(MSG.MSG_SENT_TEXT_HEIGHT, message.msgId, theight);
+ break;
+ case MSG.MSG_GET_TEXT_WIDTH:
+ // text width
+ var twidth = p2j.fonts.getTextWidth(message.font, message.text);
+
+ me.sendInt16BinaryMessage(MSG.MSG_SENT_TEXT_WIDTH, message.msgId, twidth);
+ break;
+ case MSG.MSG_GET_FONT_HEIGHT:
+ // font height
+ var fheight = p2j.fonts.getFontHeight(message.font);
+
+ me.sendInt8BinaryMessage(MSG.MSG_SENT_FONT_HEIGHT, message.msgId, fheight);
+ break;
+ case MSG.MSG_GET_FONT_WIDTHS:
+ // font widths
+ var fwidths = p2j.fonts.getFontWidths(message.font);
+
+ me.sendByteArrayBinaryMessage(MSG.MSG_SENT_FONT_WIDTHS, message.msgId, fwidths);
+ break;
+ case MSG.MSG_CREATE_FONT:
+ // create font
+ var fontId = p2j.fonts.createFont(message.font, message.name, message.size,
+ message.style, message.b64font);
+
+ me.sendInt32BinaryMessage(MSG.MSG_DONE_CREATE_FONT, message.msgId, fontId);
+ break;
+ case MSG.MSG_DERIVE_FONT:
+ // derive font
+ p2j.fonts.deriveFont(message.font);
+
+ me.sendInt8BinaryMessage(MSG.MSG_DONE_DERIVE_FONT, message.msgId, 1);
+ break;
+ case MSG.MSG_SET_CURSOR_STYLE:
+ // set cursor style
+ p2j.screen.setCursorStyle(message.styleId, message.wid);
+ break;
+ case MSG.MSG_RESTACK_WINDOWS:
+ // restack windows
+ var winidsView = new Int32Array(message.winids);
+ p2j.screen.restackZOrderEntries(winidsView);
+ break;
+ case MSG.PROCESS_MOUSE_WIDGETS:
+ // register/deregister widgets for mouse actions
+ if (!p2j.screen.isExistingWindowId(message.windowID))
+ {
+ console.log("undefined window " + message.windowID);
+ break;
+ }
+ var theWindow = p2j.screen.getWindow(message.windowID);
+ var widgetsView = new Int32Array(message.widgets);
+
+ switch(message.label)
+ {
+ case "registerWidgets":
+ var actionsView = new Int32Array(message.actions);
+ var xCoordsView = new Int16Array(message.xCoords);
+ var yCoordsView = new Int16Array(message.yCoords);
+ var widthsView = new Int16Array(message.widths);
+ var heightsView = new Int16Array(message.heights);
+ for (var k = 0; k < message.widgetNo; k++)
+ {
+ theWindow.deregisterMouseWidget(widgetsView[k]);
+ theWindow.registerMouseWidget(
+ widgetsView[k], xCoordsView[k], yCoordsView[k],
+ widthsView[k], heightsView[k], actionsView[k]);
+ }
+ var zOrderView = new Int32Array(message.zOrder);
+ theWindow.setWidgetZOrder(Array.prototype.slice.call(zOrderView));
+ break;
+ case "registerAnyWidgets":
+ for (var k = 0; k < message.widgetNo; k++)
+ {
+ theWindow.deregisterAnyMouseWidget(widgetsView[k]);
+ theWindow.registerAnyMouseWidget(widgetsView[k]);
+ }
+ break;
+ case "derigisterWidgets":
+ for (var k = 0; k < message.widgetNo; k++)
+ {
+ theWindow.deregisterMouseWidget(widgetsView[k]);
+ }
+ break;
+ case "derigisterAnyWidgets":
+ for (var k = 0; k < message.widgetNo; k++)
+ {
+ theWindow.deregisterAnyMouseWidget(widgetsView[k]);
+ }
+ break;
+ }
+ break;
+ case MSG.CAPTURE_MOUSE:
+ // enable/disable mouse events
+ p2j.screen.captureMouseEvents(message.capture);
+ break;
+ case MSG.ENABLE_OS_EVENTS:
+ // enable/disable OS events
+ p2j.screen.enableOsEvents(message.windowID, message.enable);
+ break;
+ case MSG.SET_ICONIFICATION_STATE:
+ var theWindow = p2j.screen.getWindow(message.windowID);
+ //p2j.logger.log("recieved 0x99: iconified = " + message.iconified + " windowId=" + message.windowID);
+ if (message.iconified)
+ {
+ theWindow.iconify();
+ }
+ else
+ {
+ theWindow.deiconify();
+ }
+ break;
+ case MSG.SET_RESIZEABLE_WINDOW:
+ // resizeable window
+ var theWindow = p2j.screen.getWindow(message.windowID);
+
+ theWindow.resizeable = message.resizeable;
+
+ if (message.resizeable)
+ {
+ theWindow.minWidth = message.minWidth;
+ theWindow.minHeight = message.minHeight;
+ theWindow.maxWidth = message.maxWidth;
+ theWindow.maxHeight = message.maxHeight;
+ }
+ else
+ {
+ var rect = theWindow.canvas.getBoundingClientRect();
+
+ var rwidth = rect.right - rect.left + 1;
+ var rheight = rect.bottom - rect.top + 1;
+
+ theWindow.minWidth = rwidth;
+ theWindow.minHeight = rheight;
+
+ theWindow.maxWidth = rwidth;
+ theWindow.maxHeight = rheight;
+ }
+
+ break;
+ case MSG.MSG_CURRENT_SELECTION:
+ // current editors selection is changed
+ p2j.clipboard.setSelection(message.clipboardText);
+ break;
+ case MSG.MSG_MOVE_TO_TOP:
+ p2j.screen.moveToTop(message.windowID);
+ break;
+ case MSG.MSG_MOVE_TO_BOTTOM:
+ p2j.screen.moveToBottom(message.windowID);
+ break;
+ case MSG.MSG_WINDOW_SENSITIVITY:
+ // change sensitivity for top-level or child window
+ p2j.screen.setWindowEnabled(message.windowID, message.enabled);
+ break;
+ case MSG.MSG_IS_FONT_INSTALLED:
+ // font is installed
+ var result = p2j.fonts.isFontInstalled(message.fontName);
+
+ me.sendInt8BinaryMessage(MSG.MSG_IS_FONT_INSTALLED, message.msgId, result ? 1 : 0);
+ break;
+ case MSG.MSG_REMOVE_EXPIRED_HASH:
+ // remove hashes
+ var theWindow = p2j.screen.getWindow(message.windowID);
+ var hashes = new Uint8Array(message.hashes);
+ var offset = 0;
+ for (var i = 0; i < message.hashNo; i++)
+ {
+ // read each hash and remove it
+ var hashBytes = hashes.slice(offset, offset + 16);
+ var hash = io.createHexString(hashBytes);
+ delete theWindow.removeCachedDraw(hash);
+
+ offset += 16;
+ }
+
+ me.sendInt8BinaryMessage(MSG.MSG_DRAW_HASH_REMOVED, message.msgId, 1);
+ break;
+ };
+ }
/**
* Initialize module.
@@ -454,639 +587,77 @@
me.init = function(cfg)
{
referrer = cfg.referrer;
+
+ webWorker = new Worker("/common/p2j.connector.js");
- if ('WebSocket' in window)
+ /**
+ * Handles messages from the dedicated web worker.
+ *
+ * @param {MessageEvent} evt
+ * The message from the web worker.
+ */
+ var webWorkerHandler = function(evt)
{
- ws = new WebSocket(cfg.socket.url);
-
- // on web socket open
- ws.onopen = function()
- {
- connected = true;
- ws.binaryType = 'arraybuffer';
-
- // notify the web socket has opened and the page is loaded
- me.sendNotification(0xff);
- };
-
- /** Web socket message handler */
- var messageHandler = function(message)
- {
- callNo = callNo + 1;
- console.log(callNo + ": " + message[0].toString(16));
-
- switch (message[0])
- {
- case 0x80:
- // clear screen
- p2j.screen.clear();
- break;
- case 0x81:
- // remove the MD5 code and save it here
- var md5a = new message.constructor(16);
- message = splice(message, 1, 16, md5a);
- var md5 = me.createHexString(md5a);
-
- drawNo = drawNo + 1;
- // draw screen
- var t1 = (new Date()).getTime();
- p2j.screen.drawRectangles(message, md5);
- var t2 = (new Date()).getTime();
- console.log(callNo + ":" + drawNo + " draw: " + message.length + " done in " + (t2 - t1) + " with md5: " + md5);
- break;
- case 0x82:
- // set cursor position
- p2j.screen.setCursorPosition(message[1], message[2]);
- break;
- case 0x83:
- // show cursor
- p2j.screen.setCursorStatus(message[1]);
- break;
- case 0x84:
- // message beep
- p2j.sound.beep();
- break;
- case 0x85:
- // quit
- window.location.replace(referrer);
- break;
- case 0x86:
- // switch mode p2j/vt100
- p2j.keyboard.vt100 = (message[1] == 0) ? false : true;
- break;
- case 0x87:
- // server-driven request for clipboard contents
- p2j.clipboard.sendClipboardContents();
- break;
- case 0x88:
- // The clipboard is changed.
- var text = me.readStringBinaryMessage(message, 1);
- p2j.clipboard.writeClipboard(text);
- break;
- case 0x89:
- // create a top-level window with the given id
- var id = me.readInt32BinaryMessage(message, 1);
- p2j.screen.createWindow(id);
- break;
- case 0x8A:
- // create a child window with the given id, owner and title
- var id = me.readInt32BinaryMessage(message, 1);
- var owner = me.readInt32BinaryMessage(message, 5);
- var title = me.readStringBinaryMessage(message, 9);
- p2j.screen.createChildWindow(id, owner);
- break;
- case 0x8B:
- // destroy top-level or child window
- var id = me.readInt32BinaryMessage(message, 1);
- var numberImages = me.readInt32BinaryMessage(message, 5);
- var images = [];
- for (var i = 0; i < numberImages; i++)
- {
- images[i] = me.readInt32BinaryMessage(message, 9 + (i * 4));
- }
- p2j.screen.destroyWindow(id, images);
- break;
- case 0x8C:
- // change visibility for top-level or child window
- var id = me.readInt32BinaryMessage(message, 1);
- var visible = message[5] === 0 ? false : true;
- p2j.screen.setWindowVisible(id, visible);
- break;
-
- // font and metrics related requests
- case 0x8D:
- // paragraph height
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var textLength = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var text = me.readStringBinaryMessageByLength(message, offset, textLength);
- offset = offset + textLength * 2;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var maxWidth = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- var pheight = p2j.screen.layoutParagraphWorker(null,
- text,
- font,
- 0,
- 0,
- maxWidth);
-
- me.sendInt16BinaryMessage(0x06, msgId, pheight);
- break;
- case 0x8E:
- // text height
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var textLength = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var text = me.readStringBinaryMessageByLength(message, offset, textLength);
- offset = offset + textLength * 2;
-
- var font = me.readInt32BinaryMessage(message, offset);
-
- var theight = p2j.fonts.getTextHeight(font, text);
-
- me.sendInt8BinaryMessage(0x07, msgId, theight);
- break;
- case 0x8F:
- // text width
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var textLength = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var text = me.readStringBinaryMessageByLength(message, offset, textLength);
- offset = offset + textLength * 2;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var twidth = p2j.fonts.getTextWidth(font, text);
-
- me.sendInt16BinaryMessage(0x08, msgId, twidth);
- break;
- case 0x90:
- // font height
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var fheight = p2j.fonts.getFontHeight(font);
-
- me.sendInt8BinaryMessage(0x09, msgId, fheight);
- break;
- case 0x91:
- // font widths
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var fwidths = p2j.fonts.getFontWidths(font);
-
- me.sendByteArrayBinaryMessage(0x0A, msgId, fwidths);
- break;
- case 0x92:
- // create font
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var nameLength = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- var name = me.readStringBinaryMessageByLength(message, offset, nameLength);
- offset = offset + nameLength * 2;
-
- var size = message[offset];
- offset = offset + 1;
-
- var style = message[offset];
- offset = offset + 1;
-
- var defLength = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var b64font = "";
- if (defLength > 0)
- {
- var binFont = '';
- for (var i = 0; i < defLength; i++)
- {
- binFont += String.fromCharCode(message[offset]);
- offset = offset + 1;
- }
- b64font = window.btoa(binFont);
- }
-
- var fontId = p2j.fonts.createFont(font, name, size, style, b64font);
-
- me.sendInt32BinaryMessage(0x0B, msgId, fontId);
- break;
- case 0x93:
- // derive font
-
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var font = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- p2j.fonts.deriveFont(font);
-
- me.sendInt8BinaryMessage(0x0C, msgId, 1);
- break;
- case 0x94:
- // set cursor style
- var styleId = me.readInt32BinaryMessage(message, 1);
- var wid = me.readInt32BinaryMessage(message, 5);
- p2j.screen.setCursorStyle(styleId, wid);
- break;
- case 0x95:
- // restack windows
- var num = me.readInt32BinaryMessage(message, 1);
- var winids = [];
- for (var i = 0; i < num; i++)
- {
- winids.push(me.readInt32BinaryMessage(message, 5 + (i * 4)));
- }
- p2j.screen.restackZOrderEntries(winids);
- break;
- case 0x96:
- // register/deregister widgets for mouse actions
-
- var offset = 1;
-
- // the number of windows with new widgets
- var windowNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var j = 0; j < windowNo; j++)
- {
- // the window ID
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- if (!p2j.screen.isExistingWindowId(windowID))
- {
- console.log("undefined window " + windowID);
- continue;
- }
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- // the number of new widgets in this window
- var widgetNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var k = 0; k < widgetNo; k++)
- {
- // the widget ID
- var wid = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- // the coordinates
- var x = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- var y = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- // the size
- var width = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- var height = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- // bit-encoded mouse ops: each bit from 1 to 11, if set, represents a mouse
- // operation as defined in p2j.screen.mouseOps
- var actions = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
- theWindow.deregisterMouseWidget(wid);
- theWindow.registerMouseWidget(wid, x, y, width, height, actions);
- }
-
- var allWNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
- var zOrder = [];
-
- for (var k = 0; k < allWNo; k++)
- {
- zOrder[k] = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
- }
-
- theWindow.setWidgetZOrder(zOrder);
- }
-
- // the number of windows with dead widgets
- windowNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var j = 0; j < windowNo; j++)
- {
- // the window ID
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- if (theWindow == undefined)
- {
- console.log("undefined window" + windowID);
- continue;
- }
-
- // the number of dead widgets in this window
- var widgetNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var k = 0; k < widgetNo; k++)
- {
- // the widget ID
- var wid = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- theWindow.deregisterMouseWidget(wid);
- }
- }
-
- // the number of windows with new "any widgets"
- windowNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var j = 0; j < windowNo; j++)
- {
- // the window ID
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- if (!p2j.screen.isExistingWindowId(windowID))
- {
- console.log("undefined window " + windowID);
- continue;
- }
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- // the number of new "any widgets" in this window
- var widgetNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var k = 0; k < widgetNo; k++)
- {
- // the widget ID
- var wid = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
- theWindow.deregisterAnyMouseWidget(wid);
- theWindow.registerAnyMouseWidget(wid);
- }
- }
-
- // the number of windows with dead "any widgets"
- windowNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var j = 0; j < windowNo; j++)
- {
- // the window ID
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- if (theWindow == undefined)
- {
- console.log("undefined window" + windowID);
- continue;
- }
-
- // the number of dead "any widgets" in this window
- var widgetNo = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- for (var k = 0; k < widgetNo; k++)
- {
- // the widget ID
- var wid = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- theWindow.deregisterAnyMouseWidget(wid);
- }
- }
-
- break;
- case 0x97:
- // enable/disable mouse events
- p2j.screen.captureMouseEvents(message[1] == 1);
- break;
- case 0x98:
- // enable/disable OS events
- var wid = me.readInt32BinaryMessage(message, 1);
- p2j.screen.enableOsEvents(wid, message[5] == 1);
- break;
- case 0x99:
- // set window iconification state
- var offset = 1;
-
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var iconified = (message[offset] == 1);
- offset = offset + 1;
-
- var theWindow = p2j.screen.getWindow(windowID);
- //p2j.logger.log("recieved 0x99: iconified = " + iconified + " windowId=" + windowID);
- if (iconified)
- {
- theWindow.iconify();
- }
- else
- {
- theWindow.deiconify();
- }
-
- break;
- case 0x9A:
- // resizeable window
- var offset = 1;
-
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- theWindow.resizeable = (message[offset] == 1);
- offset = offset + 1;
-
- if (theWindow.resizeable)
- {
- theWindow.minWidth = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
- theWindow.minHeight = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
-
- theWindow.maxWidth = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
- theWindow.maxHeight = me.readInt16BinaryMessage(message, offset);
- offset = offset + 2;
- }
- else
- {
- var rect = theWindow.canvas.getBoundingClientRect();
-
- var rwidth = rect.right - rect.left + 1;
- var rheight = rect.bottom - rect.top + 1;
-
- theWindow.minWidth = rwidth;
- theWindow.minHeight = rheight;
-
- theWindow.maxWidth = rwidth;
- theWindow.maxHeight = rheight;
- }
-
- break;
- case 0x9B:
- // current editors selection is changed
- var text = me.readStringBinaryMessage(message, 1);
- p2j.clipboard.setSelection(text);
- break;
- case 0x9C:
- var id = me.readInt32BinaryMessage(message, 1);
- p2j.screen.moveToTop(id);
- break;
- case 0x9D:
- var id = me.readInt32BinaryMessage(message, 1);
- p2j.screen.moveToBottom(id);
- break;
- case 0x9E:
- // change sensitivity for top-level or child window
- var id = me.readInt32BinaryMessage(message, 1);
- var enabled = message[5] === 0 ? false : true;
- p2j.screen.setWindowEnabled(id, enabled);
- break;
- case 0x9F:
- // font is installed
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var fontNameLength = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var fontName = me.readStringBinaryMessageByLength(message, offset, fontNameLength);
-
- var result = p2j.fonts.isFontInstalled(fontName);
-
- me.sendInt8BinaryMessage(0x9F, msgId, result ? 1 : 0);
- break;
- case 0xA0:
- // remove hashes
- var offset = 1;
-
- var msgId = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- // window ID
- var windowID = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- // number of hashes
- var hashNo = me.readInt32BinaryMessage(message, offset);
- offset = offset + 4;
-
- var theWindow = p2j.screen.getWindow(windowID);
-
- for (var i = 0; i < hashNo; i++)
- {
- // read each hash and remove it
- var hashBytes = message.slice(offset, offset + 16);
- var hash = me.createHexString(hashBytes);
- delete theWindow.removeCachedDraw(hash);
-
- offset += 16;
- }
-
- me.sendInt8BinaryMessage(0x12, msgId, 1);
- break;
- };
- };
- // on web socket message
- ws.onmessage = function(evt)
- {
- var data = evt.data;
-
- if (data instanceof ArrayBuffer)
- {
- // binary messages
- var message = new Uint8Array(data);
- var isDrawing = message[0] === 0x81;
- if (isDrawing)
- {
- p2j.displayWaitCursor();
- }
- setTimeout(function() { messageHandler(message); }, 1);
- if (isDrawing)
- {
- setTimeout(function() { p2j.restoreCursor(); }, 1);
- }
- }
- else
- {
- // text messages
- var pay = JSON.parse(data);
+ var data = evt.data;
+ switch(data.type)
+ {
+ case MSG.MSG_WEB_SOCKET_ERROR:
+ p2j.screen.error('WebSockets are NOT supported by your Browser.');
+ webWorker.terminate();
+ break;
+ case MSG.MSG_COLOR_PALETTE:
setTimeout(
function()
{
- switch (pay.c)
+ switch (data.msg.c)
{
case 0:
// color palette
- p2j.screen.palette = pay.p;
+ p2j.screen.palette = data.msg.p;
break;
};
}, 1);
- }
+ break;
+ case MSG.MSG_WEB_SOCKET_OPEN:
+ // on web socket open
+ connected = true;
+ webWorker.postMessage({type: MSG.MSG_PAGE_LOADED});
+ break;
+ case MSG.MSG_WEB_SOCKET_CLOSE:
+ // on web socket close
+ connected = false;
+ p2j.screen.error('Connection closed by remote host.');
+ window.setInterval(function() { window.location.replace(referrer); }, 5000);
+ break;
+ case MSG.MSG_DRAW:
+ p2j.displayWaitCursor();
+ setTimeout(
+ function()
+ {
+ messageHandler(data);
+ }, 1);
+ setTimeout(function() { p2j.restoreCursor(); }, 1);
+ break;
+ default:
+ setTimeout(
+ function()
+ {
+ messageHandler(data);
+ }, 1);
}
-
- // on web socket close
- ws.onclose = function()
- {
- connected = false;
- p2j.screen.error('Connection closed by remote host.');
- window.setInterval(function() { window.location.replace(referrer); }, 5000);
- };
-
- // refresh
- window.onpagehide = function()
- {
- if (connected)
- {
- ws.close();
- }
- };
- }
- else
+ };
+
+ /** Added the web worker message listener */
+ webWorker.addEventListener("message", webWorkerHandler);
+
+ // Directs the web worker to open a web socket connection
+ webWorker.postMessage({type: MSG.MSG_WEB_SOCKET_OPEN, url : cfg.socket.url});
+
+ // refresh
+ window.onpagehide = function()
{
- p2j.screen.error('WebSockets are NOT supported by your Browser.');
- }
+ webWorker.postMessage({type: MSG.MSG_WEB_SOCKET_CLOSE});
+ };
};
/**
@@ -1099,15 +670,7 @@
*/
me.hexStringToBytes = function(str)
{
- var bytes = new Uint8Array(str.length / 2);
-
- var idx = 0;
- for (var c = 0, idx = 0; c < str.length; c += 2, idx++)
- {
- bytes[idx] = parseInt(str.substr(c, 2), 16);
- }
-
- return bytes;
+ return io.hexStringToBytes(str);
}
/**
@@ -1120,55 +683,8 @@
*/
me.createHexString = function(arr)
{
- var result = "";
- for (var i in arr)
- {
- var str = arr[i].toString(16);
- str = str.length == 0 ? "00" :
- str.length == 1 ? "0" + str :
- str.length == 2 ? str :
- str.substring(str.length-2, str.length);
-
- result += str;
- }
-
- return result;
+ return io.createHexString(arr);
}
- /**
- * Remove the sub-array from the given array and save it in the splice parameter.
- *
- * @param {array} arr
- * The byte array from where elements are removed.
- * @param {int} starting
- * The starting position (inclusive).
- * @param {int} deleteCount
- * The number of elements to delete.
- * @param {array} splice
- * The array where to save the elements (must have enough space).
- *
- * @return The original array with the elements removed.
- */
- function splice(arr, starting, deleteCount, splice)
- {
- if (arguments.length === 1)
- {
- return arr;
- }
-
- starting = Math.max(starting, 0);
- deleteCount = Math.max(deleteCount, 0);
-
- const newSize = arr.length - deleteCount;
- const splicedArray = new arr.constructor(newSize);
-
- splicedArray.set(arr.subarray(0, starting));
- splicedArray.set(arr.subarray(starting + deleteCount), starting);
-
- splice.set(arr.subarray(starting, starting + deleteCount));
-
- return splicedArray;
- };
-
return me;
}());