From a5d1be66e5d0bbe2355e2896d275f6f77bf04ab2 Mon Sep 17 00:00:00 2001 From: Yechao Li Date: Tue, 3 Jun 2025 22:53:31 +0800 Subject: [PATCH 1/4] Support read clipboard in safari --- patches/clipboard.diff | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/patches/clipboard.diff b/patches/clipboard.diff index ffcafe5dddb0..dd35dc6db3a1 100644 --- a/patches/clipboard.diff +++ b/patches/clipboard.diff @@ -133,3 +133,37 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts if (parsedArgs.status) { await sendToPipe({ type: 'status' +Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts +=================================================================== +--- code-server.orig/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts ++++ code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts +@@ -26,8 +26,17 @@ export class BrowserClipboardService ext + @ILayoutService layoutService: ILayoutService + ) { + super(layoutService, logService); ++ window.addEventListener('keydown', event => { ++ if (event.key.toLowerCase() === 'p' || (event.key === 'v' && (event.ctrlKey || event.metaKey))) { ++ this.lastClipboardTextContent = navigator.clipboard.readText() ++ this.lastCLipboardTime = Date.now(); ++ } ++ }) + } + ++ private lastClipboardTextContent?: Promise ++ private lastCLipboardTime?: number ++ + override async writeText(text: string, type?: string): Promise { + if (!!this.environmentService.extensionTestsLocationURI && typeof type !== 'string') { + type = 'vscode-tests'; // force in-memory clipboard for tests to avoid permission issues +@@ -46,6 +55,11 @@ export class BrowserClipboardService ext + } + + try { ++ if (this.lastClipboardTextContent && this.lastCLipboardTime && Date.now() - this.lastCLipboardTime < 1000) { ++ const content = await this.lastClipboardTextContent; ++ if (content) return content ++ } ++ + return await getActiveWindow().navigator.clipboard.readText(); + } catch (error) { + return new Promise(resolve => { From 5300db2de620e71d4f505b33681fa48f9c6f0d22 Mon Sep 17 00:00:00 2001 From: Yechao Li Date: Tue, 3 Jun 2025 23:17:12 +0800 Subject: [PATCH 2/4] only this feature in safari --- patches/clipboard.diff | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/patches/clipboard.diff b/patches/clipboard.diff index dd35dc6db3a1..a31bc66ae859 100644 --- a/patches/clipboard.diff +++ b/patches/clipboard.diff @@ -137,16 +137,26 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts +++ code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts -@@ -26,8 +26,17 @@ export class BrowserClipboardService ext +@@ -15,6 +15,7 @@ import { IWorkbenchEnvironmentService } + import { ILogService } from '../../../../platform/log/common/log.js'; + import { ILayoutService } from '../../../../platform/layout/browser/layoutService.js'; + import { getActiveWindow } from '../../../../base/browser/dom.js'; ++import { isSafari } from '../../../../base/browser/browser.js'; + + export class BrowserClipboardService extends BaseBrowserClipboardService { + +@@ -26,8 +27,19 @@ export class BrowserClipboardService ext @ILayoutService layoutService: ILayoutService ) { super(layoutService, logService); -+ window.addEventListener('keydown', event => { -+ if (event.key.toLowerCase() === 'p' || (event.key === 'v' && (event.ctrlKey || event.metaKey))) { -+ this.lastClipboardTextContent = navigator.clipboard.readText() -+ this.lastCLipboardTime = Date.now(); -+ } -+ }) ++ if (isSafari) { ++ window.addEventListener('keydown', event => { ++ if (event.key.toLowerCase() === 'p' || (event.key === 'v' && (event.ctrlKey || event.metaKey))) { ++ this.lastClipboardTextContent = navigator.clipboard.readText() ++ this.lastCLipboardTime = Date.now(); ++ } ++ }) ++ } } + private lastClipboardTextContent?: Promise @@ -155,13 +165,17 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo override async writeText(text: string, type?: string): Promise { if (!!this.environmentService.extensionTestsLocationURI && typeof type !== 'string') { type = 'vscode-tests'; // force in-memory clipboard for tests to avoid permission issues -@@ -46,6 +55,11 @@ export class BrowserClipboardService ext +@@ -46,6 +58,15 @@ export class BrowserClipboardService ext } try { -+ if (this.lastClipboardTextContent && this.lastCLipboardTime && Date.now() - this.lastCLipboardTime < 1000) { -+ const content = await this.lastClipboardTextContent; -+ if (content) return content ++ if (isSafari && this.lastClipboardTextContent && this.lastCLipboardTime && Date.now() - this.lastCLipboardTime < 1000) { ++ try { ++ const content = await this.lastClipboardTextContent; ++ if (content) return content ++ } catch { ++ // ignore error, we will try to read from the clipboard ++ } + } + return await getActiveWindow().navigator.clipboard.readText(); From 45da50e2cf4bb29f79166d45cef81d6a04ad8533 Mon Sep 17 00:00:00 2001 From: Yechao Li Date: Wed, 4 Jun 2025 00:27:11 +0800 Subject: [PATCH 3/4] only enable this feature when vim mode is active --- patches/clipboard.diff | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/patches/clipboard.diff b/patches/clipboard.diff index a31bc66ae859..79186a14538f 100644 --- a/patches/clipboard.diff +++ b/patches/clipboard.diff @@ -137,21 +137,30 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts +++ code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts -@@ -15,6 +15,7 @@ import { IWorkbenchEnvironmentService } +@@ -15,19 +15,36 @@ import { IWorkbenchEnvironmentService } import { ILogService } from '../../../../platform/log/common/log.js'; import { ILayoutService } from '../../../../platform/layout/browser/layoutService.js'; import { getActiveWindow } from '../../../../base/browser/dom.js'; +import { isSafari } from '../../../../base/browser/browser.js'; ++import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; export class BrowserClipboardService extends BaseBrowserClipboardService { -@@ -26,8 +27,19 @@ export class BrowserClipboardService ext + constructor( + @INotificationService private readonly notificationService: INotificationService, ++ @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IOpenerService private readonly openerService: IOpenerService, + @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, + @ILogService logService: ILogService, @ILayoutService layoutService: ILayoutService ) { super(layoutService, logService); + if (isSafari) { + window.addEventListener('keydown', event => { -+ if (event.key.toLowerCase() === 'p' || (event.key === 'v' && (event.ctrlKey || event.metaKey))) { ++ if ( ++ (event.key.toLowerCase() === 'p' && this.contextKeyService.getContextKeyValue('vim.mode') === 'Normal') || ++ (event.key === 'v' && (event.ctrlKey || event.metaKey) && this.contextKeyService.getContextKeyValue('vim.mode') === 'SearchInProgressMode') ++ ) { + this.lastClipboardTextContent = navigator.clipboard.readText() + this.lastCLipboardTime = Date.now(); + } @@ -165,7 +174,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo override async writeText(text: string, type?: string): Promise { if (!!this.environmentService.extensionTestsLocationURI && typeof type !== 'string') { type = 'vscode-tests'; // force in-memory clipboard for tests to avoid permission issues -@@ -46,6 +58,15 @@ export class BrowserClipboardService ext +@@ -46,6 +63,15 @@ export class BrowserClipboardService ext } try { From 7fa08a92c9dec4219b7268d3d1bf1db3c28a936a Mon Sep 17 00:00:00 2001 From: Yechao Li Date: Wed, 4 Jun 2025 10:13:27 +0800 Subject: [PATCH 4/4] fix: check current editor has focus --- patches/clipboard.diff | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/patches/clipboard.diff b/patches/clipboard.diff index 79186a14538f..ee84b5c52481 100644 --- a/patches/clipboard.diff +++ b/patches/clipboard.diff @@ -137,18 +137,20 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts +++ code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipboardService.ts -@@ -15,19 +15,36 @@ import { IWorkbenchEnvironmentService } +@@ -15,19 +15,38 @@ import { IWorkbenchEnvironmentService } import { ILogService } from '../../../../platform/log/common/log.js'; import { ILayoutService } from '../../../../platform/layout/browser/layoutService.js'; import { getActiveWindow } from '../../../../base/browser/dom.js'; +import { isSafari } from '../../../../base/browser/browser.js'; +import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js'; ++import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js'; export class BrowserClipboardService extends BaseBrowserClipboardService { constructor( @INotificationService private readonly notificationService: INotificationService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, ++ @ICodeEditorService private readonly codeEditorService: ICodeEditorService, @IOpenerService private readonly openerService: IOpenerService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, @ILogService logService: ILogService, @@ -158,7 +160,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo + if (isSafari) { + window.addEventListener('keydown', event => { + if ( -+ (event.key.toLowerCase() === 'p' && this.contextKeyService.getContextKeyValue('vim.mode') === 'Normal') || ++ (event.key.toLowerCase() === 'p' && this.contextKeyService.getContextKeyValue('vim.mode') === 'Normal' && this.codeEditorService.getActiveCodeEditor()?.hasTextFocus()) || + (event.key === 'v' && (event.ctrlKey || event.metaKey) && this.contextKeyService.getContextKeyValue('vim.mode') === 'SearchInProgressMode') + ) { + this.lastClipboardTextContent = navigator.clipboard.readText() @@ -174,7 +176,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/clipboard/browser/clipbo override async writeText(text: string, type?: string): Promise { if (!!this.environmentService.extensionTestsLocationURI && typeof type !== 'string') { type = 'vscode-tests'; // force in-memory clipboard for tests to avoid permission issues -@@ -46,6 +63,15 @@ export class BrowserClipboardService ext +@@ -46,6 +65,15 @@ export class BrowserClipboardService ext } try {