WIP, firefox support
This commit is contained in:
parent
c533d18ac7
commit
8842f372b8
35
app/ui.js
35
app/ui.js
|
@ -1134,32 +1134,15 @@ const UI = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) {
|
if (UI.rfb && UI.rfb.clipboardUp && UI.rfb.clipboardSeamless) {
|
||||||
|
|
||||||
|
if (UI.rfb.clipboardBinary) {
|
||||||
navigator.clipboard.read().then((data) => {
|
navigator.clipboard.read().then((data) => {
|
||||||
UI.rfb.clipboardPasteDataFrom(data);
|
UI.rfb.clipboardPasteDataFrom(data);
|
||||||
UI.needToCheckClipboardChange = false;
|
UI.needToCheckClipboardChange = false;
|
||||||
|
}, (err) => {
|
||||||
|
console.log("No data in clipboard");
|
||||||
});
|
});
|
||||||
|
|
||||||
/*UI.readClipboard(function (text) {
|
|
||||||
console.log("clipboard read");
|
|
||||||
var maximumBufferSize = 10000;
|
|
||||||
var clipVal = document.getElementById('noVNC_clipboard_text').value;
|
|
||||||
|
|
||||||
if (clipVal != text) {
|
|
||||||
console.log("clipboard sent")
|
|
||||||
document.getElementById('noVNC_clipboard_text').value = text; // The websocket has a maximum buffer array size
|
|
||||||
|
|
||||||
if (text.length > maximumBufferSize) {
|
|
||||||
UI.popupMessage("Clipboard contents too large. Data truncated", 2000);
|
|
||||||
UI.rfb.clipboardPasteFrom(text.slice(0, maximumBufferSize));
|
|
||||||
} else {
|
|
||||||
//UI.popupMessage("Copied from Local Clipboard");
|
|
||||||
UI.rfb.clipboardPasteFrom(text);
|
|
||||||
}
|
}
|
||||||
} // Reset flag to prevent checking too often
|
|
||||||
|
|
||||||
|
|
||||||
UI.needToCheckClipboardChange = false;
|
|
||||||
}); */
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1300,15 +1283,13 @@ const UI = {
|
||||||
UI.rfb.antiAliasing = UI.getSetting('anti_aliasing');
|
UI.rfb.antiAliasing = UI.getSetting('anti_aliasing');
|
||||||
UI.rfb.clipboardUp = UI.getSetting('clipboard_up');
|
UI.rfb.clipboardUp = UI.getSetting('clipboard_up');
|
||||||
UI.rfb.clipboardDown = UI.getSetting('clipboard_down');
|
UI.rfb.clipboardDown = UI.getSetting('clipboard_down');
|
||||||
UI.rfb.clipboardBinary = supportsBinaryClipboard();
|
|
||||||
UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless');
|
UI.rfb.clipboardSeamless = UI.getSetting('clipboard_seamless');
|
||||||
if (UI.rfb.clipboardSeamless) {
|
UI.rfb.clipboardBinary = supportsBinaryClipboard() && UI.rfb.clipboardSeamless;
|
||||||
|
|
||||||
|
//Only explicitly request permission to clipboard on browsers that support binary clipboard access
|
||||||
|
if (supportsBinaryClipboard()) {
|
||||||
// explicitly request permission to the clipboard
|
// explicitly request permission to the clipboard
|
||||||
if (UI.rfb.clipboardBinary) {
|
|
||||||
navigator.permissions.query({ name: "clipboard-read" }).then((result) => { console.log('binary clipboard enabled') });
|
navigator.permissions.query({ name: "clipboard-read" }).then((result) => { console.log('binary clipboard enabled') });
|
||||||
} else {
|
|
||||||
navigator.permissions.query({ name: "clipboardRead" }).then((result) => { console.log('binary clipboard enabled') });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// KASM-960 workaround, disable seamless on Safari
|
// KASM-960 workaround, disable seamless on Safari
|
||||||
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent))
|
if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent))
|
||||||
|
|
69
core/rfb.js
69
core/rfb.js
|
@ -783,21 +783,28 @@ export default class RFB extends EventTargetMixin {
|
||||||
|
|
||||||
clipboardPasteFrom(text) {
|
clipboardPasteFrom(text) {
|
||||||
if (this._rfbConnectionState !== 'connected' || this._viewOnly) { return; }
|
if (this._rfbConnectionState !== 'connected' || this._viewOnly) { return; }
|
||||||
this.sentEventsCounter+=1;
|
if (!(typeof text === 'string' && text.length > 0)) { return; }
|
||||||
if (this._clipboardServerCapabilitiesFormats[extendedClipboardFormatText] &&
|
|
||||||
this._clipboardServerCapabilitiesActions[extendedClipboardActionNotify]) {
|
this.sentEventsCounter+=1;
|
||||||
|
|
||||||
this._clipboardText = text;
|
|
||||||
RFB.messages.extendedClipboardNotify(this._sock, [extendedClipboardFormatText]);
|
|
||||||
} else {
|
|
||||||
let data = new Uint8Array(text.length);
|
let data = new Uint8Array(text.length);
|
||||||
for (let i = 0; i < text.length; i++) {
|
for (let i = 0; i < text.length; i++) {
|
||||||
// FIXME: text can have values outside of Latin1/Uint8
|
|
||||||
data[i] = text.charCodeAt(i);
|
data[i] = text.charCodeAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
RFB.messages.clientCutText(this._sock, data);
|
let h = hashUInt8Array(data);
|
||||||
|
if (h === this._clipHash) {
|
||||||
|
console.log('No clipboard changes');
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this._clipHash = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dataset = [];
|
||||||
|
let mimes = [ 'text/plain' ];
|
||||||
|
dataset.push(data);
|
||||||
|
|
||||||
|
RFB.messages.sendBinaryClipboard(this._sock, dataset, mimes);
|
||||||
}
|
}
|
||||||
|
|
||||||
async clipboardPasteDataFrom(clipdata) {
|
async clipboardPasteDataFrom(clipdata) {
|
||||||
|
@ -816,6 +823,9 @@ export default class RFB extends EventTargetMixin {
|
||||||
case 'text/plain':
|
case 'text/plain':
|
||||||
case 'text/html':
|
case 'text/html':
|
||||||
let blob = await clipdata[i].getType(mime);
|
let blob = await clipdata[i].getType(mime);
|
||||||
|
if (!blob) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
let buff = await blob.arrayBuffer();
|
let buff = await blob.arrayBuffer();
|
||||||
let data = new Uint8Array(buff);
|
let data = new Uint8Array(buff);
|
||||||
|
|
||||||
|
@ -2465,31 +2475,48 @@ export default class RFB extends EventTargetMixin {
|
||||||
Log.Debug("HandleBinaryClipboard");
|
Log.Debug("HandleBinaryClipboard");
|
||||||
|
|
||||||
let num = this._sock.rQshift8(); // how many different mime types
|
let num = this._sock.rQshift8(); // how many different mime types
|
||||||
let blobs = [];
|
|
||||||
let clipdata = [];
|
|
||||||
let mimes = [];
|
let mimes = [];
|
||||||
|
let clipItemData = {};
|
||||||
console.log('Clipboard items recieved.');
|
console.log('Clipboard items recieved.');
|
||||||
|
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
let mimelen = this._sock.rQshift8();
|
let mimelen = this._sock.rQshift8();
|
||||||
const mime = this._sock.rQshiftStr(mimelen);
|
let mime = this._sock.rQshiftStr(mimelen);
|
||||||
|
|
||||||
let len = this._sock.rQshift32();
|
let len = this._sock.rQshift32();
|
||||||
|
let data = this._sock.rQshiftBytes(len);
|
||||||
const data = this._sock.rQshiftBytes(len);
|
|
||||||
|
|
||||||
switch(mime) {
|
switch(mime) {
|
||||||
case "image/png":
|
case "image/png":
|
||||||
case "text/html":
|
case "text/html":
|
||||||
case "text/plain":
|
case "text/plain":
|
||||||
if (mimes.includes(mime)){
|
//if (mimes.includes(mime)){
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
mimes.push(mime);
|
||||||
|
|
||||||
|
if (!this.clipboardBinary) {
|
||||||
|
if (mime == "text/plain") {
|
||||||
|
|
||||||
|
let textdata = new TextDecoder().decode(data);
|
||||||
|
|
||||||
|
if ((textdata.length > 0) && "\0" === textdata.charAt(textdata.length - 1)) {
|
||||||
|
textdata = textdata.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Clipboard item raw: ' + data);
|
||||||
|
console.log('Clipboard item decoded: ' + textdata);
|
||||||
|
this.dispatchEvent(new CustomEvent(
|
||||||
|
"clipboard",
|
||||||
|
{ detail: { text: textdata } })
|
||||||
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mimes.push(mime);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
console.log("Mime " + mime + ", len ", len);
|
console.log("Mime " + mime + ", len ", len);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
let blob = new Blob([data], { type: mime });
|
clipItemData[mime] = new Blob([data], { type: mime });
|
||||||
clipdata.push(new ClipboardItem({ [mime]: blob }));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Mime type skipped: ' + mime);
|
console.log('Mime type skipped: ' + mime);
|
||||||
|
@ -2497,14 +2524,16 @@ export default class RFB extends EventTargetMixin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clipdata.length > 0) {
|
if (Object.keys(clipItemData).length > 0) {
|
||||||
|
if (this.clipboardBinary) {
|
||||||
this._clipHash = 0;
|
this._clipHash = 0;
|
||||||
navigator.clipboard.write(clipdata).then(
|
navigator.clipboard.write([new ClipboardItem(clipItemData)]).then(
|
||||||
function() {},
|
function() {},
|
||||||
function(err) {
|
function(err) {
|
||||||
console.log("Error writing to client clipboard: " + err);
|
console.log("Error writing to client clipboard: " + err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue