Add cut and paste support.
- A textarea below the VNC area represents the state of the current VNC clipboard. If there is a server cut event, the textarea will be updated. If the user updates the contents of the textarea, the new data will be sent as a client paste (cut) event. - One important change was to detect if the clipboard is focused and allow the user to type in the clipboard instead of in the VNC area.
This commit is contained in:
parent
66a529d70a
commit
30059bdf24
2
TODO
2
TODO
|
@ -1,5 +1,3 @@
|
|||
- Cut and paste support.
|
||||
|
||||
- Better status and error feedback.
|
||||
|
||||
- Get working in firefox using flash web-socket-js:
|
||||
|
|
9
vnc.html
9
vnc.html
|
@ -16,6 +16,15 @@
|
|||
style="border-style: dotted; border-width: 1px;">
|
||||
Canvas not supported.
|
||||
</canvas>
|
||||
|
||||
<br><br>
|
||||
VNC Clipboard:
|
||||
<input id='clearButton' type="button" value="Clear"
|
||||
onclick="RFB.clipboardClear();"><br>
|
||||
<textarea id="clipboard" style="font-size:9;" cols=80 rows=5
|
||||
onchange="RFB.clipboardPasteFrom();"
|
||||
onfocus="RFB.clipboardFocus=true;"
|
||||
onblur="RFB.clipboardFocus=false;"></textarea>
|
||||
</body>
|
||||
|
||||
<script src="include/mootools.js"></script>
|
||||
|
|
94
vnc.js
94
vnc.js
|
@ -33,6 +33,12 @@ Array.prototype.shiftStr = function (len) {
|
|||
return arr.map(function (num) {
|
||||
return String.fromCharCode(num); } ).join('');
|
||||
}
|
||||
Array.prototype.pushStr = function (str) {
|
||||
for (var i=0; i < str.length; i++) {
|
||||
this.push(str.charCodeAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
Array.prototype.shiftBytes = function (len) {
|
||||
return this.splice(0, len);
|
||||
}
|
||||
|
@ -74,6 +80,10 @@ d : [], // Received data accumulator
|
|||
|
||||
version : "RFB 003.003\n",
|
||||
state : 'ProtocolVersion',
|
||||
cuttext : 'none', // ServerCutText wait state
|
||||
ct_length : 0,
|
||||
clipboardFocus: false,
|
||||
|
||||
shared : 1,
|
||||
check_rate : 217,
|
||||
req_rate : 1413,
|
||||
|
@ -233,6 +243,8 @@ normal_msg: function () {
|
|||
//console.log(">> normal_msg");
|
||||
if (FBU.rects > 0) {
|
||||
var msg_type = 0;
|
||||
} else if (RFB.cuttext != 'none') {
|
||||
var msg_type = 3;
|
||||
} else {
|
||||
var msg_type = RFB.d.shift8();
|
||||
}
|
||||
|
@ -305,9 +317,25 @@ normal_msg: function () {
|
|||
break;
|
||||
case 3: // ServerCutText
|
||||
console.log("ServerCutText");
|
||||
RFB.d.shiftBytes(3); // Padding
|
||||
var length = RFB.d.shift32();
|
||||
RFB.d.shiftBytes(length);
|
||||
console.log("RFB.d:" + RFB.d.slice(0,20));
|
||||
if (RFB.cuttext == 'none') {
|
||||
RFB.cuttext = 'header';
|
||||
}
|
||||
if (RFB.cuttext == 'header') {
|
||||
if (RFB.d.length < 7) {
|
||||
console.log("waiting for ServerCutText header");
|
||||
break;
|
||||
}
|
||||
RFB.d.shiftBytes(3); // Padding
|
||||
RFB.ct_length = RFB.d.shift32();
|
||||
}
|
||||
RFB.cuttext = 'bytes';
|
||||
if (RFB.d.length < RFB.ct_length) {
|
||||
console.log("waiting for ServerCutText bytes");
|
||||
break;
|
||||
}
|
||||
RFB.clipboardCopyTo(RFB.d.shiftStr(RFB.ct_length));
|
||||
RFB.cuttext = 'none';
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown server message type: " + msg_type);
|
||||
|
@ -618,7 +646,17 @@ pointerEvent: function (x, y) {
|
|||
return arr;
|
||||
},
|
||||
|
||||
clientCutText: function () {
|
||||
clientCutText: function (text) {
|
||||
console.log(">> clientCutText");
|
||||
var arr;
|
||||
arr = [6]; // msg-type
|
||||
arr.push8(0); // padding
|
||||
arr.push8(0); // padding
|
||||
arr.push8(0); // padding
|
||||
arr.push32(text.length);
|
||||
arr.pushStr(text);
|
||||
console.log("<< clientCutText");
|
||||
return arr;
|
||||
},
|
||||
|
||||
|
||||
|
@ -680,20 +718,24 @@ checkEvents: function () {
|
|||
}
|
||||
},
|
||||
|
||||
keyDown: function (e) {
|
||||
//console.log(">> keyDown: " + Canvas.getKeysym(e));
|
||||
_keyX: function (e, down) {
|
||||
if (RFB.clipboardFocus) {
|
||||
return true;
|
||||
}
|
||||
e.stop();
|
||||
var arr = RFB.keyEvent(Canvas.getKeysym(e), 1);
|
||||
var arr = RFB.keyEvent(Canvas.getKeysym(e), down);
|
||||
arr = arr.concat(RFB.fbUpdateRequest(1));
|
||||
RFB.send_array(arr);
|
||||
},
|
||||
|
||||
keyDown: function (e) {
|
||||
//console.log(">> keyDown: " + Canvas.getKeysym(e));
|
||||
RFB._keyX(e, 1);
|
||||
},
|
||||
|
||||
keyUp: function (e) {
|
||||
//console.log(">> keyUp: " + Canvas.getKeysym(e));
|
||||
e.stop();
|
||||
var arr = RFB.keyEvent(Canvas.getKeysym(e), 0);
|
||||
arr = arr.concat(RFB.fbUpdateRequest(1));
|
||||
RFB.send_array(arr);
|
||||
RFB._keyX(e, 0);
|
||||
},
|
||||
|
||||
mouseDown: function(e) {
|
||||
|
@ -729,6 +771,24 @@ mouseMove: function(e) {
|
|||
Mouse.arr = Mouse.arr.concat( RFB.pointerEvent(x, y) );
|
||||
},
|
||||
|
||||
clipboardCopyTo: function (text) {
|
||||
console.log(">> clipboardCopyTo: " + text.substr(0,40) + "...");
|
||||
$('clipboard').value = text;
|
||||
console.log("<< clipboardCopyTo");
|
||||
},
|
||||
|
||||
clipboardPasteFrom: function () {
|
||||
if (RFB.state != "normal") return;
|
||||
var text = $('clipboard').value;
|
||||
console.log(">> clipboardPasteFrom: " + text.substr(0,40) + "...");
|
||||
RFB.send_array(RFB.clientCutText(text));
|
||||
console.log("<< clipboardPasteFrom");
|
||||
},
|
||||
|
||||
clipboardClear: function () {
|
||||
$('clipboard').value = '';
|
||||
RFB.clipboardPasteFrom();
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
|
@ -781,10 +841,22 @@ connect: function () {
|
|||
console.log("must set host and port");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset state */
|
||||
RFB.cuttext = 'none';
|
||||
RFB.ct_length = 0;
|
||||
FBU.rects = 0;
|
||||
FBU.subrects = 0; // RRE and HEXTILE
|
||||
FBU.lines = 0, // RAW
|
||||
FBU.tiles = 0, // HEXTILE
|
||||
Mouse.buttonmask = 0;
|
||||
Mouse.arr = [];
|
||||
|
||||
if (RFB.ws) {
|
||||
RFB.ws.close();
|
||||
}
|
||||
RFB.init_ws();
|
||||
|
||||
$('connectButton').value = "Disconnect";
|
||||
$('connectButton').onclick = RFB.disconnect;
|
||||
console.log("<< connect");
|
||||
|
|
Loading…
Reference in New Issue