sussudio
Version:
An unofficial VS Code Internal API
61 lines (60 loc) • 2.63 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BrowserWindow, Menu, MenuItem } from 'electron';
import { validatedIpcMain } from "../../ipc/electron-main/ipcMain.mjs";
import { withNullAsUndefined } from "../../../common/types.mjs";
import { CONTEXT_MENU_CHANNEL, CONTEXT_MENU_CLOSE_CHANNEL } from "../common/contextmenu.mjs";
export function registerContextMenuListener() {
validatedIpcMain.on(CONTEXT_MENU_CHANNEL, (event, contextMenuId, items, onClickChannel, options) => {
const menu = createMenu(event, onClickChannel, items);
menu.popup({
window: withNullAsUndefined(BrowserWindow.fromWebContents(event.sender)),
x: options ? options.x : undefined,
y: options ? options.y : undefined,
positioningItem: options ? options.positioningItem : undefined,
callback: () => {
// Workaround for https://github.com/microsoft/vscode/issues/72447
// It turns out that the menu gets GC'ed if not referenced anymore
// As such we drag it into this scope so that it is not being GC'ed
if (menu) {
event.sender.send(CONTEXT_MENU_CLOSE_CHANNEL, contextMenuId);
}
}
});
});
}
function createMenu(event, onClickChannel, items) {
const menu = new Menu();
items.forEach(item => {
let menuitem;
// Separator
if (item.type === 'separator') {
menuitem = new MenuItem({
type: item.type,
});
}
// Sub Menu
else if (Array.isArray(item.submenu)) {
menuitem = new MenuItem({
submenu: createMenu(event, onClickChannel, item.submenu),
label: item.label
});
}
// Normal Menu Item
else {
menuitem = new MenuItem({
label: item.label,
type: item.type,
accelerator: item.accelerator,
checked: item.checked,
enabled: item.enabled,
visible: item.visible,
click: (menuItem, win, contextmenuEvent) => event.sender.send(onClickChannel, item.id, contextmenuEvent)
});
}
menu.append(menuitem);
});
return menu;
}