From bec4cba887b6fb1848a1a1abd3e25e7ff51a537a Mon Sep 17 00:00:00 2001 From: akamos Date: Wed, 25 Sep 2019 10:03:04 +0200 Subject: [PATCH] Auto copy-paste with navigator.clipboard API Co-authored-by: bulldozier --- app/ui.js | 32 ++++++++++++++++++++++++++++++++ core/rfb.js | 3 +++ tests/test.rfb.js | 2 ++ 3 files changed, 37 insertions(+) diff --git a/app/ui.js b/app/ui.js index 1909dee2..fc5b8c81 100644 --- a/app/ui.js +++ b/app/ui.js @@ -915,6 +915,32 @@ const UI = { * CLIPBOARD * ------v------*/ + writeLocalClipboard(text) { + if (typeof navigator.clipboard !== "undefined" && typeof navigator.clipboard.readText !== "undefined") { + navigator.clipboard.writeText(text).then(() => { + let debugMessage = text.substr(0, 40) + "..."; + Log.Debug('>> UI.setClipboardText: navigator.clipboard.writeText with ' + debugMessage); + }).catch(() => { + Log.Error(">> UI.setClipboardText: Failed to write system clipboard (trying to copy from NoVNC clipboard)"); + }); + } + }, + + readLocalClipboard() { + // navigator.clipboard and navigator.clipbaord.readText is not available in all browsers + if (typeof navigator.clipboard !== "undefined" && typeof navigator.clipboard.readText !== "undefined") { + navigator.clipboard.readText() + .then((clipboardText) => { + const text = document.getElementById('noVNC_clipboard_text').value; + if (clipboardText !== text) { + document.getElementById('noVNC_clipboard_text').value = clipboardText; + UI.clipboardSend(); + } + }) + .catch(err => Log.Warn("<< UI.readLocalClipboard: Failed to read system clipboard-: " + err)); + } + }, + openClipboardPanel() { UI.closeAllPanels(); UI.openControlbar(); @@ -944,17 +970,20 @@ const UI = { clipboardReceive(e) { Log.Debug(">> UI.clipboardReceive: " + e.detail.text.substr(0, 40) + "..."); document.getElementById('noVNC_clipboard_text').value = e.detail.text; + UI.writeLocalClipboard(e.detail.text); Log.Debug("<< UI.clipboardReceive"); }, clipboardClear() { document.getElementById('noVNC_clipboard_text').value = ""; + UI.writeLocalClipboard(""); UI.rfb.clipboardPasteFrom(""); }, clipboardSend() { const text = document.getElementById('noVNC_clipboard_text').value; Log.Debug(">> UI.clipboardSend: " + text.substr(0, 40) + "..."); + UI.writeLocalClipboard(text); UI.rfb.clipboardPasteFrom(text); Log.Debug("<< UI.clipboardSend"); }, @@ -1028,6 +1057,9 @@ const UI = { UI.rfb.addEventListener("securityfailure", UI.securityFailed); UI.rfb.addEventListener("capabilities", UI.updatePowerButton); UI.rfb.addEventListener("clipboard", UI.clipboardReceive); + + UI.rfb.oncanvasfocus = UI.readLocalClipboard; + UI.rfb.addEventListener("bell", UI.bell); UI.rfb.addEventListener("desktopname", UI.updateDesktopName); UI.rfb.clipViewport = UI.getSetting('view_clip'); diff --git a/core/rfb.js b/core/rfb.js index 1761500a..d85f20e5 100644 --- a/core/rfb.js +++ b/core/rfb.js @@ -234,6 +234,8 @@ export default class RFB extends EventTargetMixin { // time to set up callbacks setTimeout(this._updateConnectionState.bind(this, 'connecting')); + this.oncanvasfocus = () => {}; // Handler for canvas focused + Log.Debug("<< RFB.constructor"); // ===== PROPERTIES ===== @@ -381,6 +383,7 @@ export default class RFB extends EventTargetMixin { } focus() { + this.oncanvasfocus(); this._canvas.focus(); } diff --git a/tests/test.rfb.js b/tests/test.rfb.js index 1563a1e2..97b6e889 100644 --- a/tests/test.rfb.js +++ b/tests/test.rfb.js @@ -270,8 +270,10 @@ describe('Remote Frame Buffer Protocol Client', function () { describe('#focus', function () { it('should move focus to canvas object', function () { client._canvas.focus = sinon.spy(); + client.oncanvasfocus = sinon.spy(); client.focus(); expect(client._canvas.focus).to.have.been.calledOnce; + expect(client.oncanvasfocus).to.have.been.calledOnce; }); });