diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index 2659700d67d..dfc2cf02c54 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -289,6 +289,10 @@ export abstract class SimpleFindWidget extends Widget implements IVerticalSashLa return this._domNode; } + public getFindInputDomNode() { + return this._findInput.domNode; + } + public reveal(initialInput?: string, animated = true): void { if (initialInput) { this._findInput.setValue(initialInput); diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts index efb9b621568..f055f70620d 100644 --- a/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/terminalFindWidget.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as dom from 'vs/base/browser/dom'; import { SimpleFindWidget } from 'vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget'; -import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; +import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { ITerminalInstance, IXtermTerminal, XtermTerminalConstants } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; @@ -14,6 +15,8 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { Event } from 'vs/base/common/event'; import type { ISearchOptions } from 'xterm-addon-search'; import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { openContextMenu } from 'vs/workbench/contrib/terminalContrib/find/browser/textInputContextMenu'; const TERMINAL_FIND_WIDGET_INITIAL_WIDTH = 419; @@ -27,6 +30,8 @@ export class TerminalFindWidget extends SimpleFindWidget { @IContextViewService _contextViewService: IContextViewService, @IKeybindingService keybindingService: IKeybindingService, @IContextKeyService private readonly _contextKeyService: IContextKeyService, + @IContextMenuService _contextMenuService: IContextMenuService, + @IClipboardService _clipboardService: IClipboardService, @IThemeService private readonly _themeService: IThemeService, @IConfigurationService private readonly _configurationService: IConfigurationService ) { @@ -52,6 +57,19 @@ export class TerminalFindWidget extends SimpleFindWidget { this._findInputFocused = TerminalContextKeys.findInputFocus.bindTo(this._contextKeyService); this._findWidgetFocused = TerminalContextKeys.findFocus.bindTo(this._contextKeyService); this._findWidgetVisible = TerminalContextKeys.findVisible.bindTo(this._contextKeyService); + const innerDom = this.getDomNode().firstChild; + if (innerDom) { + this._register(dom.addDisposableListener(innerDom, 'mousedown', (event) => { + event.stopPropagation(); + })); + this._register(dom.addDisposableListener(innerDom, 'contextmenu', (event) => { + event.stopPropagation(); + })); + } + this._register(dom.addDisposableListener(this.getFindInputDomNode(), 'contextmenu', (event) => { + openContextMenu(event, _clipboardService, _contextMenuService); + event.stopPropagation(); + })); this._register(this._themeService.onDidColorThemeChange(() => { if (this.isVisible()) { this.find(true, true); diff --git a/src/vs/workbench/contrib/terminalContrib/find/browser/textInputContextMenu.ts b/src/vs/workbench/contrib/terminalContrib/find/browser/textInputContextMenu.ts new file mode 100644 index 00000000000..68dbae05a05 --- /dev/null +++ b/src/vs/workbench/contrib/terminalContrib/find/browser/textInputContextMenu.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { StandardMouseEvent } from 'vs/base/browser/mouseEvent'; +import { Action, IAction, Separator } from 'vs/base/common/actions'; +import { isNative } from 'vs/base/common/platform'; +import { localize } from 'vs/nls'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; + +export function openContextMenu(event: MouseEvent, clipboardService: IClipboardService, contextMenuService: IContextMenuService): void { + const standardEvent = new StandardMouseEvent(event); + + // Actions from workbench/browser/actions/textInputActions + const actions: IAction[] = []; + actions.push( + + // Undo/Redo + new Action('undo', localize('undo', "Undo"), undefined, true, async () => document.execCommand('undo')), + new Action('redo', localize('redo', "Redo"), undefined, true, async () => document.execCommand('redo')), + new Separator(), + + // Cut / Copy / Paste + new Action('editor.action.clipboardCutAction', localize('cut', "Cut"), undefined, true, async () => document.execCommand('cut')), + new Action('editor.action.clipboardCopyAction', localize('copy', "Copy"), undefined, true, async () => document.execCommand('copy')), + new Action('editor.action.clipboardPasteAction', localize('paste', "Paste"), undefined, true, async element => { + + // Native: paste is supported + if (isNative) { + document.execCommand('paste'); + } + + // Web: paste is not supported due to security reasons + else { + const clipboardText = await clipboardService.readText(); + if ( + element instanceof HTMLTextAreaElement || + element instanceof HTMLInputElement + ) { + const selectionStart = element.selectionStart || 0; + const selectionEnd = element.selectionEnd || 0; + + element.value = `${element.value.substring(0, selectionStart)}${clipboardText}${element.value.substring(selectionEnd, element.value.length)}`; + element.selectionStart = selectionStart + clipboardText.length; + element.selectionEnd = element.selectionStart; + } + } + }), + new Separator(), + + // Select All + new Action('editor.action.selectAll', localize('selectAll', "Select All"), undefined, true, async () => document.execCommand('selectAll')) + ); + + contextMenuService.showContextMenu({ + getAnchor: () => standardEvent, + getActions: () => actions, + getActionsContext: () => event.target, + }); +}