From 9577b829a0ff73103d3a4c5646f7e1889ebd042c Mon Sep 17 00:00:00 2001 From: Andy Dixon Date: Thu, 23 Apr 2026 11:39:47 +0100 Subject: [PATCH] Fix for Mac double-pasting --- frontend/src/js/settings.js | 9 +++++++++ frontend/src/js/terminal.js | 15 +++++++++++++++ frontend/wailsjs/go/models.ts | 2 ++ internal/models/defaults.go | 1 + internal/models/models.go | 1 + 5 files changed, 28 insertions(+) diff --git a/frontend/src/js/settings.js b/frontend/src/js/settings.js index c8c9e9e..ba8e846 100644 --- a/frontend/src/js/settings.js +++ b/frontend/src/js/settings.js @@ -349,6 +349,14 @@ }, ), ); + body.appendChild( + this._settingField( + "toggle", + "useNativePaste", + "Use native paste", + p.useNativePaste === true, + ), + ); } /** @@ -1022,6 +1030,7 @@ "defaultFontSize", "defaultScrollback", "defaultCursorStyle", + "useNativePaste", ]; for (const field of fields) { diff --git a/frontend/src/js/terminal.js b/frontend/src/js/terminal.js index ff3174a..00df4fb 100644 --- a/frontend/src/js/terminal.js +++ b/frontend/src/js/terminal.js @@ -84,6 +84,14 @@ const attachPasteGuard = () => { const inputEl = term.textarea || container.querySelector("textarea"); if (!inputEl) return; + inputEl.addEventListener("keydown", (e) => { + const mod = e.ctrlKey || e.metaKey; + if (!mod || e.key !== "v") return; + // Block the native paste when we handle Cmd/Ctrl+V ourselves. + if (!suppressPasteEvent) return; + e.preventDefault(); + e.stopPropagation(); + }); inputEl.addEventListener("paste", (e) => { if (!suppressPasteEvent) return; e.preventDefault(); @@ -182,7 +190,14 @@ // Cmd/Ctrl+V — paste from clipboard if (mod && e.key === "v" && e.type === "keydown") { + const prefs = this.app.state.preferences || {}; + if (prefs.useNativePaste === true) { + suppressPasteEvent = false; + return true; + } suppressPasteEvent = true; + e.preventDefault(); + e.stopPropagation(); setTimeout(() => { suppressPasteEvent = false; }, 250); diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index 80991dc..6ba138c 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -12,6 +12,7 @@ export namespace models { defaultFontSize: number; defaultScrollback: number; defaultCursorStyle: string; + useNativePaste: boolean; static createFrom(source: any = {}) { return new AppPreferences(source); @@ -30,6 +31,7 @@ export namespace models { this.defaultFontSize = source["defaultFontSize"]; this.defaultScrollback = source["defaultScrollback"]; this.defaultCursorStyle = source["defaultCursorStyle"]; + this.useNativePaste = source["useNativePaste"]; } } export class AuditEntry { diff --git a/internal/models/defaults.go b/internal/models/defaults.go index 3ad7b17..4a5aa34 100644 --- a/internal/models/defaults.go +++ b/internal/models/defaults.go @@ -49,6 +49,7 @@ func DefaultAppPreferences() AppPreferences { DefaultFontSize: DefaultFontSize, DefaultScrollback: DefaultScrollback, DefaultCursorStyle: DefaultCursorStyle, + UseNativePaste: false, } } diff --git a/internal/models/models.go b/internal/models/models.go index 40135b9..b641927 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -263,6 +263,7 @@ type AppPreferences struct { DefaultFontSize int `json:"defaultFontSize"` DefaultScrollback int `json:"defaultScrollback"` DefaultCursorStyle string `json:"defaultCursorStyle"` + UseNativePaste bool `json:"useNativePaste"` } // AuditEntry records an auditable action within the application.