diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 2af253b5..0e945aa9 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -46,7 +46,7 @@ import { CoreTerminal } from 'common/CoreTerminal'; import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter'; import { MutableDisposable, toDisposable } from 'common/Lifecycle'; import * as Browser from 'common/Platform'; -import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IClipboardEvent, IColorEvent, ITerminalOptions, KeyboardResultType, ScrollSource, SpecialColorIndex } from 'common/Types'; +import { ColorRequestType, CoreMouseAction, CoreMouseButton, CoreMouseEventType, IColorEvent, ITerminalOptions, KeyboardResultType, ScrollSource, SpecialColorIndex } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { IBuffer } from 'common/buffer/Types'; import { C0, C1_ESCAPED } from 'common/data/EscapeSequences'; @@ -54,7 +54,7 @@ import { evaluateKeyboardEvent } from 'common/input/Keyboard'; import { toRgbString } from 'common/input/XParseColor'; import { DecorationService } from 'common/services/DecorationService'; import { IDecorationService } from 'common/services/Services'; -import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker, IClipboardProvider } from '@xterm/xterm'; +import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm'; import { WindowsOptionsReportType } from '../common/InputHandler'; import { AccessibilityManager } from './AccessibilityManager'; import { LinkProviderService } from 'browser/services/LinkProviderService'; @@ -121,7 +121,6 @@ export class Terminal extends CoreTerminal implements ITerminal { public viewport: IViewport | undefined; private _compositionHelper: ICompositionHelper | undefined; private _accessibilityManager: MutableDisposable = this.register(new MutableDisposable()); - private _clipboardProvider: IClipboardProvider | undefined; private readonly _onCursorMove = this.register(new EventEmitter()); public readonly onCursorMove = this._onCursorMove.event; @@ -167,7 +166,6 @@ export class Terminal extends CoreTerminal implements ITerminal { this.register(this._inputHandler.onRequestReset(() => this.reset())); this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type))); this.register(this._inputHandler.onColor((event) => this._handleColorEvent(event))); - this.register(this._inputHandler.onClipboard((event) => this._handleClipboardEvent(event))); this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove)); this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange)); this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter)); @@ -905,15 +903,6 @@ export class Terminal extends CoreTerminal implements ITerminal { return this._linkProviderService.registerLinkProvider(linkProvider); } - public registerClipboardProvider(provider: IClipboardProvider): IDisposable { - this._clipboardProvider = provider; - return { - dispose: () => { - this._clipboardProvider = undefined; - } - }; - } - public registerCharacterJoiner(handler: CharacterJoinerHandler): number { if (!this._characterJoinerService) { throw new Error('Terminal must be opened first'); @@ -1314,18 +1303,6 @@ export class Terminal extends CoreTerminal implements ITerminal { } } - private _handleClipboardEvent(ev: IClipboardEvent): void { - if (!this._clipboardProvider) { - return; - } - if (ev.data === '?') { - this._clipboardProvider.readText(ev.selection).then(data => - this.coreService.triggerDataEvent(data)); - return; - } - this._clipboardProvider.writeText(ev.selection, ev.data); - } - // TODO: Remove cancel function and cancelEvents option public cancel(ev: Event, force?: boolean): boolean | undefined { if (!this.options.cancelEvents && !force) { diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 09199ae0..c7c8438c 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration, IClipboardProvider } from '@xterm/xterm'; +import { IDisposable, IMarker, ILinkProvider, IDecorationOptions, IDecoration } from '@xterm/xterm'; import { IEvent, EventEmitter } from 'common/EventEmitter'; import { ICharacterJoinerService, ICharSizeService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services'; import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; @@ -111,9 +111,6 @@ export class MockTerminal implements ITerminal { public registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined { throw new Error('Method not implemented.'); } - public registerClipboardProvider(provider: IClipboardProvider): IDisposable { - throw new Error('Method not implemented.'); - } public hasSelection(): boolean { throw new Error('Method not implemented.'); } diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 75898280..a6349225 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -13,7 +13,7 @@ import { AddonManager } from 'common/public/AddonManager'; import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi'; import { ParserApi } from 'common/public/ParserApi'; import { UnicodeApi } from 'common/public/UnicodeApi'; -import { IBufferNamespace as IBufferNamespaceApi, IClipboardProvider, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm'; +import { IBufferNamespace as IBufferNamespaceApi, IDecoration, IDecorationOptions, IDisposable, ILinkProvider, ILocalizableStrings, IMarker, IModes, IParser, ITerminalAddon, Terminal as ITerminalApi, ITerminalInitOnlyOptions, IUnicodeHandling } from '@xterm/xterm'; /** * The set of options that only have an effect when set in the Terminal constructor. @@ -174,9 +174,6 @@ export class Terminal extends Disposable implements ITerminalApi { this._verifyPositiveIntegers(decorationOptions.x ?? 0, decorationOptions.width ?? 0, decorationOptions.height ?? 0); return this._core.registerDecoration(decorationOptions); } - public registerClipboardProvider(provider: IClipboardProvider): IDisposable { - return this._core.registerClipboardProvider(provider); - } public hasSelection(): boolean { return this._core.hasSelection(); } diff --git a/src/common/InputHandler.test.ts b/src/common/InputHandler.test.ts index 7815cef5..d52077bf 100644 --- a/src/common/InputHandler.test.ts +++ b/src/common/InputHandler.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { InputHandler } from 'common/InputHandler'; -import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType, SpecialColorIndex, IClipboardEvent, ClipboardEventType } from 'common/Types'; +import { IBufferLine, IAttributeData, IColorEvent, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types'; import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine'; import { CellData } from 'common/buffer/CellData'; import { Attributes, BgFlags, UnderlineStyle } from 'common/buffer/Constants'; @@ -17,7 +17,6 @@ import { DEFAULT_OPTIONS } from 'common/services/OptionsService'; import { clone } from 'common/Clone'; import { BufferService } from 'common/services/BufferService'; import { CoreService } from 'common/services/CoreService'; -import { ClipboardSelectionType } from '@xterm/xterm'; function getCursor(bufferService: IBufferService): number[] { return [ @@ -1982,88 +1981,6 @@ describe('InputHandler', () => { assert.deepEqual(stack, [[{ type: ColorRequestType.SET, index: 0, color: [170, 187, 204] }, { type: ColorRequestType.SET, index: 123, color: [0, 17, 34] }]]); stack.length = 0; }); - describe('52: manipulate selection data', async () => { - const testDataRaw = 'hello world'; - const testDataB64 = 'aGVsbG8gd29ybGQ='; - optionsService.options.allowClipboardAccess = true; - const stack: IClipboardEvent[] = []; - inputHandler.onClipboard(ev => stack.push(ev)); - await inputHandler.parseP(`\x1b]52;c;\x07`); - await inputHandler.parseP(`\x1b]52;c;${testDataRaw}\x07`); - await inputHandler.parseP(`\x1b]52;c;${testDataB64}\x07`); - await inputHandler.parseP(`\x1b]52;c;${testDataB64}invalid\x07`); - await inputHandler.parseP(`\x1b]52;c;!\x07`); - await inputHandler.parseP(`\x1b]52;c;?\x07`); - await inputHandler.parseP(`\x1b]52;p;\x07`); - await inputHandler.parseP(`\x1b]52;p;${testDataRaw}\x07`); - await inputHandler.parseP(`\x1b]52;p;${testDataB64}\x07`); - await inputHandler.parseP(`\x1b]52;p;${testDataB64}invalid\x07`); - await inputHandler.parseP(`\x1b]52;p;!\x07`); - await inputHandler.parseP(`\x1b]52;p;?\x07`); - assert.deepEqual(stack, [ - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.SYSTEM, - data: '' - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.SYSTEM, - data: testDataRaw - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.SYSTEM, - data: testDataB64 - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.SYSTEM, - data: testDataB64+'invalid' - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.SYSTEM, - data: '!' - }, - { - type: ClipboardEventType.REPORT, - selection: ClipboardSelectionType.SYSTEM, - data: '?' - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.PRIMARY, - data: '' - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.PRIMARY, - data: testDataRaw - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.PRIMARY, - data: testDataB64 - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.PRIMARY, - data: testDataB64+'invalid' - }, - { - type: ClipboardEventType.SET, - selection: ClipboardSelectionType.PRIMARY, - data: '!' - }, - { - type: ClipboardEventType.REPORT, - selection: ClipboardSelectionType.PRIMARY, - data: '?' - } - ]); - stack.length = 0; - }); it('104: restore events', async () => { const stack: IColorEvent[] = []; inputHandler.onColor(ev => stack.push(ev)); diff --git a/src/common/InputHandler.ts b/src/common/InputHandler.ts index 8bc725fc..a4b8c64b 100644 --- a/src/common/InputHandler.ts +++ b/src/common/InputHandler.ts @@ -4,7 +4,7 @@ * @license MIT */ -import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, SpecialColorIndex, IClipboardEvent, ClipboardEventType } from 'common/Types'; +import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent, IParseStack, ColorIndex, ColorRequestType, SpecialColorIndex } from 'common/Types'; import { C0, C1 } from 'common/data/EscapeSequences'; import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets'; import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser'; @@ -22,7 +22,6 @@ import { OscHandler } from 'common/parser/OscParser'; import { DcsHandler } from 'common/parser/DcsParser'; import { IBuffer } from 'common/buffer/Types'; import { parseColor } from 'common/input/XParseColor'; -import { ClipboardSelectionType } from '@xterm/xterm'; /** * Map collect to glevel. Used in `selectCharset`. @@ -160,8 +159,6 @@ export class InputHandler extends Disposable implements IInputHandler { public readonly onTitleChange = this._onTitleChange.event; private readonly _onColor = this.register(new EventEmitter()); public readonly onColor = this._onColor.event; - private readonly _onClipboard = this.register(new EventEmitter()); - public readonly onClipboard = this._onClipboard.event; private _parseStack: IParseStack = { paused: false, @@ -323,7 +320,6 @@ export class InputHandler extends Disposable implements IInputHandler { // 50 - Set Font to Pt. // 51 - reserved for Emacs shell. // 52 - Manipulate Selection Data. - this._parser.registerOscHandler(52, new OscHandler(data => this.setOrReportClipboard(data))); // 104 ; c - Reset Color Number c. this._parser.registerOscHandler(104, new OscHandler(data => this.restoreIndexedColor(data))); // 105 ; c - Reset Special Color Number c. @@ -3081,60 +3077,6 @@ export class InputHandler extends Disposable implements IInputHandler { return this._setOrReportSpecialColor(data, 2); } - private _setOrReportClipboard(data: string): boolean { - if (!this._optionsService.options.allowClipboardAccess) { - return true; - } - const args = data.split(';'); - if (args.length < 2) { - return true; - } - const pc = args[0]; - const pd = args[1]; - if (pd.length === 0) { - return true; - } - switch (pc) { - case ClipboardSelectionType.SYSTEM: - case ClipboardSelectionType.PRIMARY: - this._onClipboard.fire({ - type: pd === '?' ? ClipboardEventType.REPORT : ClipboardEventType.SET, - selection: pc, - data: pd - }); - break; - } - return true; - } - - /** - * OSC 52 ; ; | ST - set or query selection and clipboard data - * - * Test case: - * - * ```sh - * printf "\e]52;c;%s\a" "$(echo -n "Hello, World" | base64)" - * ``` - * - * @vt: #Y OSC 52 "Manipulate Selection Data" "OSC 52 ; Pc ; Pd BEL" "Set or query selection and clipboard data." - * Pc is the selection name. Can be one of: - * - `c` - clipboard - * - `p` - primary - * - `q` - secondary - * - `s` - select - * - `0-7` - cut-buffers 0-7 - * - * Only the `c` selection (clipboard) is supported by xterm.js. The browser - * Clipboard API only supports the clipboard selection. - * - * Pd is the base64 encoded data. - * If Pd is `?`, the terminal returns the current clipboard contents. - * If Pd is neither base64 encoded nor `?`, then the clipboard is cleared. - */ - public setOrReportClipboard(data: string): boolean { - return this._setOrReportClipboard(data); - } - /** * OSC 104 ; ST - restore ANSI color * diff --git a/src/common/Types.d.ts b/src/common/Types.d.ts index 99815bad..251a09f6 100644 --- a/src/common/Types.d.ts +++ b/src/common/Types.d.ts @@ -9,7 +9,7 @@ import { Attributes, UnderlineStyle } from 'common/buffer/Constants'; // eslint- import { IBufferSet } from 'common/buffer/Types'; import { IParams } from 'common/parser/Types'; import { ICoreMouseService, ICoreService, IOptionsService, IUnicodeService } from 'common/services/Services'; -import { ClipboardSelectionType as ClipboardSelectionType, IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from '@xterm/xterm'; +import { IFunctionIdentifier, ITerminalOptions as IPublicTerminalOptions } from '@xterm/xterm'; export interface ICoreTerminal { coreMouseService: ICoreMouseService; @@ -447,17 +447,6 @@ export interface IColorRestoreRequest { } export type IColorEvent = (IColorReportRequest | IColorSetRequest | IColorRestoreRequest)[]; -export const enum ClipboardEventType { - REPORT = 0, - SET = 1 -} - -export interface IClipboardEvent { - type: ClipboardEventType; - selection: ClipboardSelectionType; - data: string; -} - /** * Calls the parser and handles actions generated by the parser. */ @@ -527,7 +516,6 @@ export interface IInputHandler { /** OSC 10 */ setOrReportFgColor(data: string): boolean; /** OSC 11 */ setOrReportBgColor(data: string): boolean; /** OSC 12 */ setOrReportCursorColor(data: string): boolean; - /** OSC 52 */ setOrReportClipboard(data: string): boolean; /** OSC 104 */ restoreIndexedColor(data: string): boolean; /** OSC 110 */ restoreFgColor(data: string): boolean; /** OSC 111 */ restoreBgColor(data: string): boolean; diff --git a/src/common/services/OptionsService.ts b/src/common/services/OptionsService.ts index b80c6676..3c2d9678 100644 --- a/src/common/services/OptionsService.ts +++ b/src/common/services/OptionsService.ts @@ -54,8 +54,7 @@ export const DEFAULT_OPTIONS: Readonly> = { convertEol: false, termName: 'xterm', cancelEvents: false, - overviewRulerWidth: 0, - allowClipboardAccess: false + overviewRulerWidth: 0 }; const FONT_WEIGHT_OPTIONS: Extract[] = ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900']; diff --git a/src/common/services/Services.ts b/src/common/services/Services.ts index f7749795..210a0afb 100644 --- a/src/common/services/Services.ts +++ b/src/common/services/Services.ts @@ -206,7 +206,6 @@ export type FontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '50 export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'off'; export interface ITerminalOptions { - allowClipboardAccess?: boolean; allowProposedApi?: boolean; allowTransparency?: boolean; altClickMovesCursor?: boolean; diff --git a/test/playwright/Terminal.test.ts b/test/playwright/Terminal.test.ts index 13c0f8d8..19f6eb31 100644 --- a/test/playwright/Terminal.test.ts +++ b/test/playwright/Terminal.test.ts @@ -770,60 +770,6 @@ test.describe('API Integration Tests', () => { }); }); - test.describe('registerClipboardProvider', () => { - async function registerClipboardProvider(ctx: ITestContext): Promise { - await ctx.page.evaluate(`window.clipboard = ''`); - await ctx.page.evaluate(`window.term._disposables.push( - window.term.registerClipboardProvider({ - readText: (selection) => { - return Promise.resolve(window.clipboard); - }, - writeText: (selection, text) => { - window.clipboard = text; - return Promise.resolve(); - } - }) - )`); - } - test('should register clipboard provider', async () => { - await openTerminal(ctx, { allowClipboardAccess: true }); - await registerClipboardProvider(ctx); - await ctx.page.evaluate(`window.term.dispose()`); - }); - test('should ignore clipboard when no provider is registered', async () => { - await openTerminal(ctx, { allowClipboardAccess: true }); - await ctx.proxy.write('\x1b]52;c;foobar\x07'); - strictEqual(await ctx.page.evaluate(`window.clipboard`), ''); - await ctx.page.evaluate(`window.term.dispose()`); - }); - test('should ignore clipboard when allowClipboardAccess is false', async () => { - await openTerminal(ctx, { allowClipboardAccess: false }); - await registerClipboardProvider(ctx); - await ctx.proxy.write('\x1b]52;c;foobar\x07'); - strictEqual(await ctx.page.evaluate(`window.clipboard`), ''); - await ctx.page.evaluate(`window.term.dispose()`); - }); - test('should save to clipboard when writeText is called', async () => { - await openTerminal(ctx, { allowClipboardAccess: true }); - await registerClipboardProvider(ctx); - await ctx.proxy.write('\x1b]52;c;foobar\x07'); - strictEqual(await ctx.page.evaluate(`window.clipboard`), 'foobar'); - await ctx.page.evaluate(`window.term.dispose()`); - }); - test('should read from clipboard when readText is called', async () => { - await openTerminal(ctx, { allowClipboardAccess: true }); - await registerClipboardProvider(ctx); - await ctx.page.evaluate(` - window.data = []; - window.term.onData(e => data.push(e)); - `); - await ctx.proxy.write('\x1b]52;c;foobar\x07'); - await ctx.proxy.write('\x1b]52;c;?\x07'); - deepStrictEqual(await ctx.page.evaluate(`window.data`), ['foobar']); - await ctx.page.evaluate(`window.term.dispose()`); - }); - }); - test.describe('registerLinkProvider', () => { test('should fire provideLinks when hovering cells', async () => { await openTerminal(ctx); diff --git a/test/playwright/TestUtils.ts b/test/playwright/TestUtils.ts index 93179eac..1427578c 100644 --- a/test/playwright/TestUtils.ts +++ b/test/playwright/TestUtils.ts @@ -78,7 +78,6 @@ type TerminalProxyCustomOverrides = 'buffer' | ( 'attachCustomWheelEventHandler' | 'registerLinkProvider' | 'registerCharacterJoiner' | - 'registerClipboardProvider' | 'deregisterCharacterJoiner' | 'loadAddon' ); diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index b7beb2f7..33008289 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -24,12 +24,6 @@ declare module '@xterm/xterm' { * An object containing options for the terminal. */ export interface ITerminalOptions { - /** - * Whether to allow clipboard access. When false, any access to the - * clipboard is ignored. The default is false. - */ - allowClipboardAccess?: boolean; - /** * Whether to allow the use of proposed API. When false, any usage of APIs * marked as experimental/proposed will throw an error. The default is @@ -1130,14 +1124,6 @@ declare module '@xterm/xterm' { */ registerDecoration(decorationOptions: IDecorationOptions): IDecoration | undefined; - /** - * Registers a clipboard provider, allowing custom handling of clipboard - * selection events. This is used primarily to enable accessing the - * clipboard to read/write clipboard data. - * @param provider The provider to register. - */ - registerClipboardProvider(provider: IClipboardProvider): IDisposable; - /** * Gets whether the terminal has an active selection. */ @@ -1919,33 +1905,4 @@ declare module '@xterm/xterm' { */ readonly wraparoundMode: boolean; } - - export interface IClipboardProvider { - /** - * Gets the clipboard content. - * @param selection The clipboard selection to read. - * @returns A promise that resolves with the base64 encoded data. - */ - readText(selection: ClipboardSelectionType): Promise; - - /** - * Sets the clipboard content. - * @param selection The clipboard selection to set. - * @param data The base64 encoded data to set. If the data is invalid - * base64, the clipboard is cleared. - */ - writeText(selection: ClipboardSelectionType, data: string): Promise; - } - - /** - * Clipboard selection type. This is used to specify which selection buffer to - * read or write to. - * - SYSTEM `c`: The system clipboard. - * - PRIMARY `p`: The primary clipboard. This is provided for compatibility - * with Linux X11. - */ - export const enum ClipboardSelectionType { - SYSTEM = 'c', - PRIMARY = 'p', - } }