diff --git a/RemoteDesktop/README.md b/RemoteDesktop/README.md
index 4ef2bf5..bcfc2f0 100644
--- a/RemoteDesktop/README.md
+++ b/RemoteDesktop/README.md
@@ -5,11 +5,8 @@ A web based VNC client allowing to control remote VNC desktop from browser. The
Further information on **wvnc**: [https://blog.lxsang.me/post/id/23](https://blog.lxsang.me/post/id/23)
-**Credit**
-* antd-wvnc-plugin: [https://github.com/lxsang/antd-wvnc-plugin](https://github.com/lxsang/antd-wvnc-plugin)
-* wvnc.js: [https://github.com/lxsang/wvnc.js](https://github.com/lxsang/wvnc.js)
-*
## Change logs
+* v0.1.5 - add package dependencies and use the new **libwvnc**
* v0.1.0 - adapt to the new AntOS API
\ No newline at end of file
diff --git a/RemoteDesktop/build/debug/README.md b/RemoteDesktop/build/debug/README.md
index 4ef2bf5..bcfc2f0 100644
--- a/RemoteDesktop/build/debug/README.md
+++ b/RemoteDesktop/build/debug/README.md
@@ -5,11 +5,8 @@ A web based VNC client allowing to control remote VNC desktop from browser. The
Further information on **wvnc**: [https://blog.lxsang.me/post/id/23](https://blog.lxsang.me/post/id/23)
-**Credit**
-* antd-wvnc-plugin: [https://github.com/lxsang/antd-wvnc-plugin](https://github.com/lxsang/antd-wvnc-plugin)
-* wvnc.js: [https://github.com/lxsang/wvnc.js](https://github.com/lxsang/wvnc.js)
-*
## Change logs
+* v0.1.5 - add package dependencies and use the new **libwvnc**
* v0.1.0 - adapt to the new AntOS API
\ No newline at end of file
diff --git a/RemoteDesktop/build/debug/main.js b/RemoteDesktop/build/debug/main.js
index 8263c4a..a6e0383 100644
--- a/RemoteDesktop/build/debug/main.js
+++ b/RemoteDesktop/build/debug/main.js
@@ -1 +1 @@
-(function(){var t,e,n;(t=class t extends this.OS.GUI.BasicDialog{constructor(){super("ConnectionDialog",t.scheme)}main(){return super.main(),this.find("bbp").data=[{text:"16 bits",value:16,selected:!0},{text:"32 bits",value:32}],this.find("compression").data=[{text:"No compression",value:0},{text:"JPEG",value:1},{text:"zLib",value:2},{text:"JPEG & zLib",value:3,selected:!0}],this.find("jq").value=40,this.find("bt-ok").onbtclick=t=>{var e;if(this.handle)return e={wvnc:this.find("txtWVNC").value,server:this.find("txtServer").value,bbp:this.find("bbp").selectedItem.data.value,flag:this.find("compression").selectedItem.data.value,quality:this.find("jq").value},this.handle(e),this.quit()},this.find("bt-cancel").onbtclick=t=>this.quit()}}).scheme='\n \n
\n \n \n \n \n \n
\n \n \n
\n \n \n
\n \n \n \n \n
\n \n \n
\n \n \n',(e=class t extends this.OS.GUI.BasicDialog{constructor(){super("CredentialDialog",t.scheme)}main(){return this.find("bt-ok").onbtclick=()=>{var t;return this.handle?(t={username:this.find("txtUser").value,password:this.find("txtPass").value},this.handle(t),this.quit()):this.quit()},this.find("bt-cancel").onbtclick=()=>this.quit()}}).scheme='\n \n \n \n \n \n \n \n
\n \n \n \n',n=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteDesktop",t)}main(){return this.canvas=this.find("screen"),this.container=this.find("container"),this.client=new WVNC({element:this.canvas,worker:`${this._api.handle.get}/${this.meta().path}/decoder.js`}),this.client.onerror=t=>(this.error(t),this.showConnectionDialog()),this.client.onresize=()=>this.setScale(),this.client.onpassword=()=>new Promise((t,e)=>this.openDialog("PromptDialog",{title:__("VNC password"),label:__("VNC password"),value:"!x$@n9ph",type:"password"}).then((function(e){return t(e)}))),this.client.oncredential=()=>new Promise((t,n)=>this.openDialog(new e,{title:__("User credential")}).then((function(e){return t(e.username,e.password)}))),this.on("resize",t=>this.setScale()),this.on("focus",t=>$(this.canvas).focus()),this.client.init().then(()=>this.showConnectionDialog())}setScale(){var t,e,n,a;if(this.client&&this.client.resolution)return a=$(this.container).width(),t=$(this.container).height(),(e=a/this.client.resolution.w)>(n=t/this.client.resolution.h)?this.client.setScale(n):this.client.setScale(e)}menu(){return[{text:"__(Connection)",nodes:[{text:"__(New Connection)",dataid:this.name+"-new"},{text:"__(Disconnect)",dataid:this.name+"-close"}],onchildselect:t=>this.actionConnection()}]}actionConnection(t){return this.client&&this.client.disconnect(),this.showConnectionDialog()}showConnectionDialog(){return this.openDialog(new t,{title:__("Connection")}).then(t=>(this.client.ws=t.wvnc,console.log(t),this.client.connect(t.server,t)))}cleanup(){if(this.client)return this.client.disconnect()}},this.OS.register("RemoteDesktop",n)}).call(this),function(){var t;t=function(){function t(t){var e,n;this.socket=void 0,this.ws=void 0,this.canvas=void 0,n="decoder.js",this.scale=1,t.ws&&(this.ws=t.ws),this.canvas=t.element,"string"==typeof this.canvas&&(this.canvas=document.getElementById(this.canvas)),t.worker&&(n=t.worker),this.decoder=new Worker(n),this.enableEvent=!0,(e=this).mouseMask=0,this.decoder.onmessage=function(t){return e.process(t.data)}}return t.prototype.init=function(){var t;return t=this,new Promise((function(e,n){return t.canvas?($(t.canvas).attr("tabindex","1"),t.initInputEvent(),e()):n("Canvas is not set")}))},t.prototype.initInputEvent=function(){var t,e,n,a;if((n=this).canvas&&(e=function(t){var e;return e=n.canvas.getBoundingClientRect(),{x:Math.floor((t.clientX-e.left)/n.scale),y:Math.floor((t.clientY-e.top)/n.scale)}},a=function(t){var a;if(n.enableEvent)return a=e(t),n.sendPointEvent(a.x,a.y,n.mouseMask)},n.canvas))return n.canvas.oncontextmenu=function(t){return t.preventDefault(),!1},n.canvas.onmousemove=function(t){return a(t)},n.canvas.onmousedown=function(t){var e;return e=1<>8,a[2]=255&e,a[3]=e>>8,a[4]=n,this.socket.send(this.buildCommand(5,a))},t.prototype.sendKeyEvent=function(t,e){var n;if(this.socket&&this.enableEvent)return(n=new Uint8Array(3))[0]=255&t,n[1]=t>>8,n[2]=e,this.socket.send(this.buildCommand(6,n))},t.prototype.buildCommand=function(t,e){var n,a;switch(a=void 0,typeof e){case"string":a=(new TextEncoder).encode(e);break;case"number":a=new Uint8Array([e]);break;default:a=e}return(n=new Uint8Array(a.length+3))[0]=t,n[2]=a.length>>8,n[1]=15&a.length,n.set(a,3),n.buffer},t.prototype.oncopy=function(t){return console.log("Get clipboard text: "+t)},t.prototype.onpassword=function(){return new Promise((function(t,e){return e("onpassword is not implemented")}))},t.prototype.sendTextAsClipboard=function(t){if(this.socket)return console.log("send ",t),this.socket.send(this.buildCommand(7,t))},t.prototype.oncredential=function(){return new Promise((function(t,e){return e("oncredential is not implemented")}))},t.prototype.onerror=function(t){return console.log("Error",t)},t.prototype.onresize=function(){return console.log("resize")},t.prototype.consume=function(t){var e,n,a,i,s,o,r;switch(e=(n=new Uint8Array(t.data))[0],o=this,e){case 254:return n=n.subarray(1,n.length-1),a=new TextDecoder("utf-8"),this.onerror(a.decode(n));case 129:return console.log("Request for password"),this.enableEvent=!1,this.onpassword().then((function(t){return o.socket.send(o.buildCommand(2,t)),o.enableEvent=!0}));case 130:return console.log("Request for login"),this.enableEvent=!1,this.oncredential().then((function(t,e){var n;return(n=new Uint8Array(t.length+e.length+1)).set((new TextEncoder).encode(t),0),n.set(["\0"],t.length),n.set((new TextEncoder).encode(e),t.length+1),o.socket.send(o.buildCommand(3,n)),o.enableEvent=!0}));case 131:return r=n[1]|n[2]<<8,s=n[3]|n[4]<<8,i=n[5],this.initCanvas(r,s,i),this.socket.send(this.buildCommand(4,1)),this.onresize();case 132:return this.decoder.postMessage(n.buffer,[n.buffer]);case 133:return n=n.subarray(1),a=new TextDecoder("utf-8"),this.oncopy(a.decode(n)),this.socket.send(this.buildCommand(4,1));default:return console.log(e)}},t}(),window.WVNC=t}.call(this);
\ No newline at end of file
+(function(){var t,e,i;(t=class t extends this.OS.GUI.BasicDialog{constructor(){super("ConnectionDialog",t.scheme)}main(){return super.main(),this.find("bbp").data=[{text:"16 bits",value:16,selected:!0},{text:"32 bits",value:32}],this.find("compression").data=[{text:"No compression",value:0},{text:"JPEG",value:1,selected:!0}],this.find("jq").value=40,this.find("bt-ok").onbtclick=t=>{var e;if(this.handle)return e={wvnc:this.find("txtWVNC").value,server:this.find("txtServer").value,bbp:this.find("bbp").selectedItem.data.value,flag:this.find("compression").selectedItem.data.value,quality:this.find("jq").value},this.handle(e),this.quit()},this.find("bt-cancel").onbtclick=t=>this.quit()}}).scheme='\n \n
\n \n \n \n \n \n
\n \n \n
\n \n \n
\n \n \n \n \n
\n \n \n
\n \n \n',(e=class t extends this.OS.GUI.BasicDialog{constructor(){super("CredentialDialog",t.scheme)}main(){return this.find("bt-ok").onbtclick=()=>{var t;return this.handle?(t={username:this.find("txtUser").value,password:this.find("txtPass").value},this.handle(t),this.quit()):this.quit()},this.find("bt-cancel").onbtclick=()=>this.quit()}}).scheme='\n \n \n \n \n \n \n \n
\n \n \n \n',(i=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteDesktop",t)}main(){return this.canvas=this.find("screen"),this.container=this.find("container"),this.client=new WVNC({element:this.canvas,libjpeg:"pkg://libjpeg/jpg.js".asFileHandle().getlink()}),this.client.onerror=t=>(this.error(t),this.showConnectionDialog()),this.client.onresize=()=>this.setScale(),this.client.onpassword=()=>new Promise((t,e)=>this.openDialog("PromptDialog",{title:__("VNC password"),label:__("VNC password"),value:"password",type:"password"}).then((function(e){return t(e)}))),this.client.oncredential=()=>new Promise((t,i)=>this.openDialog(new e,{title:__("User credential")}).then((function(e){return t(e.username,e.password)}))),this.on("resize",t=>this.setScale()),this.on("focus",t=>$(this.canvas).focus()),this.client.init().then(()=>this.showConnectionDialog())}setScale(){var t,e,i,a;if(this.client&&this.client.resolution)return a=$(this.container).width(),t=$(this.container).height(),(e=a/this.client.resolution.w)>(i=t/this.client.resolution.h)?this.client.setScale(i):this.client.setScale(e)}menu(){return[{text:"__(Connection)",nodes:[{text:"__(New Connection)",dataid:this.name+"-new"},{text:"__(Disconnect)",dataid:this.name+"-close"}],onchildselect:t=>this.actionConnection()}]}actionConnection(t){return this.client&&this.client.disconnect(!1),this.showConnectionDialog()}showConnectionDialog(){return this.openDialog(new t,{title:__("Connection")}).then(t=>(this.client.ws=t.wvnc,this.client.connect(t.server,t)))}cleanup(){if(this.client)return this.client.disconnect(!0)}}).dependencies=["pkg://libwvnc/main.js"],this.OS.register("RemoteDesktop",i)}).call(this);
\ No newline at end of file
diff --git a/RemoteDesktop/build/debug/package.json b/RemoteDesktop/build/debug/package.json
index 7c7db2d..5422089 100644
--- a/RemoteDesktop/build/debug/package.json
+++ b/RemoteDesktop/build/debug/package.json
@@ -6,7 +6,8 @@
"author": "",
"email": ""
},
- "version":"0.1.0-a",
+ "version":"0.1.5-a",
+ "dependencies": ["libwvnc@0.1.2-a"],
"category":"Other",
"icon": "icon.png",
"mimes":["none"]
diff --git a/RemoteDesktop/build/release/RemoteDesktop.zip b/RemoteDesktop/build/release/RemoteDesktop.zip
index 8fa829a..c903c36 100644
Binary files a/RemoteDesktop/build/release/RemoteDesktop.zip and b/RemoteDesktop/build/release/RemoteDesktop.zip differ
diff --git a/RemoteDesktop/coffees/main.coffee b/RemoteDesktop/coffees/main.coffee
index 9d6dd67..098ce5f 100644
--- a/RemoteDesktop/coffees/main.coffee
+++ b/RemoteDesktop/coffees/main.coffee
@@ -6,14 +6,12 @@ class ConnectionDialog extends this.OS.GUI.BasicDialog
main: () ->
super.main()
@find("bbp").data = [
- { text: "16 bits", value: 16, selected: true },
+ { text: "16 bits", value: 16, selected: true },
{ text: "32 bits", value: 32 }
]
@find("compression").data = [
{text: "No compression", value:0},
- {text: "JPEG", value:1},
- {text: "zLib", value:2},
- {text: "JPEG & zLib", value:3, selected:true}
+ {text: "JPEG", value:1, selected: true}
]
@find("jq").value = 40
@find("bt-ok").onbtclick = (e) =>
@@ -38,7 +36,7 @@ ConnectionDialog.scheme = """
-
+
@@ -106,7 +104,7 @@ class RemoteDesktop extends this.OS.application.BaseApplication
@container = @find "container"
@client = new WVNC {
element: @canvas,
- worker: "#{@_api.handle.get}/#{@meta().path}/decoder.js"
+ libjpeg: "pkg://libjpeg/jpg.js".asFileHandle().getlink()
}
@client.onerror = (m) =>
@error m
@@ -118,7 +116,7 @@ class RemoteDesktop extends this.OS.application.BaseApplication
@openDialog "PromptDialog", {
title: __("VNC password"),
label: __("VNC password"),
- value: "!x$@n9ph",
+ value: "password",
type: "password"
}
.then (d) ->
@@ -156,7 +154,7 @@ class RemoteDesktop extends this.OS.application.BaseApplication
]
actionConnection: (e) ->
- @client.disconnect() if @client
+ @client.disconnect(false) if @client
@showConnectionDialog()
showConnectionDialog: () ->
@@ -164,11 +162,12 @@ class RemoteDesktop extends this.OS.application.BaseApplication
@openDialog new ConnectionDialog, { title: __("Connection")}
.then (d) =>
@client.ws = d.wvnc
- console.log d
@client.connect d.server, d
cleanup: () ->
- @client.disconnect() if @client
-
-
+ @client.disconnect(true) if @client
+
+RemoteDesktop.dependencies = [
+ "pkg://libwvnc/main.js"
+]
this.OS.register "RemoteDesktop", RemoteDesktop
\ No newline at end of file
diff --git a/RemoteDesktop/javascripts/decoder.js b/RemoteDesktop/javascripts/decoder.js
deleted file mode 100644
index e60e095..0000000
--- a/RemoteDesktop/javascripts/decoder.js
+++ /dev/null
@@ -1 +0,0 @@
-var api,onmessage,resolution,wasm_update;importScripts("wvnc_asm.js"),api={},resolution=void 0,Module.onRuntimeInitialized=function(){return api={createBuffer:Module.cwrap("create_buffer","number",["number","number"]),destroyBuffer:Module.cwrap("destroy_buffer","",["number"]),updateBuffer:Module.cwrap("update","number",["number","number","number","number","number","number"]),decodeBuffer:Module.cwrap("decode","number",["number","number","number","number"])}},wasm_update=function(e){var r,u,n,t,a,o,d,f,i,s,m;if(s=(r=new Uint8Array(e))[1]|r[2]<<8,m=r[3]|r[4]<<8,i=r[5]|r[6]<<8,t=r[7]|r[8]<<8,n=r[9],a=api.createBuffer(r.length),Module.HEAP8.set(r,a),d=i*t*4,o=api.decodeBuffer(a,r.length,resolution.depth,d),u=new Uint8Array(Module.HEAP8.buffer,o,d),e={},(f=new Uint8Array(d)).set(u,0),e.pixels=f.buffer,e.x=s,e.y=m,e.w=i,e.h=t,postMessage(e,[e.pixels]),api.destroyBuffer(a),0!==n||32!==resolution.depth)return api.destroyBuffer(o)},onmessage=function(e){return e.data.depth?resolution=e.data:wasm_update(e.data)};
diff --git a/RemoteDesktop/javascripts/wvnc.js b/RemoteDesktop/javascripts/wvnc.js
deleted file mode 100644
index 6903e09..0000000
--- a/RemoteDesktop/javascripts/wvnc.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(){var e;e=function(){function e(e){var t,n;this.socket=void 0,this.ws=void 0,this.canvas=void 0,n="decoder.js",this.scale=1,e.ws&&(this.ws=e.ws),this.canvas=e.element,"string"==typeof this.canvas&&(this.canvas=document.getElementById(this.canvas)),e.worker&&(n=e.worker),this.decoder=new Worker(n),this.enableEvent=!0,(t=this).mouseMask=0,this.decoder.onmessage=function(e){return t.process(e.data)}}return e.prototype.init=function(){var n;return n=this,new Promise(function(e,t){return n.canvas?($(n.canvas).attr("tabindex","1"),n.initInputEvent(),e()):t("Canvas is not set")})},e.prototype.initInputEvent=function(){var e,n,o,s;if((o=this).canvas&&(n=function(e){var t;return t=o.canvas.getBoundingClientRect(),{x:Math.floor((e.clientX-t.left)/o.scale),y:Math.floor((e.clientY-t.top)/o.scale)}},s=function(e){var t;if(o.enableEvent)return t=n(e),o.sendPointEvent(t.x,t.y,o.mouseMask)},o.canvas))return o.canvas.oncontextmenu=function(e){return e.preventDefault(),!1},o.canvas.onmousemove=function(e){return s(e)},o.canvas.onmousedown=function(e){var t;return t=1<>8,o[2]=255&t,o[3]=t>>8,o[4]=n,this.socket.send(this.buildCommand(5,o))},e.prototype.sendKeyEvent=function(e,t){var n;if(this.socket&&this.enableEvent)return(n=new Uint8Array(3))[0]=255&e,n[1]=e>>8,n[2]=t,this.socket.send(this.buildCommand(6,n))},e.prototype.buildCommand=function(e,t){var n,o;switch(o=void 0,typeof t){case"string":o=(new TextEncoder).encode(t);break;case"number":o=new Uint8Array([t]);break;default:o=t}return(n=new Uint8Array(o.length+3))[0]=e,n[2]=o.length>>8,n[1]=15&o.length,n.set(o,3),n.buffer},e.prototype.oncopy=function(e){return console.log("Get clipboard text: "+e)},e.prototype.onpassword=function(){return new Promise(function(e,t){return t("onpassword is not implemented")})},e.prototype.sendTextAsClipboard=function(e){if(this.socket)return console.log("send ",e),this.socket.send(this.buildCommand(7,e))},e.prototype.oncredential=function(){return new Promise(function(e,t){return t("oncredential is not implemented")})},e.prototype.onerror=function(e){return console.log("Error",e)},e.prototype.onresize=function(){return console.log("resize")},e.prototype.consume=function(e){var t,n,o,s,a,r,i;switch(t=(n=new Uint8Array(e.data))[0],r=this,t){case 254:return n=n.subarray(1,n.length-1),o=new TextDecoder("utf-8"),this.onerror(o.decode(n));case 129:return console.log("Request for password"),this.enableEvent=!1,this.onpassword().then(function(e){return r.socket.send(r.buildCommand(2,e)),r.enableEvent=!0});case 130:return console.log("Request for login"),this.enableEvent=!1,this.oncredential().then(function(e,t){var n;return(n=new Uint8Array(e.length+t.length+1)).set((new TextEncoder).encode(e),0),n.set(["\0"],e.length),n.set((new TextEncoder).encode(t),e.length+1),r.socket.send(r.buildCommand(3,n)),r.enableEvent=!0});case 131:return i=n[1]|n[2]<<8,a=n[3]|n[4]<<8,s=n[5],this.initCanvas(i,a,s),this.socket.send(this.buildCommand(4,1)),this.onresize();case 132:return this.decoder.postMessage(n.buffer,[n.buffer]);case 133:return n=n.subarray(1),o=new TextDecoder("utf-8"),this.oncopy(o.decode(n)),this.socket.send(this.buildCommand(4,1));default:return console.log(t)}},e}(),window.WVNC=e}).call(this);
\ No newline at end of file
diff --git a/RemoteDesktop/javascripts/wvnc_asm.js b/RemoteDesktop/javascripts/wvnc_asm.js
deleted file mode 100644
index d257dac..0000000
--- a/RemoteDesktop/javascripts/wvnc_asm.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}Module["arguments"]=[];Module["thisProgram"]="./this.program";Module["quit"]=(function(status,toThrow){throw toThrow});Module["preRun"]=[];Module["postRun"]=[];var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}else{return scriptDirectory+path}}if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;Module["read"]=function shell_read(filename,binary){var ret;if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));process["on"]("unhandledRejection",(function(reason,p){process["exit"](1)}));Module["quit"]=(function(status){process["exit"](status)});Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){Module["read"]=function shell_read(f){return read(f)}}Module["readBinary"]=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof quit==="function"){Module["quit"]=(function(status){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WEB){if(document.currentScript){scriptDirectory=document.currentScript.src}}else{scriptDirectory=self.location.href}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}Module["read"]=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){Module["readBinary"]=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)};Module["setWindowTitle"]=(function(title){document.title=title})}else{}var out=Module["print"]||(typeof console!=="undefined"?console.log.bind(console):typeof print!=="undefined"?print:null);var err=Module["printErr"]||(typeof printErr!=="undefined"?printErr:typeof console!=="undefined"&&console.warn.bind(console)||out);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var STACK_ALIGN=16;function staticAlloc(size){var ret=STATICTOP;STATICTOP=STATICTOP+size+15&-16;return ret}function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;var ret=size=Math.ceil(size/factor)*factor;return ret}var asm2wasmImports={"f64-rem":(function(x,y){return x%y}),"debugger":(function(){debugger})};var functionPointers=new Array(0);var GLOBAL_BASE=1024;var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}var JSfuncs={"stackSave":(function(){stackSave()}),"stackRestore":(function(){stackRestore()}),"arrayToC":(function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};function ccall(ident,returnType,argTypes,args,opts){function convertReturnValue(ret){if(returnType==="string")return Pointer_stringify(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return UTF8ToString(ptr)}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}var WASM_PAGE_SIZE=65536;var ASMJS_PAGE_SIZE=16777216;var MIN_TOTAL_MEMORY=16777216;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBuffer(buf){Module["buffer"]=buffer=buf}function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+TOTAL_MEMORY+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")}if(!Module["reallocBuffer"])Module["reallocBuffer"]=(function(size){var ret;try{var oldHEAP8=HEAP8;ret=new ArrayBuffer(size);var temp=new Int8Array(ret);temp.set(oldHEAP8)}catch(e){return false}var success=_emscripten_replace_memory(ret);if(!success)return false;return ret});function enlargeMemory(){var PAGE_MULTIPLE=Module["usingWasm"]?WASM_PAGE_SIZE:ASMJS_PAGE_SIZE;var LIMIT=2147483648-PAGE_MULTIPLE;if(HEAP32[DYNAMICTOP_PTR>>2]>LIMIT){return false}var OLD_TOTAL_MEMORY=TOTAL_MEMORY;TOTAL_MEMORY=Math.max(TOTAL_MEMORY,MIN_TOTAL_MEMORY);while(TOTAL_MEMORY>2]){if(TOTAL_MEMORY<=536870912){TOTAL_MEMORY=alignUp(2*TOTAL_MEMORY,PAGE_MULTIPLE)}else{TOTAL_MEMORY=Math.min(alignUp((3*TOTAL_MEMORY+2147483648)/4,PAGE_MULTIPLE),LIMIT)}}var replacement=Module["reallocBuffer"](TOTAL_MEMORY);if(!replacement||replacement.byteLength!=TOTAL_MEMORY){TOTAL_MEMORY=OLD_TOTAL_MEMORY;return false}updateGlobalBuffer(replacement);updateGlobalBufferViews();return true}var byteLength;try{byteLength=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get);byteLength(new ArrayBuffer(4))}catch(e){byteLength=(function(buffer){return buffer.byteLength})}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(TOTAL_MEMORY0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}function integrateWasmJS(){var wasmTextFile="wvnc_asm.wast";var wasmBinaryFile="wvnc_asm.wasm";var asmjsCodeFile="wvnc_asm.temp.asm.js";if(!isDataURI(wasmTextFile)){wasmTextFile=locateFile(wasmTextFile)}if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}if(!isDataURI(asmjsCodeFile)){asmjsCodeFile=locateFile(asmjsCodeFile)}var wasmPageSize=64*1024;var info={"global":null,"env":null,"asm2wasm":asm2wasmImports,"parent":Module};var exports=null;function mergeMemory(newBuffer){var oldBuffer=Module["buffer"];if(newBuffer.byteLength>2]=poolPtr;HEAP32[environ>>2]=envPtr}else{envPtr=HEAP32[environ>>2];poolPtr=HEAP32[envPtr>>2]}var strings=[];var totalSize=0;for(var key in ENV){if(typeof ENV[key]==="string"){var line=key+"="+ENV[key];strings.push(line);totalSize+=line.length}}if(totalSize>TOTAL_ENV_SIZE){throw new Error("Environment size exceeded TOTAL_ENV_SIZE!")}var ptrSize=4;for(var i=0;i>2]=poolPtr;poolPtr+=line.length+1}HEAP32[envPtr+strings.length*ptrSize>>2]=0}var SYSCALLS={varargs:0,get:(function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret}),getStr:(function(){var ret=Pointer_stringify(SYSCALLS.get());return ret}),get64:(function(){var low=SYSCALLS.get(),high=SYSCALLS.get();if(low>=0)assert(high===0);else assert(high===-1);return low}),getZero:(function(){assert(SYSCALLS.get()===0)})};function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var offset=offset_low;FS.llseek(stream,offset,whence);HEAP32[result>>2]=stream.position;if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall146(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.get(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();var ret=0;if(!___syscall146.buffers){___syscall146.buffers=[null,[],[]];___syscall146.printChar=(function(stream,curr){var buffer=___syscall146.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}})}for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=value;return value}DYNAMICTOP_PTR=staticAlloc(4);STACK_BASE=STACKTOP=alignMemory(STATICTOP);STACK_MAX=STACK_BASE+TOTAL_STACK;DYNAMIC_BASE=alignMemory(STACK_MAX);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;staticSealed=true;Module["wasmTableSize"]=212;Module["wasmMaxTableSize"]=212;Module.asmGlobalArg={};Module.asmLibraryArg={"abort":abort,"enlargeMemory":enlargeMemory,"getTotalMemory":getTotalMemory,"abortOnCannotGrowMemory":abortOnCannotGrowMemory,"___buildEnvironment":___buildEnvironment,"___setErrNo":___setErrNo,"___syscall140":___syscall140,"___syscall146":___syscall146,"___syscall54":___syscall54,"___syscall6":___syscall6,"_emscripten_memcpy_big":_emscripten_memcpy_big,"_exit":_exit,"_getenv":_getenv,"DYNAMICTOP_PTR":DYNAMICTOP_PTR,"STACKTOP":STACKTOP};var asm=Module["asm"](Module.asmGlobalArg,Module.asmLibraryArg,buffer);Module["asm"]=asm;var ___emscripten_environ_constructor=Module["___emscripten_environ_constructor"]=(function(){return Module["asm"]["___emscripten_environ_constructor"].apply(null,arguments)});var ___errno_location=Module["___errno_location"]=(function(){return Module["asm"]["___errno_location"].apply(null,arguments)});var _create_buffer=Module["_create_buffer"]=(function(){return Module["asm"]["_create_buffer"].apply(null,arguments)});var _decode=Module["_decode"]=(function(){return Module["asm"]["_decode"].apply(null,arguments)});var _destroy_buffer=Module["_destroy_buffer"]=(function(){return Module["asm"]["_destroy_buffer"].apply(null,arguments)});var _emscripten_replace_memory=Module["_emscripten_replace_memory"]=(function(){return Module["asm"]["_emscripten_replace_memory"].apply(null,arguments)});var _free=Module["_free"]=(function(){return Module["asm"]["_free"].apply(null,arguments)});var _malloc=Module["_malloc"]=(function(){return Module["asm"]["_malloc"].apply(null,arguments)});var _update=Module["_update"]=(function(){return Module["asm"]["_update"].apply(null,arguments)});var stackAlloc=Module["stackAlloc"]=(function(){return Module["asm"]["stackAlloc"].apply(null,arguments)});var stackRestore=Module["stackRestore"]=(function(){return Module["asm"]["stackRestore"].apply(null,arguments)});var stackSave=Module["stackSave"]=(function(){return Module["asm"]["stackSave"].apply(null,arguments)});var dynCall_vi=Module["dynCall_vi"]=(function(){return Module["asm"]["dynCall_vi"].apply(null,arguments)});Module["asm"]=asm;Module["cwrap"]=cwrap;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}ExitStatus.prototype=new Error;ExitStatus.prototype.constructor=ExitStatus;var initialStackTop;dependenciesFulfilled=function runCaller(){if(!Module["calledRun"])run();if(!Module["calledRun"])dependenciesFulfilled=runCaller};function run(args){args=args||Module["arguments"];if(runDependencies>0){return}preRun();if(runDependencies>0)return;if(Module["calledRun"])return;function doRun(){if(Module["calledRun"])return;Module["calledRun"]=true;if(ABORT)return;ensureInitRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout((function(){setTimeout((function(){Module["setStatus"]("")}),1);doRun()}),1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&Module["noExitRuntime"]&&status===0){return}if(Module["noExitRuntime"]){}else{ABORT=true;EXITSTATUS=status;STACKTOP=initialStackTop;exitRuntime();if(Module["onExit"])Module["onExit"](status)}Module["quit"](status,new ExitStatus(status))}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}if(what!==undefined){out(what);err(what);what=JSON.stringify(what)}else{what=""}ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}Module["noExitRuntime"]=true;run()
-
-
-
-
diff --git a/RemoteDesktop/javascripts/wvnc_asm.wasm b/RemoteDesktop/javascripts/wvnc_asm.wasm
deleted file mode 100644
index b54362f..0000000
Binary files a/RemoteDesktop/javascripts/wvnc_asm.wasm and /dev/null differ
diff --git a/RemoteDesktop/package.json b/RemoteDesktop/package.json
index 7c7db2d..5422089 100644
--- a/RemoteDesktop/package.json
+++ b/RemoteDesktop/package.json
@@ -6,7 +6,8 @@
"author": "",
"email": ""
},
- "version":"0.1.0-a",
+ "version":"0.1.5-a",
+ "dependencies": ["libwvnc@0.1.2-a"],
"category":"Other",
"icon": "icon.png",
"mimes":["none"]
diff --git a/RemoteDesktop/project.json b/RemoteDesktop/project.json
index f6b658f..9d9cfc4 100644
--- a/RemoteDesktop/project.json
+++ b/RemoteDesktop/project.json
@@ -1,7 +1,7 @@
{
"name": "RemoteDesktop",
"css": ["assets/main.css"],
- "javascripts": ["javascripts/wvnc.js"],
+ "javascripts": [],
"coffees": ["coffees/main.coffee"],
- "copies": ["assets/scheme.html", "package.json", "README.md", "javascripts/decoder.js", "javascripts/wvnc_asm.js", "javascripts/wvnc_asm.wasm", "assets/icon.png"]
+ "copies": ["assets/scheme.html", "package.json", "README.md","assets/icon.png"]
}
\ No newline at end of file
diff --git a/libwvnc/README.md b/libwvnc/README.md
new file mode 100644
index 0000000..f56b5a5
--- /dev/null
+++ b/libwvnc/README.md
@@ -0,0 +1,74 @@
+# libwvnc
+
+Overview about WVNC: [https://blog.lxsang.me/r/id/23](https://blog.lxsang.me/r/id/23)
+
+**libwvnc** is the client side protocol API for my [Antd's **wvnc**](https://github.com/lxsang/antd-wvnc-plugin) server side plugin. It allows to acess VNC server from the web using websocket (via the **wvnc** server plugin).
+
+Since the **wvnc** plugin offers data compression using JPEG, **wvnc.js** depends on the **libjpeg** package and **web worker** to speed up the data decoding process, thus speed up the screen rendering on HTML canvas.
+
+
+## Example
+It is straight forward to use the api:
+
+Html code:
+
+```html
+ ...
+
+```
+
+Javascript:
+
+```javascript
+ var args, client;
+ args = {
+ // the canvas element
+ element: 'screen',
+ // The websocket uri to the wvnc server side plugin
+ ws: 'wss://localhost/wvnc',
+ // the decoder worker
+ libjpeg: 'path/to/jpg.js'
+ };
+ client = new WVNC(args);
+
+ // This function responds to a VNC server password request
+ // should return a promise
+ client.onpassword = function() {
+ return new Promise(function(r, e) {
+ return r('password');
+ });
+ };
+
+ // this function responds to the remote OS username and password request
+ // should return a promise
+ client.oncredential = function() {
+ return new Promise(function(r, e) {
+ return r('username', 'password');
+ });
+ };
+ // event fired when a text is copied on
+ // the remote computer
+ client.oncopy = function(text) {
+ console.log(text);
+ };
+ // init the WVNC client
+ client.init()
+ .then(function() {
+ client.connect(
+ // VNC server
+ "192.168.1.20:5901",
+ {
+ // bits per pixel
+ bbp: 32,
+ // data compression flag
+ // 1 is for both JPEG
+ // 0 is for raw data
+ flag: 1,
+ // JPEG quality %
+ quality: 50
+ });
+ })
+ .catch(function(m, s) {
+ return console.error(m, s);
+ });
+```
diff --git a/libwvnc/build/debug/README.md b/libwvnc/build/debug/README.md
new file mode 100644
index 0000000..f56b5a5
--- /dev/null
+++ b/libwvnc/build/debug/README.md
@@ -0,0 +1,74 @@
+# libwvnc
+
+Overview about WVNC: [https://blog.lxsang.me/r/id/23](https://blog.lxsang.me/r/id/23)
+
+**libwvnc** is the client side protocol API for my [Antd's **wvnc**](https://github.com/lxsang/antd-wvnc-plugin) server side plugin. It allows to acess VNC server from the web using websocket (via the **wvnc** server plugin).
+
+Since the **wvnc** plugin offers data compression using JPEG, **wvnc.js** depends on the **libjpeg** package and **web worker** to speed up the data decoding process, thus speed up the screen rendering on HTML canvas.
+
+
+## Example
+It is straight forward to use the api:
+
+Html code:
+
+```html
+ ...
+
+```
+
+Javascript:
+
+```javascript
+ var args, client;
+ args = {
+ // the canvas element
+ element: 'screen',
+ // The websocket uri to the wvnc server side plugin
+ ws: 'wss://localhost/wvnc',
+ // the decoder worker
+ libjpeg: 'path/to/jpg.js'
+ };
+ client = new WVNC(args);
+
+ // This function responds to a VNC server password request
+ // should return a promise
+ client.onpassword = function() {
+ return new Promise(function(r, e) {
+ return r('password');
+ });
+ };
+
+ // this function responds to the remote OS username and password request
+ // should return a promise
+ client.oncredential = function() {
+ return new Promise(function(r, e) {
+ return r('username', 'password');
+ });
+ };
+ // event fired when a text is copied on
+ // the remote computer
+ client.oncopy = function(text) {
+ console.log(text);
+ };
+ // init the WVNC client
+ client.init()
+ .then(function() {
+ client.connect(
+ // VNC server
+ "192.168.1.20:5901",
+ {
+ // bits per pixel
+ bbp: 32,
+ // data compression flag
+ // 1 is for both JPEG
+ // 0 is for raw data
+ flag: 1,
+ // JPEG quality %
+ quality: 50
+ });
+ })
+ .catch(function(m, s) {
+ return console.error(m, s);
+ });
+```
diff --git a/libwvnc/build/debug/decoder.js b/libwvnc/build/debug/decoder.js
new file mode 100644
index 0000000..c9a0890
--- /dev/null
+++ b/libwvnc/build/debug/decoder.js
@@ -0,0 +1,112 @@
+let resolution;
+
+decode_jpeg = (raw, msg) =>
+{
+ if(!JpegImage)
+ {
+ console.error("The JPEG library is not available");
+ return 0;
+ }
+ let jpeg = new JpegImage()
+ jpeg.parse(raw)
+ if(jpeg.width != msg.w || jpeg.height != msg.h)
+ {
+ console.error("Incorrect data size: expect " + msg.w*msg.h*4 + " got " + jpeg.width*jpeg.height*4);
+ return 0;
+ }
+ msg.pixels = new Uint8Array(msg.w*msg.h*4);
+ let data = jpeg.getData(msg.w, msg.h);
+ for(let j = 0; j < msg.h; j++)
+ {
+ for(let i = 0; i < msg.w; i++)
+ {
+ let index = j*msg.w*4 + i*4;
+ msg.pixels[index] = data[j*msg.w*3 + i*3];
+ msg.pixels[index+1] = data[j*msg.w*3 + i*3 + 1];
+ msg.pixels[index+2] = data[j*msg.w*3 + i*3 + 2];
+ msg.pixels[index+3] = 255;
+ }
+ }
+ return msg.pixels.length;
+}
+
+decode_raw = (raw, msg) =>
+{
+ let size =raw.length;
+ if(resolution.depth == 32)
+ {
+ msg.pixels = new Uint8Array(raw);
+ return size;
+ }
+ if(resolution.depth != 16)
+ {
+ console.error("Unsupported depth" + resolution.depth);
+ return 0;
+ }
+ let bytes = resolution.depth/8;
+ let npixels = size / bytes;
+ let outsize = npixels*4;
+ if(outsize != msg.w*msg.h*4)
+ {
+ console.error("Incorrect data size: expect " + msg.w*msg.h*4 + " got " + outsize);
+ return 0;
+ }
+ msg.pixels = new Uint8Array(outsize);
+ let value = 0;
+ let px = {};
+ for(let i = 0; i < npixels; i++)
+ {
+ value = 0;
+ for(let j=0; j < bytes; j++ )
+ value = (raw[i * bytes + j] << (j*8)) | value ;
+ // lookup for pixel
+ msg.pixels[i*4] = (value & 0x1F) * (255 / 31);
+ msg.pixels[i*4+1] = ((value >> 5) & 0x3F) * (255 / 63);
+ msg.pixels[i*4+2] = ((value >> 11) & 0x1F) * (255 / 31);
+ msg.pixels[i*4+3] = 255;
+ }
+ return outsize;
+}
+
+decode = (arr) =>
+{
+ let datain = new Uint8Array(arr);
+ let msg = {
+ x: datain[1] | (datain[2] << 8),
+ y: datain[3] | (datain[4] << 8),
+ w: datain[5] | (datain[6] << 8),
+ h: datain[7] | (datain[8] << 8),
+ flag: datain[9],
+ pixels: undefined
+ }
+ switch (msg.flag) {
+ case 0x0:
+ decode_raw(datain.subarray(10), msg);
+ break;
+ case 0x1:
+ decode_jpeg(datain.subarray(10), msg);
+ break;
+ default:
+ console.error("Unknow flag: " + msg.flag);
+ }
+ if(msg.pixels)
+ {
+ msg.pixels = msg.pixels.buffer;
+ postMessage(msg, [msg.pixels]);
+ }
+}
+
+onmessage = (e) => {
+ if(e.data.depth)
+ {
+ resolution = e.data;
+ }
+ else if(e.data.libjpeg)
+ {
+ importScripts(e.data.libjpeg);
+ }
+ else
+ {
+ decode(e.data);
+ }
+}
\ No newline at end of file
diff --git a/libwvnc/build/debug/main.js b/libwvnc/build/debug/main.js
new file mode 100644
index 0000000..bd79c80
--- /dev/null
+++ b/libwvnc/build/debug/main.js
@@ -0,0 +1 @@
+(function(){var e;e=class{constructor(e){var t,n,s;this.socket=void 0,this.ws=void 0,this.canvas=void 0,s="pkg://libwvnc/decoder.js".asFileHandle().getlink(),this.scale=1,e.ws&&(this.ws=e.ws),this.canvas=e.element,"string"==typeof this.canvas&&(this.canvas=document.getElementById(this.canvas)),e.libjpeg&&(t=e.libjpeg),this.decoder=new Worker(s),this.enableEvent=!0,n=this,this.mouseMask=0,this.decoder.postMessage({libjpeg:t}),this.decoder.onmessage=function(e){return n.process(e.data)}}init(){var e;return e=this,new Promise((function(t,n){return e.canvas?($(e.canvas).attr("tabindex","1"),e.initInputEvent(),t()):n("Canvas is not set")}))}initInputEvent(){var e,t,n,s;if(n=this,this.canvas&&(t=function(e){var t;return t=n.canvas.getBoundingClientRect(),{x:Math.floor((e.clientX-t.left)/n.scale),y:Math.floor((e.clientY-t.top)/n.scale)}},s=function(e){var s;if(n.enableEvent)return s=t(e),n.sendPointEvent(s.x,s.y,n.mouseMask)},n.canvas))return n.canvas.oncontextmenu=function(e){return e.preventDefault(),!1},n.canvas.onmousemove=function(e){return s(e)},n.canvas.onmousedown=function(e){var t;return t=1<this.disconnect(!0),window.addEventListener("unload",e),window.addEventListener("beforeunload",e)}initCanvas(e,t,n){return this.depth=n,this.canvas.width=e,this.canvas.height=t,this.resolution={w:e,h:t,depth:this.depth},this.decoder.postMessage(this.resolution),this.canvas.style.cursor="none",this.setScale(this.scale)}process(e){var t,n,s;if(this.socket)return n=new Uint8Array(e.pixels),(s=(t=this.canvas.getContext("2d",{alpha:!1})).createImageData(e.w,e.h)).data.set(n),t.putImageData(s,e.x,e.y)}setScale(e){if(this.scale=e,this.canvas)return this.canvas.style.transformOrigin="0 0",this.canvas.style.transform="scale("+e+")"}connect(e,t){var n;if(n=this,this.socket&&this.socket.close(),this.ws)return this.socket=new WebSocket(this.ws),this.socket.binaryType="arraybuffer",this.socket.onopen=function(){return console.log("socket opened"),n.initConnection(e,t)},this.socket.onmessage=function(e){return n.consume(e)},this.socket.onclose=function(){return n.socket=null,n.canvas.style.cursor="auto",n.canvas&&n.resolution&&n.canvas.getContext("2d").clearRect(0,0,n.resolution.w,n.resolution.h),console.log("socket closed")}}disconnect(e){if(this.socket&&this.socket.close(),this.decoder&&e)return this.decoder.terminate()}initConnection(e,t){var n;return(n=new Uint8Array(e.length+3))[0]=32,n[1]=1,n[2]=50,t&&(t.bbp&&(n[0]=t.bbp),t.flag&&(n[1]=t.flag),t.quality&&(n[2]=t.quality)),n.set((new TextEncoder).encode(e),3),this.socket.send(this.buildCommand(1,n))}sendPointEvent(e,t,n){var s;if(this.socket)return(s=new Uint8Array(5))[0]=255&e,s[1]=e>>8,s[2]=255&t,s[3]=t>>8,s[4]=n,this.socket.send(this.buildCommand(5,s))}sendKeyEvent(e,t){var n;if(this.socket&&this.enableEvent)return(n=new Uint8Array(3))[0]=255&e,n[1]=e>>8,n[2]=t,this.socket.send(this.buildCommand(6,n))}buildCommand(e,t){var n,s;switch(s=void 0,typeof t){case"string":s=(new TextEncoder).encode(t);break;case"number":s=new Uint8Array([t]);break;default:s=t}return(n=new Uint8Array(s.length+3))[0]=e,n[2]=s.length>>8,n[1]=15&s.length,n.set(s,3),n.buffer}oncopy(e){return console.log("Get clipboard text: "+e)}onpassword(){return new Promise((function(e,t){return t("onpassword is not implemented")}))}sendTextAsClipboard(e){if(this.socket)return console.log("send ",e),this.socket.send(this.buildCommand(7,e))}oncredential(){return new Promise((function(e,t){return t("oncredential is not implemented")}))}onerror(e){return console.log("Error",e)}onresize(){return console.log("resize")}consume(e){var t,n,s,a,r,o,i;switch(t=(n=new Uint8Array(e.data))[0],o=this,t){case 254:return n=n.subarray(1,n.length-1),s=new TextDecoder("utf-8"),this.onerror(s.decode(n));case 129:return console.log("Request for password"),this.enableEvent=!1,this.onpassword().then((function(e){return o.socket.send(o.buildCommand(2,e)),o.enableEvent=!0}));case 130:return console.log("Request for login"),this.enableEvent=!1,this.oncredential().then((function(e,t){var n;return(n=new Uint8Array(e.length+t.length+1)).set((new TextEncoder).encode(e),0),n.set(["\0"],e.length),n.set((new TextEncoder).encode(t),e.length+1),o.socket.send(o.buildCommand(3,n)),o.enableEvent=!0}));case 131:return i=n[1]|n[2]<<8,r=n[3]|n[4]<<8,a=n[5],this.initCanvas(i,r,a),this.socket.send(this.buildCommand(4,1)),this.onresize();case 132:return this.decoder.postMessage(n.buffer,[n.buffer]);case 133:return n=n.subarray(1),s=new TextDecoder("utf-8"),this.oncopy(s.decode(n)),this.socket.send(this.buildCommand(4,1));default:return console.log(t)}}},window.WVNC=e}).call(this);
\ No newline at end of file
diff --git a/libwvnc/build/debug/package.json b/libwvnc/build/debug/package.json
new file mode 100644
index 0000000..69da22a
--- /dev/null
+++ b/libwvnc/build/debug/package.json
@@ -0,0 +1,15 @@
+{
+ "pkgname": "libwvnc",
+ "name":"libwvnc",
+ "description":"libwvnc: client side VNC protocol via websocket",
+ "info":{
+ "author": "",
+ "email": ""
+ },
+ "version":"0.1.2-a",
+ "category":"Library",
+ "iconclass":"fa fa-cog",
+ "mimes":["none"],
+ "dependencies":["libjpeg@0.1.1-a"],
+ "locale": {}
+}
\ No newline at end of file
diff --git a/libwvnc/build/release/libwvnc.zip b/libwvnc/build/release/libwvnc.zip
new file mode 100644
index 0000000..1bf22b2
Binary files /dev/null and b/libwvnc/build/release/libwvnc.zip differ
diff --git a/libwvnc/decoder.js b/libwvnc/decoder.js
new file mode 100644
index 0000000..c9a0890
--- /dev/null
+++ b/libwvnc/decoder.js
@@ -0,0 +1,112 @@
+let resolution;
+
+decode_jpeg = (raw, msg) =>
+{
+ if(!JpegImage)
+ {
+ console.error("The JPEG library is not available");
+ return 0;
+ }
+ let jpeg = new JpegImage()
+ jpeg.parse(raw)
+ if(jpeg.width != msg.w || jpeg.height != msg.h)
+ {
+ console.error("Incorrect data size: expect " + msg.w*msg.h*4 + " got " + jpeg.width*jpeg.height*4);
+ return 0;
+ }
+ msg.pixels = new Uint8Array(msg.w*msg.h*4);
+ let data = jpeg.getData(msg.w, msg.h);
+ for(let j = 0; j < msg.h; j++)
+ {
+ for(let i = 0; i < msg.w; i++)
+ {
+ let index = j*msg.w*4 + i*4;
+ msg.pixels[index] = data[j*msg.w*3 + i*3];
+ msg.pixels[index+1] = data[j*msg.w*3 + i*3 + 1];
+ msg.pixels[index+2] = data[j*msg.w*3 + i*3 + 2];
+ msg.pixels[index+3] = 255;
+ }
+ }
+ return msg.pixels.length;
+}
+
+decode_raw = (raw, msg) =>
+{
+ let size =raw.length;
+ if(resolution.depth == 32)
+ {
+ msg.pixels = new Uint8Array(raw);
+ return size;
+ }
+ if(resolution.depth != 16)
+ {
+ console.error("Unsupported depth" + resolution.depth);
+ return 0;
+ }
+ let bytes = resolution.depth/8;
+ let npixels = size / bytes;
+ let outsize = npixels*4;
+ if(outsize != msg.w*msg.h*4)
+ {
+ console.error("Incorrect data size: expect " + msg.w*msg.h*4 + " got " + outsize);
+ return 0;
+ }
+ msg.pixels = new Uint8Array(outsize);
+ let value = 0;
+ let px = {};
+ for(let i = 0; i < npixels; i++)
+ {
+ value = 0;
+ for(let j=0; j < bytes; j++ )
+ value = (raw[i * bytes + j] << (j*8)) | value ;
+ // lookup for pixel
+ msg.pixels[i*4] = (value & 0x1F) * (255 / 31);
+ msg.pixels[i*4+1] = ((value >> 5) & 0x3F) * (255 / 63);
+ msg.pixels[i*4+2] = ((value >> 11) & 0x1F) * (255 / 31);
+ msg.pixels[i*4+3] = 255;
+ }
+ return outsize;
+}
+
+decode = (arr) =>
+{
+ let datain = new Uint8Array(arr);
+ let msg = {
+ x: datain[1] | (datain[2] << 8),
+ y: datain[3] | (datain[4] << 8),
+ w: datain[5] | (datain[6] << 8),
+ h: datain[7] | (datain[8] << 8),
+ flag: datain[9],
+ pixels: undefined
+ }
+ switch (msg.flag) {
+ case 0x0:
+ decode_raw(datain.subarray(10), msg);
+ break;
+ case 0x1:
+ decode_jpeg(datain.subarray(10), msg);
+ break;
+ default:
+ console.error("Unknow flag: " + msg.flag);
+ }
+ if(msg.pixels)
+ {
+ msg.pixels = msg.pixels.buffer;
+ postMessage(msg, [msg.pixels]);
+ }
+}
+
+onmessage = (e) => {
+ if(e.data.depth)
+ {
+ resolution = e.data;
+ }
+ else if(e.data.libjpeg)
+ {
+ importScripts(e.data.libjpeg);
+ }
+ else
+ {
+ decode(e.data);
+ }
+}
\ No newline at end of file
diff --git a/libwvnc/main.coffee b/libwvnc/main.coffee
new file mode 100644
index 0000000..b94f57d
--- /dev/null
+++ b/libwvnc/main.coffee
@@ -0,0 +1,315 @@
+class WVNC
+ constructor: (args) ->
+ @socket = undefined
+ @ws = undefined
+ @canvas = undefined
+ worker = "pkg://libwvnc/decoder.js".asFileHandle().getlink()
+ @scale = 1.0
+ @ws = args.ws if args.ws
+ @canvas = args.element
+ @canvas = document.getElementById @canvas if typeof @canvas is 'string'
+ libjpeg = args.libjpeg if args.libjpeg
+ @decoder = new Worker worker
+ @enableEvent = true
+ me = @
+ @mouseMask = 0
+ @decoder.postMessage {libjpeg: libjpeg}
+ @decoder.onmessage = (e) ->
+ me.process e.data
+ init: () ->
+ me = @
+ return new Promise (r, e) ->
+ return e('Canvas is not set') if not me.canvas
+ # fix keyboard event problem
+ $(me.canvas).attr 'tabindex', '1'
+ me.initInputEvent()
+ r()
+
+ initInputEvent: () ->
+ me = @
+ return unless @canvas
+ getMousePos = (e) ->
+ rect = me.canvas.getBoundingClientRect()
+ pos=
+ x: Math.floor((e.clientX - rect.left) / me.scale)
+ y: Math.floor((e.clientY - rect.top) / me.scale)
+ return pos
+
+ sendMouseLocation = (e) ->
+ return unless me.enableEvent
+ p = getMousePos e
+ me.sendPointEvent p.x, p.y, me.mouseMask
+
+ return unless me.canvas
+ me.canvas.oncontextmenu = (e) ->
+ e.preventDefault()
+ return false
+
+ me.canvas.onmousemove = (e) -> sendMouseLocation e
+
+ me.canvas.onmousedown = (e) ->
+ state = 1 << e.button
+ me.mouseMask = me.mouseMask | state
+ sendMouseLocation e
+ #e.preventDefault()
+
+ me.canvas.onmouseup = (e) ->
+ state = 1 << e.button
+ me.mouseMask = me.mouseMask & (~state)
+ sendMouseLocation e
+ #e.preventDefault()
+
+ me.canvas.onkeydown = me.canvas.onkeyup = (e) ->
+ # get the key code
+ keycode = e.keyCode
+ #console.log e
+ switch keycode
+ when 8 then code = 0xFF08 #back space
+ when 9 then code = 0xff89 #0xFF09 # tab ?
+ when 13 then code = 0xFF0D # return
+ when 27 then code = 0xFF1B # esc
+ when 46 then code = 0xFFFF # delete to verify
+ when 38 then code = 0xFF52 # up
+ when 40 then code = 0xFF54 # down
+ when 37 then code = 0xFF51 # left
+ when 39 then code = 0xFF53 # right
+ when 91 then code = 0xFFE7 # meta left
+ when 93 then code = 0xFFE8 # meta right
+ when 16 then code = 0xFFE1 # shift left
+ when 17 then code = 0xFFE3 # ctrl left
+ when 18 then code = 0xFFE9 # alt left
+ when 20 then code = 0xFFE5 # capslock
+ when 113 then code = 0xFFBF # f2
+ when 112 then code = 0xFFBE # f1
+ when 114 then code = 0xFFC0 # f3
+ when 115 then code = 0xFFC1 # f4
+ when 116 then code = 0xFFC2 # f5
+ when 117 then code = 0xFFC3 # f6
+ when 118 then code = 0xFFC4 # f7
+ when 119 then code = 0xFFC5 # f8
+ when 120 then code = 0xFFC6 # f9
+ when 121 then code = 0xFFC7 # f10
+ when 122 then code = 0xFFC8 # f11
+ when 123 then code = 0xFFC9 # f12
+ else
+ code = e.key.charCodeAt(0) #if not e.ctrlKey and not e.altKey
+ #if ((keycode > 47 and keycode < 58) or (keycode > 64 and keycode < 91) or (keycode > 95 and keycode < 112) or (keycode > 185 and keycode < 193) or (keycode > 218 && keycode < 223))
+ # code = e.key.charCodeAt(0)
+ #else
+ # code = keycode
+ e.preventDefault()
+ return unless code
+ if e.type is "keydown"
+ me.sendKeyEvent code, 1
+ else if e.type is "keyup"
+ me.sendKeyEvent code, 0
+
+ # mouse wheel event
+ @canvas.addEventListener 'wheel', (e) ->
+ return unless me.enableEvent
+ #if (e.deltaY < 0) # up
+ p = getMousePos e
+ e.preventDefault()
+ if e.deltaY < 0
+ me.sendPointEvent p.x, p.y, 8
+ me.sendPointEvent p.x, p.y, 0
+ return
+ me.sendPointEvent p.x, p.y, 16
+ me.sendPointEvent p.x, p.y, 0
+ # paste event
+ @canvas.onpaste = (e) ->
+ return unless me.enableEvent
+ pastedText = undefined
+ if window.clipboardData and window.clipboardData.getData #IE
+ pastedText = window.clipboardData.getData 'Text'
+ else if e.clipboardData and e.clipboardData.getData
+ pastedText = e.clipboardData.getData 'text/plain'
+ return false unless pastedText
+ e.preventDefault()
+ me.sendTextAsClipboard pastedText
+ # global event
+ fn = (e) =>
+ @disconnect(true)
+
+ window.addEventListener "unload", fn
+ window.addEventListener "beforeunload", fn
+
+ initCanvas: (w, h , d) ->
+ me = @
+ @depth = d
+ @canvas.width = w
+ @canvas.height = h
+ @resolution =
+ w: w,
+ h: h,
+ depth: @depth
+ @decoder.postMessage @resolution
+ me.canvas.style.cursor = "none"
+ @setScale @scale
+
+ process: (msg) ->
+ if not @socket
+ return
+ data = new Uint8Array msg.pixels
+ #w = @buffer.width * @scale
+ #h = @buffer.height * @scale
+ ctx = @canvas.getContext "2d", { alpha: false }
+ imgData = ctx.createImageData msg.w, msg.h
+ imgData.data.set data
+ ctx.putImageData imgData, msg.x, msg.y
+
+
+ setScale: (n) ->
+ @scale = n
+ return unless @canvas
+ @canvas.style.transformOrigin = '0 0'
+ @canvas.style.transform = 'scale(' + n + ')'
+
+
+ connect: (url, args) ->
+ me = @
+ @socket.close() if @socket
+ return unless @ws
+ @socket = new WebSocket @ws
+ @socket.binaryType = "arraybuffer"
+ @socket.onopen = () ->
+ console.log "socket opened"
+ me.initConnection(url, args)
+
+ @socket.onmessage = (e) ->
+ me.consume e
+ @socket.onclose = () ->
+ me.socket = null
+ me.canvas.style.cursor = "auto"
+ me.canvas.getContext('2d').clearRect 0,0, me.resolution.w, me.resolution.h if me.canvas and me.resolution
+ console.log "socket closed"
+
+ disconnect: (close_worker) ->
+ @socket.close() if @socket
+ @decoder.terminate() if @decoder and close_worker
+
+ initConnection: (vncserver, params) ->
+ #vncserver = "192.168.1.20:5901"
+ data = new Uint8Array vncserver.length + 3
+ data[0] = 32 # bbp
+ ###
+ flag:
+ 0: raw data no compress
+ 1: jpeg no compress
+ ###
+ data[1] = 1
+ data[2] = 50 # jpeg quality
+ if params
+ data[0] = params.bbp if params.bbp
+ data[1] = params.flag if params.flag
+ data[2] = params.quality if params.quality
+ ## rate in milisecond
+
+ data.set (new TextEncoder()).encode(vncserver), 3
+ @socket.send(@buildCommand 0x01, data)
+
+ sendPointEvent: (x, y, mask) ->
+ return unless @socket
+ data = new Uint8Array 5
+ data[0] = x & 0xFF
+ data[1] = x >> 8
+ data[2] = y & 0xFF
+ data[3] = y >> 8
+ data[4] = mask
+ @socket.send( @buildCommand 0x05, data )
+
+ sendKeyEvent: (code, v) ->
+ #console.log code, v
+ return unless @socket
+ return unless @enableEvent
+ data = new Uint8Array 3
+ data[0] = code & 0xFF
+ data[1] = code >> 8
+ data[2] = v
+ @socket.send( @buildCommand 0x06, data )
+
+ buildCommand: (hex, o) ->
+ data = undefined
+ switch typeof o
+ when 'string'
+ data = (new TextEncoder()).encode(o)
+ when 'number'
+ data = new Uint8Array [o]
+ else
+ data = o
+ cmd = new Uint8Array data.length + 3
+ cmd[0] = hex
+ cmd[2] = data.length >> 8
+ cmd[1] = data.length & 0x0F
+ cmd.set data, 3
+ #console.log "the command is", cmd.buffer
+ return cmd.buffer
+
+ oncopy: (text) ->
+ console.log "Get clipboard text: " + text
+
+ onpassword: () ->
+ return new Promise (resolve, reject) ->
+ reject("onpassword is not implemented")
+
+ sendTextAsClipboard: (text) ->
+ return unless @socket
+ console.log "send ", text
+ @socket.send (@buildCommand 0x07, text)
+
+ oncredential: () ->
+ return new Promise (resolve, reject) ->
+ reject("oncredential is not implemented")
+
+ onerror: (m) ->
+ console.log "Error", m
+
+ onresize: () ->
+ console.log "resize"
+
+ consume: (e) ->
+ data = new Uint8Array e.data
+ cmd = data[0]
+ me = @
+ switch cmd
+ when 0xFE #error
+ data = data.subarray 1, data.length - 1
+ dec = new TextDecoder("utf-8")
+ @onerror dec.decode(data)
+ when 0x81
+ console.log "Request for password"
+ @enableEvent = false
+ @onpassword().then (pass) ->
+ me.socket.send (me.buildCommand 0x02, pass)
+ me.enableEvent = true
+ when 0x82
+ console.log "Request for login"
+ @enableEvent = false
+ @oncredential().then (user, pass) ->
+ arr = new Uint8Array user.length + pass.length + 1
+ arr.set (new TextEncoder()).encode(user), 0
+ arr.set ['\0'], user.length
+ arr.set (new TextEncoder()).encode(pass), user.length + 1
+ me.socket.send(me.buildCommand 0x03, arr)
+ me.enableEvent = true
+ when 0x83
+ w = data[1] | (data[2]<<8)
+ h = data[3] | (data[4]<<8)
+ depth = data[5]
+ @initCanvas w, h, depth
+ # status command for ack
+ @socket.send(@buildCommand 0x04, 1)
+ @onresize()
+ when 0x84
+ # send data to web assembly for decoding
+ @decoder.postMessage data.buffer, [data.buffer]
+ when 0x85
+ # clipboard data from server
+ data = data.subarray 1
+ dec = new TextDecoder "utf-8"
+ @oncopy dec.decode data
+ @socket.send(@buildCommand 0x04, 1)
+ else
+ console.log cmd
+
+window.WVNC = WVNC
\ No newline at end of file
diff --git a/libwvnc/package.json b/libwvnc/package.json
new file mode 100644
index 0000000..69da22a
--- /dev/null
+++ b/libwvnc/package.json
@@ -0,0 +1,15 @@
+{
+ "pkgname": "libwvnc",
+ "name":"libwvnc",
+ "description":"libwvnc: client side VNC protocol via websocket",
+ "info":{
+ "author": "",
+ "email": ""
+ },
+ "version":"0.1.2-a",
+ "category":"Library",
+ "iconclass":"fa fa-cog",
+ "mimes":["none"],
+ "dependencies":["libjpeg@0.1.1-a"],
+ "locale": {}
+}
\ No newline at end of file
diff --git a/libwvnc/project.json b/libwvnc/project.json
new file mode 100644
index 0000000..84df19d
--- /dev/null
+++ b/libwvnc/project.json
@@ -0,0 +1,7 @@
+{
+ "name": "libwvnc",
+ "css": [],
+ "javascripts": [],
+ "coffees": ["main.coffee"],
+ "copies": [ "decoder.js","package.json", "README.md"]
+}
\ No newline at end of file
diff --git a/packages.json b/packages.json
index fc75e10..c2fec8d 100644
--- a/packages.json
+++ b/packages.json
@@ -149,6 +149,16 @@
"dependencies": [],
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libjpeg/build/release/libjpeg.zip"
},
+ {
+ "pkgname": "libwvnc",
+ "name": "libwvnc",
+ "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libwvnc/README.md",
+ "category": "Library",
+ "author": "",
+ "version": "0.1.2-a",
+ "dependencies": ["libjpeg@0.1.1-a"],
+ "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/libwvnc/build/release/libwvnc.zip"
+ },
{
"pkgname": "LuaPlayground",
"name": "LuaPlayground",
@@ -205,8 +215,8 @@
"description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteDesktop/README.md",
"category": "Other",
"author": "",
- "version": "0.1.0-a",
- "dependencies": [],
+ "version": "0.1.5-a",
+ "dependencies": ["libwvnc@0.1.2-a"],"category":"Other","icon":"icon.png","mimes":["none"],
"download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteDesktop/build/release/RemoteDesktop.zip"
},
{