KASM-1947 binary clipboard WIP

This commit is contained in:
matt 2021-09-23 08:39:37 +00:00
parent 141f91fde5
commit 34bfdddab5
2 changed files with 82 additions and 53 deletions

View File

@ -1125,15 +1125,12 @@ const UI = {
UI.copyFromLocalClipboard(); UI.copyFromLocalClipboard();
}, },
copyFromLocalClipboard: function copyFromLocalClipboard() { copyFromLocalClipboard: function copyFromLocalClipboard() {
console.log("copyFromLocalClipboard Called");
if (!document.hasFocus()) { if (!document.hasFocus()) {
console.log("window does not have focus"); console.log("window does not have focus");
return; return;
} }
if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) { if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) {
console.log('checking clipboard');
navigator.clipboard.read().then((data) => { navigator.clipboard.read().then((data) => {
console.log('sending clipboard data to server');
UI.rfb.clipboardPasteDataFrom(data); UI.rfb.clipboardPasteDataFrom(data);
}); });

View File

@ -798,34 +798,54 @@ export default class RFB extends EventTargetMixin {
let dataset = []; let dataset = [];
let mimes = []; let mimes = [];
let h = 0;
for (let i = 0; i < clipdata.length; i++) { for (let i = 0; i < clipdata.length; i++) {
for (let ti = 0; ti < clipdata[i].types.length; ti++) { for (let ti = 0; ti < clipdata[i].types.length; ti++) {
let mime = clipdata[i].types[ti]; let mime = clipdata[i].types[ti];
if (mime !== 'image/png') {
console.log('skipping type: ' + mime);
continue;
}
switch (mime) {
case 'image/png':
case 'text/plain':
case 'text/html':
mimes.push(mime); mimes.push(mime);
let blob = await clipdata[i].getType(mime); let blob = await clipdata[i].getType(mime);
let buff = await blob.arrayBuffer(); let buff = await blob.arrayBuffer();
let data = new Uint8Array(buff); let data = new Uint8Array(buff);
let h = hashUInt8Array(data); if (!h) {
console.log('New Clip hash: ' + h); h = hashUInt8Array(data);
if (h === this._clipHash) { if (h === this._clipHash) {
console.log('No clipboard changes');
return; return;
} else { } else {
this._clipHash = h; this._clipHash = h;
} }
}
dataset.push(data); dataset.push(data);
console.log('Sending mime type: ' + mime); console.log('Sending mime type: ' + mime);
break;
default:
console.log('skipping clip send mime type: ' + mime)
} }
}
}
//if png is present and text/plain is not, remove other variations of images to save bandwidth
//if png is present with text/plain, then remove png. Word will put in a png of copied text
if (mimes.includes('image/png') && !mimes.includes('text/plain')) {
let i = mimes.indexOf('image/png');
mimes = mimes.slice(i, i+1);
dataset = dataset.slice(i, i+1);
} else if (mimes.includes('image/png') && mimes.includes('text/plain')) {
let i = mimes.indexOf('image/png');
mimes.splice(i, 1);
dataset.splice(i, 1);
} }
if (dataset.length > 0) { if (dataset.length > 0) {
RFB.messages.sendBinaryClipboard(this._sock, dataset[0], mimes[0]); RFB.messages.sendBinaryClipboard(this._sock, dataset, mimes);
} }
} }
@ -2460,6 +2480,7 @@ export default class RFB extends EventTargetMixin {
} }
if (clipdata.length > 0) { if (clipdata.length > 0) {
this._clipHash = 0;
navigator.clipboard.write(clipdata).then( navigator.clipboard.write(clipdata).then(
function() {}, function() {},
function(err) { function(err) {
@ -3269,27 +3290,37 @@ RFB.messages = {
}, },
sendBinaryClipboard(sock, data, mime) { sendBinaryClipboard(sock, dataset, mimes) {
const buff = sock._sQ; const buff = sock._sQ;
const offset = sock._sQlen; let offset = sock._sQlen;
buff[offset] = 180; // msg-type buff[offset] = 180; // msg-type
buff[offset + 1] = dataset.length; // how many mime types
sock._sQlen += 2;
offset += 2;
buff[offset + 1] = 1; // we're sending one mime type for (let i=0; i < dataset.length; i++) {
buff[offset + 2] = mime.length; let mime = mimes[i];
let data = dataset[i];
buff[offset++] = mime.length;
for (let i = 0; i < mime.length; i++) { for (let i = 0; i < mime.length; i++) {
buff[offset + 3 + i] = mime.charCodeAt(i); // change to [] if not a string buff[offset++] = mime.charCodeAt(i); // change to [] if not a string
} }
let length = data.length; let length = data.length;
buff[offset + 3 + mime.length] = length >> 24; console.log('Clipboard data sent mime type ' + mime + ' len ' + length);
buff[offset + 3 + mime.length + 1] = length >> 16;
buff[offset + 3 + mime.length + 2] = length >> 8;
buff[offset + 3 + mime.length + 3] = length;
sock._sQlen += 3 + mime.length + 4; buff[offset++] = length >> 24;
buff[offset++] = length >> 16;
buff[offset++] = length >> 8;
buff[offset++] = length;
sock._sQlen += 1 + mime.length + 4;
// We have to keep track of from where in the data we begin creating the // We have to keep track of from where in the data we begin creating the
// buffer for the flush in the next iteration. // buffer for the flush in the next iteration.
@ -3310,7 +3341,8 @@ RFB.messages = {
dataOffset += flushSize; dataOffset += flushSize;
} }
console.log('clipboard sent'); offset = sock._sQlen;
}
}, },
setDesktopSize(sock, width, height, id, flags) { setDesktopSize(sock, width, height, id, flags) {