[go: nahoru, domu]

Skip to content

Commit

Permalink
Adds preventDefaultContextMenuItems option
Browse files Browse the repository at this point in the history
This allows webviews to opt-out of the default (cut/copy/paste) context menu items
  • Loading branch information
eamodio committed Jul 15, 2022
1 parent 516bc4e commit 71f0180
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/vs/workbench/api/browser/mainThreadWebviewPanels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,5 +371,6 @@ function reviveWebviewOptions(panelOptions: extHostProtocol.IWebviewPanelOptions
return {
enableFindWidget: panelOptions.enableFindWidget,
retainContextWhenHidden: panelOptions.retainContextWhenHidden,
preventDefaultContextMenuItems: panelOptions.preventDefaultContextMenuItems,
};
}
2 changes: 1 addition & 1 deletion src/vs/workbench/api/browser/mainThreadWebviewViews.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class MainThreadWebviewsViews extends Disposable implements extHostProtoc
public $registerWebviewViewProvider(
extensionData: extHostProtocol.WebviewExtensionDescription,
viewType: string,
options: { retainContextWhenHidden?: boolean; serializeBuffersForPostMessage: boolean }
options: { retainContextWhenHidden?: boolean; preventDefaultContextMenuItems?: boolean; serializeBuffersForPostMessage: boolean }
): void {
if (this._webviewViewProviders.has(viewType)) {
throw new Error(`View provider for ${viewType} already registered`);
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerWebviewViewProvider(viewId: string, provider: vscode.WebviewViewProvider, options?: {
webviewOptions?: {
retainContextWhenHidden?: boolean;
preventDefaultContextMenuItems?: boolean;
};
}) {
return extHostWebviewViews.registerWebviewViewProvider(extension, viewId, provider, options?.webviewOptions);
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ export interface IWebviewContentOptions {
export interface IWebviewPanelOptions {
readonly enableFindWidget?: boolean;
readonly retainContextWhenHidden?: boolean;
readonly preventDefaultContextMenuItems?: boolean;
}

export interface CustomTextEditorCapabilities {
Expand Down Expand Up @@ -846,7 +847,7 @@ export interface MainThreadCustomEditorsShape extends IDisposable {
}

export interface MainThreadWebviewViewsShape extends IDisposable {
$registerWebviewViewProvider(extension: WebviewExtensionDescription, viewType: string, options: { retainContextWhenHidden?: boolean; serializeBuffersForPostMessage: boolean }): void;
$registerWebviewViewProvider(extension: WebviewExtensionDescription, viewType: string, options: { retainContextWhenHidden?: boolean; preventDefaultContextMenuItems?: boolean; serializeBuffersForPostMessage: boolean }): void;
$unregisterWebviewViewProvider(viewType: string): void;

$setWebviewViewTitle(handle: WebviewHandle, value: string | undefined): void;
Expand Down
5 changes: 5 additions & 0 deletions src/vs/workbench/api/common/extHostCustomEditors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { ExtHostWebviews, shouldSerializeBuffersForPostMessage, toExtensionData } from 'vs/workbench/api/common/extHostWebview';
import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import type * as vscode from 'vscode';
import { Cache } from './cache';
import * as extHostProtocol from './extHost.protocol';
Expand Down Expand Up @@ -178,6 +179,10 @@ export class ExtHostCustomEditors implements extHostProtocol.ExtHostCustomEditor
provider: vscode.CustomReadonlyEditorProvider | vscode.CustomTextEditorProvider,
options: { webviewOptions?: vscode.WebviewPanelOptions; supportsMultipleEditorsPerDocument?: boolean },
): vscode.Disposable {
if (options?.webviewOptions?.preventDefaultContextMenuItems) {
checkProposedApiEnabled(extension, 'webviewContextMenus');
}

const disposables = new DisposableStore();
if (isCustomTextEditorProvider(provider)) {
disposables.add(this._editorProviders.addTextProvider(viewType, extension, provider));
Expand Down
6 changes: 6 additions & 0 deletions src/vs/workbench/api/common/extHostWebviewPanels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
import { serializeWebviewOptions, ExtHostWebview, ExtHostWebviews, toExtensionData, shouldSerializeBuffersForPostMessage } from 'vs/workbench/api/common/extHostWebview';
import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import type * as vscode from 'vscode';
import * as extHostProtocol from './extHost.protocol';
import * as extHostTypes from './extHostTypes';
Expand Down Expand Up @@ -197,6 +198,10 @@ export class ExtHostWebviewPanels implements extHostProtocol.ExtHostWebviewPanel
showOptions: vscode.ViewColumn | { viewColumn: vscode.ViewColumn; preserveFocus?: boolean },
options: (vscode.WebviewPanelOptions & vscode.WebviewOptions) = {},
): vscode.WebviewPanel {
if (options.preventDefaultContextMenuItems) {
checkProposedApiEnabled(extension, 'webviewContextMenus');
}

const viewColumn = typeof showOptions === 'object' ? showOptions.viewColumn : showOptions;
const webviewShowOptions = {
viewColumn: typeConverters.ViewColumn.from(viewColumn),
Expand Down Expand Up @@ -317,5 +322,6 @@ function serializeWebviewPanelOptions(options: vscode.WebviewPanelOptions): extH
return {
enableFindWidget: options.enableFindWidget,
retainContextWhenHidden: options.retainContextWhenHidden,
preventDefaultContextMenuItems: options.preventDefaultContextMenuItems,
};
}
6 changes: 6 additions & 0 deletions src/vs/workbench/api/common/extHostWebviewView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,21 @@ export class ExtHostWebviewViews implements extHostProtocol.ExtHostWebviewViewsS
provider: vscode.WebviewViewProvider,
webviewOptions?: {
retainContextWhenHidden?: boolean;
preventDefaultContextMenuItems?: boolean;
},
): vscode.Disposable {
if (webviewOptions?.preventDefaultContextMenuItems) {
checkProposedApiEnabled(extension, 'webviewContextMenus');
}

if (this._viewProviders.has(viewType)) {
throw new Error(`View provider for '${viewType}' already registered`);
}

this._viewProviders.set(viewType, { provider, extension });
this._proxy.$registerWebviewViewProvider(toExtensionData(extension), viewType, {
retainContextWhenHidden: webviewOptions?.retainContextWhenHidden,
preventDefaultContextMenuItems: webviewOptions?.preventDefaultContextMenuItems,
serializeBuffersForPostMessage: shouldSerializeBuffersForPostMessage(extension),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MultiCommand, RedoCommand, SelectAllCommand, UndoCommand } from 'vs/edi
import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/browser/clipboard';
import * as nls from 'vs/nls';
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IWebviewService, IWebview } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
Expand Down Expand Up @@ -44,6 +45,8 @@ overrideCommandForWebview(CopyAction, webview => webview.copy());
overrideCommandForWebview(PasteAction, webview => webview.paste());
overrideCommandForWebview(CutAction, webview => webview.cut());

export const PreventDefaultContextMenuItemsContextKeyName = 'preventDefaultContextMenuItems';

if (CutAction) {
MenuRegistry.appendMenuItem(MenuId.WebviewContext, {
command: {
Expand All @@ -52,6 +55,7 @@ if (CutAction) {
},
group: '5_cutcopypaste',
order: 1,
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
});
}

Expand All @@ -63,6 +67,7 @@ if (CopyAction) {
},
group: '5_cutcopypaste',
order: 2,
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
});
}

Expand All @@ -74,5 +79,6 @@ if (PasteAction) {
},
group: '5_cutcopypaste',
order: 3,
when: ContextKeyExpr.not(PreventDefaultContextMenuItemsContextKeyName),
});
}
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/webview/browser/webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export interface WebviewOptions {
readonly enableFindWidget?: boolean;
readonly tryRestoreScrollPosition?: boolean;
readonly retainContextWhenHidden?: boolean;
readonly preventDefaultContextMenuItems?: boolean;
transformCssVariables?(styles: WebviewStyles): WebviewStyles;
}

Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/webview/browser/webviewElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { asWebviewUri, decodeAuthority, webviewGenericCspSource, webviewRootReso
import { loadLocalResource, WebviewResourceResponse } from 'vs/workbench/contrib/webview/browser/resourceLoading';
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
import { areWebviewContentOptionsEqual, IWebview, WebviewContentOptions, WebviewExtensionDescription, WebviewMessageReceivedEvent, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
import { PreventDefaultContextMenuItemsContextKeyName } from 'vs/workbench/contrib/webview/browser/webview.contribution';
import { WebviewFindDelegate, WebviewFindWidget } from 'vs/workbench/contrib/webview/browser/webviewFindWidget';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';

Expand Down Expand Up @@ -343,6 +344,7 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
contextMenuService.showContextMenu({
getActions: () => {
const contextKeyService = this._contextKeyService!.createOverlay([
[PreventDefaultContextMenuItemsContextKeyName, this.options.preventDefaultContextMenuItems],
['webview', this.providedId],
['webviewItem', data.context.item],
['webviewItemElement', data.context.itemElement],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const allApiProposals = Object.freeze({
timeline: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.timeline.d.ts',
tokenInformation: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.tokenInformation.d.ts',
treeViewReveal: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.treeViewReveal.d.ts',
webviewContextMenus: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.webviewContextMenus.d.ts',
workspaceTrust: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.workspaceTrust.d.ts'
});
export type ApiProposalName = keyof typeof allApiProposals;
52 changes: 52 additions & 0 deletions src/vscode-dts/vscode.proposed.webviewContextMenus.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

declare module 'vscode' {

// https://github.com/microsoft/vscode/issues/54285 @eamodio

export interface WebviewPanelOptions {
/**
* Controls if the webview panel's context menu will have default items (e.g. cut, copy, paste) automatically provided or not.
*
* Defaults to `false`.
*/
readonly preventDefaultContextMenuItems?: boolean;
}

export namespace window {
export function registerWebviewViewProvider(viewId: string, provider: WebviewViewProvider, options?: {
/**
* Content settings for the webview created for this view.
*/
readonly webviewOptions?: {
/**
* Controls if the webview element itself (iframe) is kept around even when the view
* is no longer visible.
*
* Normally the webview's html context is created when the view becomes visible
* and destroyed when it is hidden. Extensions that have complex state
* or UI can set the `retainContextWhenHidden` to make the editor keep the webview
* context around, even when the webview moves to a background tab. When a webview using
* `retainContextWhenHidden` becomes hidden, its scripts and other dynamic content are suspended.
* When the view becomes visible again, the context is automatically restored
* in the exact same state it was in originally. You cannot send messages to a
* hidden webview, even with `retainContextWhenHidden` enabled.
*
* `retainContextWhenHidden` has a high memory overhead and should only be used if
* your view's context cannot be quickly saved and restored.
*/
readonly retainContextWhenHidden?: boolean;

/**
* Controls if the webview view's context menu will have default items (e.g. cut, copy, paste) automatically provided or not.
*
* Defaults to `false`.
*/
readonly preventDefaultContextMenuItems?: boolean;
};
}): Disposable;
}
}

0 comments on commit 71f0180

Please sign in to comment.