Skip to content

Commit

Permalink
Make context element mandatory when showing a context menu.
Browse files Browse the repository at this point in the history
Fixes eclipse-theia#14960

Contributed on behalf of STMicroelectronics

Signed-off-by: Thomas Mäder <t.s.maeder@gmail.com>
  • Loading branch information
tsmaeder committed Feb 19, 2025
1 parent 15f9c39 commit f3cd4b3
Show file tree
Hide file tree
Showing 28 changed files with 49 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class SampleToolbarContribution extends AbstractToolbarContribution
includeAnchorArg: false,
menuPath: ToolbarMenus.SEARCH_WIDGET_DROPDOWN_MENU,
anchor: { x: left, y: bottom },
context: e.currentTarget
});
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/ai-chat-ui/src/browser/chat-input-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export class AIChatInputWidget extends ReactWidget {
this.contextMenuRenderer.render({
menuPath: AIChatInputWidget.CONTEXT_MENU,
anchor: { x: event.posx, y: event.posy },
context: event.target
});
event.preventDefault();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ export class CodePartRenderer
this.contextMenuRenderer.render({
menuPath: ChatViewTreeWidget.CONTEXT_MENU,
anchor: { x: event.posx, y: event.posy },
args: [node, { code }]
args: [node, { code }],
context: event.target
});
event.preventDefault();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,8 @@ export class ChatViewTreeWidget extends TreeWidget {
this.contextMenuRenderer.render({
menuPath: ChatViewTreeWidget.CONTEXT_MENU,
anchor: { x: event.clientX, y: event.clientY },
args: [node]
args: [node],
context: event.currentTarget
});
event.preventDefault();
}
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/browser/context-menu-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ export interface RenderContextMenuOptions {
*/
includeAnchorArg?: boolean;
/**
* A DOM context to use when evaluating any `when` clauses
* of menu items registered for this item.
* A DOM context for the menu to be shown
* Will be used to attach the menu to a window and to evaluate enablement ("when"-clauses)
*/
context?: HTMLElement;
context: HTMLElement;
contextKeyService?: ContextMatcher;
onHide?: () => void;
/**
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/browser/shell/side-panel-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ export class SidePanelHandler {
this.contextMenuRenderer.render({
args: [title.owner],
menuPath: SIDE_PANEL_TOOLBAR_CONTEXT_MENU,
anchor: e
anchor: e,
context: e.currentTarget instanceof HTMLElement ? e.currentTarget : this.tabBar.node
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export class SidebarBottomMenuWidget extends SidebarMenuWidget {
anchor: {
x: button.left + button.width,
y: button.top + button.height,
}
},
context: e.currentTarget
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/browser/shell/sidebar-menu-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export class SidebarMenuWidget extends ReactWidget {
x: button.left + button.width,
y: button.top,
},
context: e.currentTarget,
onHide: () => {
this.preservingContext = false;
if (this.preservedContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ export class TabBarToolbar extends ReactWidget {
menuPath: TAB_BAR_TOOLBAR_CONTEXT_MENU,
args: [this.current],
anchor,
context: this.current?.node,
context: this.current?.node || this.node,
onHide: () => toDisposeOnHide.dispose(),
skipSingleRootNode: true,
});
Expand Down Expand Up @@ -375,7 +375,7 @@ export class TabBarToolbar extends ReactWidget {
menuPath,
args: [this.current],
anchor,
context: this.current?.node,
context: this.current?.node || this.node,
contextKeyService: contextMatcher,
onHide: () => toDisposeOnHide.dispose()
});
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/browser/shell/tab-bars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ export class TabBarRenderer extends TabBar.Renderer {
menuPath: this.contextMenuPath!,
anchor: event,
args: [event],
context: event.currentTarget,
contextKeyService: contextKeyServiceOverlay,
// We'd like to wait until the command triggered by the context menu has been run, but this should let it get through the preamble, at least.
onHide: () => setTimeout(() => { if (this.selectionService) { this.selectionService.selection = oldSelection; } })
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/browser/tree/tree-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,7 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
const args = this.toContextMenuArgs(node);
setTimeout(() => this.contextMenuRenderer.render({
menuPath: contextMenuPath,
context: event.currentTarget,
anchor: { x, y },
args
}), 10);
Expand Down
8 changes: 6 additions & 2 deletions packages/core/src/browser/view-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,11 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
if (event.button === 2 && every(this.containerLayout.iter(), part => !!part.isHidden)) {
event.stopPropagation();
event.preventDefault();
contextMenuRenderer.render({ menuPath: this.contextMenuPath, anchor: event });
contextMenuRenderer.render({
menuPath: this.contextMenuPath,
anchor: event,
context: event.currentTarget instanceof HTMLElement ? event.currentTarget : this.node
});
}
}),
commandRegistry.registerCommand({ id: this.globalHideCommandId }, {
Expand Down Expand Up @@ -436,7 +440,7 @@ export class ViewContainer extends BaseWidget implements StatefulWidget, Applica
if (event.button === 2) {
event.preventDefault();
event.stopPropagation();
this.contextMenuRenderer.render({ menuPath: this.contextMenuPath, anchor: event });
this.contextMenuRenderer.render({ menuPath: this.contextMenuPath, anchor: event, context: this.node });
}
}),
newPart.onTitleChanged(() => this.refreshMenu(newPart)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class ElectronTextInputContextMenuContribution implements FrontendApplica
this.contextMenuRenderer.render({
anchor: event,
menuPath: ElectronTextInputContextMenu.MENU_PATH,
context: event.target,
onHide: () => target.focus()
});
}
Expand Down Expand Up @@ -119,7 +120,8 @@ export class ElectronContextMenuRenderer extends BrowserContextMenuRenderer {
const node = (menuAccess as BrowserContextMenuAccess).menu.node;
const topPanelHeight = document.getElementById('theia-top-panel')?.clientHeight ?? 0;
// ensure the context menu is not displayed outside of the main area
if (node.style.top && parseInt(node.style.top.substring(0, node.style.top.length - 2)) < topPanelHeight) {
const menuRect = node.getBoundingClientRect();
if (menuRect.top < topPanelHeight) {
node.style.top = `${topPanelHeight}px`;
node.style.maxHeight = `calc(${node.style.maxHeight} - ${topPanelHeight}px)`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export class EditorLineNumberContribution implements FrontendApplicationContribu
this.contextMenuRenderer.render({
menuPath: EDITOR_LINENUMBER_CONTEXT_MENU,
anchor: event.event,
context: editor.node,
args,
contextKeyService
});
Expand Down
3 changes: 2 additions & 1 deletion packages/keymaps/src/browser/keybindings-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ export class KeybindingWidget extends ReactWidget implements StatefulWidget {
this.contextMenuRenderer.render({
menuPath: KeybindingWidget.CONTEXT_MENU,
anchor: event.nativeEvent,
args: [item, this]
args: [item, this],
context: event.currentTarget
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ export class MemoryTableWidget extends ReactWidget {
menuPath: MemoryTableWidget.CONTEXT_MENU,
anchor: { x: right, y: top },
args: this.getContextMenuArgs(event),
context: target
});
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export class RegisterTableWidget extends MemoryTableWidget {
menuPath: RegisterTableWidget.CONTEXT_MENU,
anchor: event.nativeEvent,
args: this.getContextMenuArgs(event),
context: curTarget
});
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/monaco/src/browser/monaco-context-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ export class MonacoContextMenuService implements IContextMenuService {
}
}

private getContext(delegate: IContextMenuDelegate): HTMLElement | undefined {
private getContext(delegate: IContextMenuDelegate): HTMLElement {
const anchor = delegate.getAnchor();
if (anchor instanceof HTMLElement) {
return anchor;
} else if (anchor instanceof StandardMouseEvent) {
return anchor.target;
} else {
return undefined;
return window.document.body; // last resort
}
}
showContextMenu(delegate: IContextMenuDelegate): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class NotebookCellToolbarFactory {
menuPath,
includeAnchorArg: false,
args: itemOptions.contextMenuArgs?.(),
context: this.notebookContextManager.context
context: this.notebookContextManager.context || (e.currentTarget as HTMLElement)
}) :
() => this.commandRegistry.executeCommand(menuNode.command!, ...(itemOptions.commandArgs?.() ?? [])),
isVisible: () => menuPath ? true : Boolean(this.commandRegistry.getVisibleHandler(menuNode.command!, ...(itemOptions.commandArgs?.() ?? []))),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,8 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
menuPath: contextMenuPath,
anchor: { x, y },
args,
contextKeyService
contextKeyService,
context: event.currentTarget
}), 10);
}
}
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-ext/src/main/browser/webview/webview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
args: [event.context],
anchor: {
x: domRect.x + event.clientX, y: domRect.y + event.clientY
}
},
context: this.node
});
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export abstract class PreferenceLeafNodeRenderer<ValueType extends JSONValue, In
menuPath: PreferenceMenus.PREFERENCE_EDITOR_CONTEXT_MENU,
anchor: { x: domRect.left, y: domRect.bottom },
args: [{ id: this.id, value }],
context: target,
onHide: () => this.hideCog()
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export class PreferencesScopeTabBar extends TabBar<Widget> implements StatefulWi
this.contextMenuRenderer.render({
menuPath: PreferenceMenus.FOLDER_SCOPE_MENU_PATH,
anchor: { x: tabRect.left, y: tabRect.bottom },
context: folderTabNode,
onHide: () => {
setTimeout(() => toDisposeOnHide.dispose());
if (source === 'click') { folderTabNode.blur(); }
Expand Down
3 changes: 2 additions & 1 deletion packages/scm/src/browser/scm-tree-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,8 @@ export abstract class ScmElement<P extends ScmElement.Props = ScmElement.Props>
contextMenuRenderer.render({
menuPath: this.contextMenuPath,
anchor: event.nativeEvent,
args: this.contextMenuArgs
args: this.contextMenuArgs,
context: event.currentTarget
});
});
};
Expand Down
2 changes: 1 addition & 1 deletion packages/terminal/src/browser/terminal-widget-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ export class TerminalWidgetImpl extends TerminalWidget implements StatefulWidget
const contextMenuListener = (event: MouseEvent) => {
event.preventDefault();
event.stopPropagation();
this.contextMenuRenderer.render({ menuPath: TerminalMenus.TERMINAL_CONTEXT_MENU, anchor: event });
this.contextMenuRenderer.render({ menuPath: TerminalMenus.TERMINAL_CONTEXT_MENU, anchor: event, context: this.node });
};
this.node.addEventListener('contextmenu', contextMenuListener);
this.onDispose(() => this.node.removeEventListener('contextmenu', contextMenuListener));
Expand Down
3 changes: 2 additions & 1 deletion packages/timeline/src/browser/timeline-tree-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export class TimelineItemNode extends React.Component<TimelineItemNode.Props> {
contextMenuRenderer.render({
menuPath: TIMELINE_ITEM_CONTEXT_MENU,
anchor: event.nativeEvent,
args: [timelineItem]
args: [timelineItem],
context: event.currentTarget
});
} finally {
contextKeys.timelineItem.set(currentTimelineItem);
Expand Down
1 change: 1 addition & 0 deletions packages/toolbar/src/browser/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class ToolbarImpl extends TabBarToolbar {
const { menuPath, anchor } = this.getMenuDetailsForClick(event);
return this.contextMenuRenderer.render({
args: contextMenuArgs,
context: event.currentTarget,
menuPath,
anchor,
});
Expand Down
3 changes: 2 additions & 1 deletion packages/vsx-registry/src/browser/vsx-extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,8 @@ export class VSXExtension implements VSXExtensionData, TreeElement {
x: e.clientX,
y: e.clientY,
},
args: [this]
args: [this],
context: e.currentTarget
});
}

Expand Down

0 comments on commit f3cd4b3

Please sign in to comment.