This commit is contained in:
Jeremy Rose 2020-07-06 13:24:54 -07:00 коммит произвёл GitHub
Родитель 2a3437e5b5
Коммит 71a7e1b2e3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 156 добавлений и 131 удалений

Просмотреть файл

@ -96,7 +96,7 @@ Appends the `menuItem` to the menu.
* `id` String
Returns `MenuItem` the item with the specified `id`
Returns `MenuItem | null` the item with the specified `id`
#### `menu.insert(pos, menuItem)`

Просмотреть файл

@ -201,10 +201,10 @@ auto_filenames = {
"lib/browser/api/global-shortcut.ts",
"lib/browser/api/in-app-purchase.ts",
"lib/browser/api/ipc-main.ts",
"lib/browser/api/menu-item-roles.js",
"lib/browser/api/menu-item.js",
"lib/browser/api/menu-utils.js",
"lib/browser/api/menu.js",
"lib/browser/api/menu-item-roles.ts",
"lib/browser/api/menu-item.ts",
"lib/browser/api/menu-utils.ts",
"lib/browser/api/menu.ts",
"lib/browser/api/message-channel.ts",
"lib/browser/api/module-list.ts",
"lib/browser/api/native-theme.ts",

Просмотреть файл

@ -1,44 +1,56 @@
'use strict';
const { app } = require('electron');
import { app, BrowserWindow, WebContents, MenuItemConstructorOptions } from 'electron';
const isMac = process.platform === 'darwin';
const isWindows = process.platform === 'win32';
const isLinux = process.platform === 'linux';
const roles = {
type RoleId = 'about' | 'close' | 'copy' | 'cut' | 'delete' | 'forcereload' | 'front' | 'help' | 'hide' | 'hideothers' | 'minimize' |
'paste' | 'pasteandmatchstyle' | 'quit' | 'redo' | 'reload' | 'resetzoom' | 'selectall' | 'services' | 'recentdocuments' | 'clearrecentdocuments' | 'startspeaking' | 'stopspeaking' |
'toggledevtools' | 'togglefullscreen' | 'undo' | 'unhide' | 'window' | 'zoom' | 'zoomin' | 'zoomout' | 'appmenu' | 'filemenu' | 'editmenu' | 'viewmenu' | 'windowmenu'
interface Role {
label: string;
accelerator?: string;
windowMethod?: ((window: BrowserWindow) => void);
webContentsMethod?: ((webContents: WebContents) => void);
appMethod?: () => void;
registerAccelerator?: boolean;
nonNativeMacOSRole?: boolean;
submenu?: MenuItemConstructorOptions[];
}
export const roleList: Record<RoleId, Role> = {
about: {
get label () {
return isLinux ? 'About' : `About ${app.name}`;
},
...(isWindows && { appMethod: 'showAboutPanel' })
...(isWindows && { appMethod: () => app.showAboutPanel() })
},
close: {
label: isMac ? 'Close Window' : 'Close',
accelerator: 'CommandOrControl+W',
windowMethod: 'close'
windowMethod: w => w.close()
},
copy: {
label: 'Copy',
accelerator: 'CommandOrControl+C',
webContentsMethod: 'copy',
webContentsMethod: wc => wc.copy(),
registerAccelerator: false
},
cut: {
label: 'Cut',
accelerator: 'CommandOrControl+X',
webContentsMethod: 'cut',
webContentsMethod: wc => wc.cut(),
registerAccelerator: false
},
delete: {
label: 'Delete',
webContentsMethod: 'delete'
webContentsMethod: wc => wc.delete()
},
forcereload: {
label: 'Force Reload',
accelerator: 'Shift+CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: (window) => {
windowMethod: (window: BrowserWindow) => {
window.webContents.reloadIgnoringCache();
}
},
@ -61,18 +73,18 @@ const roles = {
minimize: {
label: 'Minimize',
accelerator: 'CommandOrControl+M',
windowMethod: 'minimize'
windowMethod: w => w.minimize()
},
paste: {
label: 'Paste',
accelerator: 'CommandOrControl+V',
webContentsMethod: 'paste',
webContentsMethod: wc => wc.paste(),
registerAccelerator: false
},
pasteandmatchstyle: {
label: 'Paste and Match Style',
accelerator: isMac ? 'Cmd+Option+Shift+V' : 'Shift+CommandOrControl+V',
webContentsMethod: 'pasteAndMatchStyle',
webContentsMethod: wc => wc.pasteAndMatchStyle(),
registerAccelerator: false
},
quit: {
@ -84,31 +96,31 @@ const roles = {
}
},
accelerator: isWindows ? undefined : 'CommandOrControl+Q',
appMethod: 'quit'
appMethod: () => app.quit()
},
redo: {
label: 'Redo',
accelerator: isWindows ? 'Control+Y' : 'Shift+CommandOrControl+Z',
webContentsMethod: 'redo'
webContentsMethod: wc => wc.redo()
},
reload: {
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
nonNativeMacOSRole: true,
windowMethod: 'reload'
windowMethod: w => w.reload()
},
resetzoom: {
label: 'Actual Size',
accelerator: 'CommandOrControl+0',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContentsMethod: (webContents: WebContents) => {
webContents.zoomLevel = 0;
}
},
selectall: {
label: 'Select All',
accelerator: 'CommandOrControl+A',
webContentsMethod: 'selectAll'
webContentsMethod: wc => wc.selectAll()
},
services: {
label: 'Services'
@ -129,19 +141,19 @@ const roles = {
label: 'Toggle Developer Tools',
accelerator: isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I',
nonNativeMacOSRole: true,
windowMethod: 'toggleDevTools'
windowMethod: w => w.webContents.toggleDevTools()
},
togglefullscreen: {
label: 'Toggle Full Screen',
accelerator: isMac ? 'Control+Command+F' : 'F11',
windowMethod: (window) => {
windowMethod: (window: BrowserWindow) => {
window.setFullScreen(!window.isFullScreen());
}
},
undo: {
label: 'Undo',
accelerator: 'CommandOrControl+Z',
webContentsMethod: 'undo'
webContentsMethod: wc => wc.undo()
},
unhide: {
label: 'Show All'
@ -156,7 +168,7 @@ const roles = {
label: 'Zoom In',
accelerator: 'CommandOrControl+Plus',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContentsMethod: (webContents: WebContents) => {
webContents.zoomLevel += 0.5;
}
},
@ -164,7 +176,7 @@ const roles = {
label: 'Zoom Out',
accelerator: 'CommandOrControl+-',
nonNativeMacOSRole: true,
webContentsMethod: (webContents) => {
webContentsMethod: (webContents: WebContents) => {
webContents.zoomLevel -= 0.5;
}
},
@ -214,11 +226,11 @@ const roles = {
{ role: 'stopSpeaking' }
]
}
] : [
] as MenuItemConstructorOptions[] : [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
] as MenuItemConstructorOptions[])
]
},
// View submenu
@ -245,40 +257,38 @@ const roles = {
...(isMac ? [
{ type: 'separator' },
{ role: 'front' }
] : [
] as MenuItemConstructorOptions[] : [
{ role: 'close' }
])
] as MenuItemConstructorOptions[])
]
}
};
exports.roleList = roles;
const canExecuteRole = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return false;
const canExecuteRole = (role: keyof typeof roleList) => {
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return false;
if (!isMac) return true;
// macOS handles all roles natively except for a few
return roles[role].nonNativeMacOSRole;
return roleList[role].nonNativeMacOSRole;
};
exports.getDefaultLabel = (role) => {
return Object.prototype.hasOwnProperty.call(roles, role) ? roles[role].label : '';
};
export function getDefaultLabel (role: RoleId) {
return Object.prototype.hasOwnProperty.call(roleList, role) ? roleList[role].label : '';
}
exports.getDefaultAccelerator = (role) => {
if (Object.prototype.hasOwnProperty.call(roles, role)) return roles[role].accelerator;
};
export function getDefaultAccelerator (role: RoleId) {
if (Object.prototype.hasOwnProperty.call(roleList, role)) return roleList[role].accelerator;
}
exports.shouldRegisterAccelerator = (role) => {
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roles, role) && roles[role].registerAccelerator !== undefined;
return hasRoleRegister ? roles[role].registerAccelerator : true;
};
export function shouldRegisterAccelerator (role: RoleId) {
const hasRoleRegister = Object.prototype.hasOwnProperty.call(roleList, role) && roleList[role].registerAccelerator !== undefined;
return hasRoleRegister ? roleList[role].registerAccelerator : true;
}
exports.getDefaultSubmenu = (role) => {
if (!Object.prototype.hasOwnProperty.call(roles, role)) return;
export function getDefaultSubmenu (role: RoleId) {
if (!Object.prototype.hasOwnProperty.call(roleList, role)) return;
let { submenu } = roles[role];
let { submenu } = roleList[role];
// remove null items from within the submenu
if (Array.isArray(submenu)) {
@ -286,35 +296,27 @@ exports.getDefaultSubmenu = (role) => {
}
return submenu;
};
}
exports.execute = (role, focusedWindow, focusedWebContents) => {
export function execute (role: RoleId, focusedWindow: BrowserWindow, focusedWebContents: WebContents) {
if (!canExecuteRole(role)) return false;
const { appMethod, webContentsMethod, windowMethod } = roles[role];
const { appMethod, webContentsMethod, windowMethod } = roleList[role];
if (appMethod) {
app[appMethod]();
appMethod();
return true;
}
if (windowMethod && focusedWindow != null) {
if (typeof windowMethod === 'function') {
windowMethod(focusedWindow);
} else {
focusedWindow[windowMethod]();
}
windowMethod(focusedWindow);
return true;
}
if (webContentsMethod && focusedWebContents != null) {
if (typeof webContentsMethod === 'function') {
webContentsMethod(focusedWebContents);
} else {
focusedWebContents[webContentsMethod]();
}
webContentsMethod(focusedWebContents);
return true;
}
return false;
};
}

Просмотреть файл

@ -1,12 +1,9 @@
'use strict';
const roles = require('@electron/internal/browser/api/menu-item-roles');
import * as roles from './menu-item-roles';
import { Menu, Event, BrowserWindow, WebContents } from 'electron';
let nextCommandId = 0;
const MenuItem = function (options) {
const { Menu } = require('electron');
const MenuItem = function (this: any, options: any) {
// Preserve extra fields specified by user
for (const key in options) {
if (!(key in this)) this[key] = options[key];
@ -47,7 +44,7 @@ const MenuItem = function (options) {
this.overrideReadOnlyProperty('commandId', ++nextCommandId);
const click = options.click;
this.click = (event, focusedWindow, focusedWebContents) => {
this.click = (event: Event, focusedWindow: BrowserWindow, focusedWebContents: WebContents) => {
// Manually flip the checked flags when clicked.
if (this.type === 'checkbox' || this.type === 'radio') {
this.checked = !this.checked;
@ -69,13 +66,13 @@ MenuItem.prototype.getDefaultRoleAccelerator = function () {
return roles.getDefaultAccelerator(this.role);
};
MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
MenuItem.prototype.overrideProperty = function (name: string, defaultValue: any = null) {
if (this[name] == null) {
this[name] = defaultValue;
}
};
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
MenuItem.prototype.overrideReadOnlyProperty = function (name: string, defaultValue: any) {
this.overrideProperty(name, defaultValue);
Object.defineProperty(this, name, {
enumerable: true,

Просмотреть файл

@ -1,6 +1,4 @@
'use strict';
function splitArray (arr, predicate) {
function splitArray<T> (arr: T[], predicate: (x: T) => boolean) {
const result = arr.reduce((multi, item) => {
const current = multi[multi.length - 1];
if (predicate(item)) {
@ -9,7 +7,7 @@ function splitArray (arr, predicate) {
current.push(item);
}
return multi;
}, [[]]);
}, [[]] as T[][]);
if (result[result.length - 1].length === 0) {
return result.slice(0, result.length - 1);
@ -17,7 +15,7 @@ function splitArray (arr, predicate) {
return result;
}
function joinArrays (arrays, joinIDs) {
function joinArrays (arrays: any[][], joinIDs: any[]) {
return arrays.reduce((joined, arr, i) => {
if (i > 0 && arr.length) {
if (joinIDs.length > 0) {
@ -31,14 +29,14 @@ function joinArrays (arrays, joinIDs) {
}, []);
}
function pushOntoMultiMap (map, key, value) {
function pushOntoMultiMap<K, V> (map: Map<K, V[]>, key: K, value: V) {
if (!map.has(key)) {
map.set(key, []);
}
map.get(key).push(value);
map.get(key)!.push(value);
}
function indexOfGroupContainingID (groups, id, ignoreGroup) {
function indexOfGroupContainingID<T> (groups: {id?: T}[][], id: T, ignoreGroup: {id?: T}[]) {
return groups.findIndex(
candidateGroup =>
candidateGroup !== ignoreGroup &&
@ -50,11 +48,11 @@ function indexOfGroupContainingID (groups, id, ignoreGroup) {
// Sort nodes topologically using a depth-first approach. Encountered cycles
// are broken.
function sortTopologically (originalOrder, edgesById) {
const sorted = [];
const marked = new Set();
function sortTopologically<T> (originalOrder: T[], edgesById: Map<T, T[]>) {
const sorted = [] as T[];
const marked = new Set<T>();
const visit = (mark) => {
const visit = (mark: T) => {
if (marked.has(mark)) return;
marked.add(mark);
const edges = edgesById.get(mark);
@ -68,7 +66,7 @@ function sortTopologically (originalOrder, edgesById) {
return sorted;
}
function attemptToMergeAGroup (groups) {
function attemptToMergeAGroup<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
for (const item of group) {
@ -87,7 +85,7 @@ function attemptToMergeAGroup (groups) {
return false;
}
function mergeGroups (groups) {
function mergeGroups<T> (groups: {before?: T[], after?: T[], id?: T}[][]) {
let merged = true;
while (merged) {
merged = attemptToMergeAGroup(groups);
@ -95,7 +93,7 @@ function mergeGroups (groups) {
return groups;
}
function sortItemsInGroup (group) {
function sortItemsInGroup<T> (group: {before?: T[], after?: T[], id?: T}[]) {
const originalOrder = group.map((node, i) => i);
const edges = new Map();
const idToIndex = new Map(group.map((item, i) => [item.id, i]));
@ -123,7 +121,7 @@ function sortItemsInGroup (group) {
return sortedNodes.map(i => group[i]);
}
function findEdgesInGroup (groups, i, edges) {
function findEdgesInGroup<T> (groups: {beforeGroupContaining?: T[], afterGroupContaining?: T[], id?: T}[][], i: number, edges: Map<any, any>) {
const group = groups[i];
for (const item of group) {
if (item.beforeGroupContaining) {
@ -147,7 +145,7 @@ function findEdgesInGroup (groups, i, edges) {
}
}
function sortGroups (groups) {
function sortGroups<T> (groups: {id?: T}[][]) {
const originalOrder = groups.map((item, i) => i);
const edges = new Map();
@ -159,8 +157,8 @@ function sortGroups (groups) {
return sortedGroupIndexes.map(i => groups[i]);
}
function sortMenuItems (menuItems) {
const isSeparator = (item) => item.type === 'separator';
export function sortMenuItems (menuItems: {type?: string, id?: string}[]) {
const isSeparator = (item: {type?: string}) => item.type === 'separator';
const separators = menuItems.filter(i => i.type === 'separator');
// Split the items into their implicit groups based upon separators.
@ -172,5 +170,3 @@ function sortMenuItems (menuItems) {
const joined = joinArrays(sortedGroups, separators);
return joined;
}
module.exports = { sortMenuItems };

Просмотреть файл

@ -1,13 +1,11 @@
'use strict';
import { BaseWindow, MenuItem, webContents, Menu as MenuType, BrowserWindow, MenuItemConstructorOptions } from 'electron';
import { sortMenuItems } from './menu-utils';
const { BaseWindow, MenuItem, webContents } = require('electron');
const { sortMenuItems } = require('@electron/internal/browser/api/menu-utils');
const EventEmitter = require('events').EventEmitter;
const v8Util = process._linkedBinding('electron_common_v8_util');
const bindings = process._linkedBinding('electron_browser_menu');
const { Menu } = bindings;
let applicationMenu = null;
const { Menu } = bindings as { Menu: typeof MenuType };
let applicationMenu: MenuType | null = null;
let groupIdIndex = 0;
/* Instance Methods */
@ -19,17 +17,17 @@ Menu.prototype._init = function () {
};
Menu.prototype._isCommandIdChecked = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].checked : undefined;
return this.commandsMap[id] ? this.commandsMap[id].checked : false;
};
Menu.prototype._isCommandIdEnabled = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].enabled : undefined;
return this.commandsMap[id] ? this.commandsMap[id].enabled : false;
};
Menu.prototype._shouldCommandIdWorkWhenHidden = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].acceleratorWorksWhenHidden : undefined;
return this.commandsMap[id] ? !!this.commandsMap[id].acceleratorWorksWhenHidden : false;
};
Menu.prototype._isCommandIdVisible = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].visible : undefined;
return this.commandsMap[id] ? this.commandsMap[id].visible : false;
};
Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator) {
@ -40,13 +38,14 @@ Menu.prototype._getAcceleratorForCommandId = function (id, useDefaultAccelerator
};
Menu.prototype._shouldRegisterAcceleratorForCommandId = function (id) {
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : undefined;
return this.commandsMap[id] ? this.commandsMap[id].registerAccelerator : false;
};
Menu.prototype._executeCommand = function (event, id) {
const command = this.commandsMap[id];
if (!command) return;
command.click(event, BaseWindow.getFocusedWindow(), webContents.getFocusedWebContents());
const focusedWindow = BaseWindow.getFocusedWindow();
command.click(event, focusedWindow instanceof BrowserWindow ? focusedWindow : undefined, webContents.getFocusedWebContents());
};
Menu.prototype._menuWillShow = function () {
@ -73,17 +72,17 @@ Menu.prototype.popup = function (options = {}) {
// find which window to use
const wins = BaseWindow.getAllWindows();
if (!wins || wins.indexOf(window) === -1) {
window = BaseWindow.getFocusedWindow();
if (!wins || wins.indexOf(window as any) === -1) {
window = BaseWindow.getFocusedWindow() as any;
if (!window && wins && wins.length > 0) {
window = wins[0];
window = wins[0] as any;
}
if (!window) {
throw new Error('Cannot open Menu without a BaseWindow present');
}
}
this.popupAt(window, x, y, positioningItem, callback);
this.popupAt(window as unknown as BaseWindow, x, y, positioningItem, callback);
return { browserWindow: window, x, y, position: positioningItem };
};
@ -102,8 +101,9 @@ Menu.prototype.getMenuItemById = function (id) {
let found = items.find(item => item.id === id) || null;
for (let i = 0; !found && i < items.length; i++) {
if (items[i].submenu) {
found = items[i].submenu.getMenuItemById(id);
const { submenu } = items[i];
if (submenu) {
found = submenu.getMenuItemById(id);
}
}
return found;
@ -155,7 +155,7 @@ Menu.getApplicationMenu = () => applicationMenu;
Menu.sendActionToFirstResponder = bindings.sendActionToFirstResponder;
// set application menu with a preexisting menu
Menu.setApplicationMenu = function (menu) {
Menu.setApplicationMenu = function (menu: MenuType) {
if (menu && menu.constructor !== Menu) {
throw new TypeError('Invalid menu');
}
@ -200,7 +200,7 @@ Menu.buildFromTemplate = function (template) {
/* Helper Functions */
// validate the template against having the wrong attribute
function areValidTemplateItems (template) {
function areValidTemplateItems (template: (MenuItemConstructorOptions | MenuItem)[]) {
return template.every(item =>
item != null &&
typeof item === 'object' &&
@ -209,7 +209,7 @@ function areValidTemplateItems (template) {
item.type === 'separator'));
}
function sortTemplate (template) {
function sortTemplate (template: (MenuItemConstructorOptions | MenuItem)[]) {
const sorted = sortMenuItems(template);
for (const item of sorted) {
if (Array.isArray(item.submenu)) {
@ -220,15 +220,15 @@ function sortTemplate (template) {
}
// Search between separators to find a radio menu item and return its group id
function generateGroupId (items, pos) {
function generateGroupId (items: (MenuItemConstructorOptions | MenuItem)[], pos: number) {
if (pos > 0) {
for (let idx = pos - 1; idx >= 0; idx--) {
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'separator') break;
}
} else if (pos < items.length) {
for (let idx = pos; idx <= items.length - 1; idx++) {
if (items[idx].type === 'radio') return items[idx].groupId;
if (items[idx].type === 'radio') return (items[idx] as any).groupId;
if (items[idx].type === 'separator') break;
}
}
@ -236,7 +236,7 @@ function generateGroupId (items, pos) {
return groupIdIndex;
}
function removeExtraSeparators (items) {
function removeExtraSeparators (items: (MenuItemConstructorOptions | MenuItem)[]) {
// fold adjacent separators together
let ret = items.filter((e, idx, arr) => {
if (e.visible === false) return true;
@ -252,7 +252,7 @@ function removeExtraSeparators (items) {
return ret;
}
function insertItemByType (item, pos) {
function insertItemByType (this: MenuType, item: MenuItem, pos: number) {
const types = {
normal: () => this.insertItem(pos, item.commandId, item.label),
checkbox: () => this.insertCheckItem(pos, item.commandId, item.label),

10
spec-main/ambient.d.ts поставляемый
Просмотреть файл

@ -1,16 +1,6 @@
declare let standardScheme: string;
declare namespace Electron {
interface Menu {
_executeCommand(event: any, id: number): void;
_menuWillShow(): void;
getAcceleratorTextAt(index: number): string;
}
interface MenuItem {
getDefaultRoleAccelerator(): Accelerator | undefined;
}
interface WebContents {
getOwnerBrowserWindow(): BrowserWindow;
getWebPreferences(): any;

40
typings/internal-electron.d.ts поставляемый
Просмотреть файл

@ -107,6 +107,45 @@ declare namespace Electron {
length(): number;
}
interface Menu {
_init(): void;
_isCommandIdChecked(id: string): boolean;
_isCommandIdEnabled(id: string): boolean;
_shouldCommandIdWorkWhenHidden(id: string): boolean;
_isCommandIdVisible(id: string): boolean;
_getAcceleratorForCommandId(id: string, useDefaultAccelerator: boolean): Accelerator | undefined;
_shouldRegisterAcceleratorForCommandId(id: string): boolean;
_callMenuWillShow(): void;
_executeCommand(event: any, id: number): void;
_menuWillShow(): void;
commandsMap: Record<string, MenuItem>;
groupsMap: Record<string, {
checked: boolean;
}[]>;
getItemCount(): number;
popupAt(window: BaseWindow, x: number, y: number, positioning: number, callback: () => void): void;
closePopupAt(id: number): void;
setSublabel(index: number, label: string): void;
setToolTip(index: number, tooltip: string): void;
setIcon(index: number, image: string | NativeImage): void;
setRole(index: number, role: string): void;
insertItem(index: number, commandId: number, label: string): void;
insertCheckItem(index: number, commandId: number, label: string): void;
insertRadioItem(index: number, commandId: number, label: string, groupId: number): void;
insertSeparator(index: number): void;
insertSubMenu(index: number, commandId: number, label: string, submenu?: Menu): void;
delegate?: any;
getAcceleratorTextAt(index: number): string;
}
interface MenuItem {
overrideReadOnlyProperty(property: string, value: any): void;
groupId: number;
getDefaultRoleAccelerator(): Accelerator | undefined;
acceleratorWorksWhenHidden?: boolean;
}
const deprecate: ElectronInternal.DeprecationUtil;
namespace Main {
@ -123,6 +162,7 @@ declare namespace Electron {
static getAllWindows(): BaseWindow[];
isFocused(): boolean;
static getFocusedWindow(): BaseWindow | undefined;
setMenu(menu: Menu): void;
}
class WebContentsView {
constructor(options: BrowserWindowConstructorOptions)