Skip to content

Instantly share code, notes, and snippets.

@pavelfeldman
Created September 16, 2022 04:43
Show Gist options
  • Save pavelfeldman/83ef1550d2d328312b175c0f740b6609 to your computer and use it in GitHub Desktop.
Save pavelfeldman/83ef1550d2d328312b175c0f740b6609 to your computer and use it in GitHub Desktop.
diff --git a/core/clipboard.js b/core/clipboard.js
new file mode 100644
index 0000000..a4a6813
--- /dev/null
+++ b/core/clipboard.js
@@ -0,0 +1,46 @@
+export default class Clipboard {
+ constructor(target) {
+ this._target = target;
+
+ this._eventHandlers = {
+ 'copy': this._handleCopy.bind(this),
+ 'paste': this._handlePaste.bind(this)
+ };
+
+ // ===== EVENT HANDLERS =====
+
+ this.onpaste = () => {};
+ }
+
+ // ===== PRIVATE METHODS =====
+
+ _handleCopy(e) {
+ if (navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(e.clipboardData.getData('text/plain')).catch(() => {/* Do nothing */});
+ }
+ }
+
+ _handlePaste(e) {
+ if (navigator.clipboard.readText) {
+ navigator.clipboard.readText().then(this.onpaste).catch(() => {/* Do nothing */});
+ } else if (e.clipboardData) {
+ this.onpaste(e.clipboardData.getData('text/plain'));
+ }
+ }
+
+ // ===== PUBLIC METHODS =====
+
+ grab() {
+ if (!Clipboard.isSupported) return;
+ this._target.addEventListener('copy', this._eventHandlers.copy);
+ this._target.addEventListener('paste', this._eventHandlers.paste);
+ }
+
+ ungrab() {
+ if (!Clipboard.isSupported) return;
+ this._target.removeEventListener('copy', this._eventHandlers.copy);
+ this._target.removeEventListener('paste', this._eventHandlers.paste);
+ }
+}
+
+Clipboard.isSupported = (navigator && navigator.clipboard) ? true : false;
diff --git a/core/rfb.js b/core/rfb.js
index ea3bf58..ef4857c 100644
--- a/core/rfb.js
+++ b/core/rfb.js
@@ -132,6 +132,7 @@ export default class RFB extends EventTargetMixin {
this._sock = null; // Websock object
this._display = null; // Display object
this._flushing = false; // Display flushing state
+ this._clipboard = null; // Clipboard object
this._keyboard = null; // Keyboard input handler object
this._gestures = null; // Gesture input handler object
this._resizeObserver = null; // Resize observer object
@@ -229,6 +230,9 @@ export default class RFB extends EventTargetMixin {
}
this._display.onflush = this._onFlush.bind(this);
+ this._clipboard = new Clipboard(this._canvas);
+ this._clipboard.onpaste = this.clipboardPasteFrom.bind(this);
+
this._keyboard = new Keyboard(this._canvas);
this._keyboard.onkeyevent = this._handleKeyEvent.bind(this);
@@ -277,8 +281,10 @@ export default class RFB extends EventTargetMixin {
this._rfbConnectionState === "connected") {
if (viewOnly) {
this._keyboard.ungrab();
+ this._clipboard.ungrab();
} else {
this._keyboard.grab();
+ this._clipboard.grab();
}
}
}
@@ -1746,6 +1752,7 @@ export default class RFB extends EventTargetMixin {
this._setDesktopName(name);
this._resize(width, height);
+ if (!this._viewOnly) { this._clipboard.grab(); }
if (!this._viewOnly) { this._keyboard.grab(); }
this._fbDepth = 24;
@@ -1867,6 +1874,17 @@ export default class RFB extends EventTargetMixin {
"clipboard",
{ detail: { text: text } }));
+ if (Clipboard.isSupported) {
+ const clipboardData = new DataTransfer();
+ clipboardData.setData("text/plain", text);
+ const clipboardEvent = new ClipboardEvent('copy', { clipboardData });
+ // Force initialization since the constructor is broken in Firefox
+ if (!clipboardEvent.clipboardData.items.length) {
+ clipboardEvent.clipboardData.items.add(text, "text/plain");
+ }
+ this._canvas.dispatchEvent(clipboardEvent);
+ }
+
} else {
//Extended msg.
length = Math.abs(length);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment