diff --git a/atom/browser/ui/cocoa/atom_menu_controller.mm b/atom/browser/ui/cocoa/atom_menu_controller.mm index 642721e6bd..26cf2a94ed 100644 --- a/atom/browser/ui/cocoa/atom_menu_controller.mm +++ b/atom/browser/ui/cocoa/atom_menu_controller.mm @@ -38,6 +38,7 @@ Role kRolesMap[] = { { @selector(performMiniaturize:), "minimize" }, { @selector(performClose:), "close" }, { @selector(performZoom:), "zoom" }, + { @selector(terminate:), "quit" }, }; } // namespace diff --git a/default_app/main.js b/default_app/main.js index 4e5ea96b03..4c3c658420 100644 --- a/default_app/main.js +++ b/default_app/main.js @@ -214,7 +214,7 @@ app.once('ready', () => { { label: 'Quit ' + app.getName(), accelerator: 'Command+Q', - click () { app.quit() } + role: 'quit' } ] }) @@ -243,6 +243,18 @@ app.once('ready', () => { ] } + if (process.platform === 'win32') { + template.unshift({ + label: 'File', + submenu: [ + { + label: 'Exit', + role: 'quit' + } + ] + }) + } + const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) }) diff --git a/docs/api/menu-item.md b/docs/api/menu-item.md index ec3fef55e5..391b639e11 100644 --- a/docs/api/menu-item.md +++ b/docs/api/menu-item.md @@ -51,6 +51,7 @@ The `role` property can have following values: * `delete` * `minimize` - Minimize current window * `close` - Close current window +* `quit`- Quit the application On macOS `role` can also have following additional values: diff --git a/lib/browser/api/menu-item.js b/lib/browser/api/menu-item.js index 4d2737d0fa..f38ab970d6 100644 --- a/lib/browser/api/menu-item.js +++ b/lib/browser/api/menu-item.js @@ -1,11 +1,9 @@ 'use strict' -var MenuItem, methodInBrowserWindow, nextCommandId, rolesMap - -nextCommandId = 0 +let nextCommandId = 0 // Maps role to methods of webContents -rolesMap = { +const rolesMap = { undo: 'undo', redo: 'redo', cut: 'cut', @@ -15,22 +13,27 @@ rolesMap = { selectall: 'selectAll', minimize: 'minimize', close: 'close', - delete: 'delete' + delete: 'delete', + quit: 'quit' } // Maps methods that should be called directly on the BrowserWindow instance -methodInBrowserWindow = { +const methodInBrowserWindow = { minimize: true, close: true } -MenuItem = (function () { +const methodInApp = { + quit: true +} + +const MenuItem = (function () { MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio'] function MenuItem (options) { - var click, ref - const Menu = require('electron').Menu - click = options.click + const {app, Menu} = require('electron') + + const click = options.click this.selector = options.selector this.type = options.type this.role = options.role @@ -48,7 +51,7 @@ MenuItem = (function () { if ((this.type == null) && (this.submenu != null)) { this.type = 'submenu' } - if (this.type === 'submenu' && ((ref = this.submenu) != null ? ref.constructor : void 0) !== Menu) { + if (this.type === 'submenu' && (this.submenu != null ? this.submenu.constructor : void 0) !== Menu) { throw new Error('Invalid submenu') } this.overrideReadOnlyProperty('type', 'normal') @@ -67,16 +70,19 @@ MenuItem = (function () { this.commandId = ++nextCommandId this.click = (focusedWindow) => { // Manually flip the checked flags when clicked. - var methodName, ref1, ref2 - if ((ref1 = this.type) === 'checkbox' || ref1 === 'radio') { + if (this.type === 'checkbox' || this.type === 'radio') { this.checked = !this.checked } + if (this.role && rolesMap[this.role] && process.platform !== 'darwin' && (focusedWindow != null)) { - methodName = rolesMap[this.role] - if (methodInBrowserWindow[methodName]) { + const methodName = rolesMap[this.role] + if (methodInApp[methodName]) { + return app[methodName]() + } else if (methodInBrowserWindow[methodName]) { return focusedWindow[methodName]() } else { - return (ref2 = focusedWindow.webContents) != null ? ref2[methodName]() : void 0 + const {webContents} = focusedWindow + return webContents != null ? webContents[methodName]() : void 0 } } else if (typeof click === 'function') { return click(this, focusedWindow)