From dfe0836b5a921d0ed7e95ca79268c2e2d83a3530 Mon Sep 17 00:00:00 2001 From: Eric Feng Date: Mon, 23 Mar 2026 17:04:31 -0700 Subject: [PATCH 1/3] fix: allow Ctrl/Cmd+V through Guacamole keyboard to fix Safari clipboard sync Safari only permits clipboard API reads during user-initiated events. The Guacamole keyboard was calling preventDefault() on all keydown events, which prevented the browser paste event from firing. By allowing Ctrl/Cmd+V through, the browser fires the paste event naturally, triggering the existing onPaste -> syncClipboard codepath. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../chromium-headful/client/src/components/video.vue | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/images/chromium-headful/client/src/components/video.vue b/images/chromium-headful/client/src/components/video.vue index a2a739db..0d4c020d 100644 --- a/images/chromium-headful/client/src/components/video.vue +++ b/images/chromium-headful/client/src/components/video.vue @@ -534,6 +534,17 @@ } this.$client.sendData('keydown', { key: this.keyMap(key) }) + + // Allow Ctrl/Cmd+V through so the browser fires a paste event, + // which triggers onPaste -> syncClipboard (required for Safari + // clipboard access since it only permits reads in user-initiated events) + const isV = key === 0x0076 + const isCtrl = this.keyboard.modifiers?.ctrl + const isMeta = this.keyboard.modifiers?.meta + if (isV && (isCtrl || isMeta)) { + return true + } + return false } this.keyboard.onkeyup = (key: number) => { From 6dbcc002c7e82ee15b02d9276cfe57f2f3653869 Mon Sep 17 00:00:00 2001 From: Eric Feng Date: Wed, 25 Mar 2026 11:33:06 -0700 Subject: [PATCH 2/3] Update images/chromium-headful/client/src/components/video.vue Co-authored-by: archandatta --- images/chromium-headful/client/src/components/video.vue | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/images/chromium-headful/client/src/components/video.vue b/images/chromium-headful/client/src/components/video.vue index 0d4c020d..b92b266c 100644 --- a/images/chromium-headful/client/src/components/video.vue +++ b/images/chromium-headful/client/src/components/video.vue @@ -538,12 +538,8 @@ // Allow Ctrl/Cmd+V through so the browser fires a paste event, // which triggers onPaste -> syncClipboard (required for Safari // clipboard access since it only permits reads in user-initiated events) - const isV = key === 0x0076 - const isCtrl = this.keyboard.modifiers?.ctrl - const isMeta = this.keyboard.modifiers?.meta - if (isV && (isCtrl || isMeta)) { - return true - } + const { ctrl, meta } = this.keyboard.modifiers + return key === 0x0076 && !!(ctrl || meta) return false } From 40fae55d71e81ce5bcbf69818115aad9eb47cd72 Mon Sep 17 00:00:00 2001 From: Eric Feng Date: Wed, 25 Mar 2026 11:39:17 -0700 Subject: [PATCH 3/3] Apply suggestion from @ehfeng --- images/chromium-headful/client/src/components/video.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/images/chromium-headful/client/src/components/video.vue b/images/chromium-headful/client/src/components/video.vue index 2a8f42c1..fdb1d375 100644 --- a/images/chromium-headful/client/src/components/video.vue +++ b/images/chromium-headful/client/src/components/video.vue @@ -540,8 +540,6 @@ // clipboard access since it only permits reads in user-initiated events) const { ctrl, meta } = this.keyboard.modifiers return key === 0x0076 && !!(ctrl || meta) - - return false } this.keyboard.onkeyup = (key: number) => { if (!this.hosting || this.locked) {