fix: use xib file to construct macOS Menu (#20670)

* fix: use xib file to construct macOS Menu

* add nib files back to zip manifests

* address final review comments
This commit is contained in:
trop[bot]
2019-10-22 16:48:36 +09:00
committed by Cheng Zhao
parent e6f92f3f30
commit d417bbdcfd
10 changed files with 330 additions and 65 deletions

View File

@@ -534,7 +534,7 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
void AtomBrowserMainParts::PreMainMessageLoopStartCommon() {
#if defined(OS_MACOSX)
InitializeEmptyApplicationMenu();
InitializeMainNib();
RegisterURLHandler();
#endif
media::SetLocalizedStringProvider(MediaStringProvider);

View File

@@ -106,7 +106,7 @@ class AtomBrowserMainParts : public content::BrowserMainParts {
#if defined(OS_MACOSX)
void FreeAppDelegate();
void RegisterURLHandler();
void InitializeEmptyApplicationMenu();
void InitializeMainNib();
#endif
#if defined(OS_MACOSX)

View File

@@ -4,56 +4,16 @@
#include "shell/browser/atom_browser_main_parts.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/path_service.h"
#include "shell/browser/atom_paths.h"
#import "shell/browser/mac/atom_application.h"
#include "shell/browser/mac/atom_application_delegate.h"
#include "ui/base/l10n/l10n_util_mac.h"
namespace electron {
namespace {
base::scoped_nsobject<NSMenuItem> CreateMenuItem(NSString* title,
SEL action,
NSString* key_equivalent) {
return base::scoped_nsobject<NSMenuItem>([[NSMenuItem alloc]
initWithTitle:title
action:action
keyEquivalent:key_equivalent]);
}
// The App Menu refers to the dropdown titled "Electron".
base::scoped_nsobject<NSMenu> BuildAppMenu() {
// The title is not used, as the title will always be the name of the App.
base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
NSString* app_name = [[[NSBundle mainBundle] infoDictionary]
objectForKey:(id)kCFBundleNameKey];
base::scoped_nsobject<NSMenuItem> item =
CreateMenuItem([NSString stringWithFormat:@"Quit %@", app_name],
@selector(terminate:), @"q");
[menu addItem:item];
return menu;
}
base::scoped_nsobject<NSMenu> BuildEmptyMainMenu() {
base::scoped_nsobject<NSMenu> main_menu([[NSMenu alloc] initWithTitle:@""]);
using Builder = base::scoped_nsobject<NSMenu> (*)();
static const Builder kBuilderFuncs[] = {&BuildAppMenu};
for (auto* builder : kBuilderFuncs) {
NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle:@""
action:NULL
keyEquivalent:@""] autorelease];
item.submenu = builder();
[main_menu addItem:item];
}
return main_menu;
}
} // namespace
void AtomBrowserMainParts::PreMainMessageLoopStart() {
// Set our own application delegate.
AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init];
@@ -77,9 +37,37 @@ void AtomBrowserMainParts::RegisterURLHandler() {
[[AtomApplication sharedApplication] registerURLHandler];
}
void AtomBrowserMainParts::InitializeEmptyApplicationMenu() {
base::scoped_nsobject<NSMenu> main_menu = BuildEmptyMainMenu();
[[NSApplication sharedApplication] setMainMenu:main_menu];
// Replicates NSApplicationMain, but doesn't start a run loop.
void AtomBrowserMainParts::InitializeMainNib() {
auto infoDictionary = base::mac::OuterBundle().infoDictionary;
auto principalClass =
NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]);
auto application = [principalClass sharedApplication];
NSString* mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"];
NSNib* mainNib;
@try {
mainNib = [[NSNib alloc] initWithNibNamed:mainNibName
bundle:base::mac::FrameworkBundle()];
// Handle failure of initWithNibNamed on SMB shares
// TODO(codebytere): Remove when
// https://bugs.chromium.org/p/chromium/issues/detail?id=932935 is fixed
} @catch (NSException* exception) {
NSString* nibPath =
[NSString stringWithFormat:@"Resources/%@.nib", mainNibName];
nibPath = [base::mac::FrameworkBundle().bundlePath
stringByAppendingPathComponent:nibPath];
NSData* data = [NSData dataWithContentsOfFile:nibPath];
mainNib = [[NSNib alloc] initWithNibData:data
bundle:base::mac::FrameworkBundle()];
}
[mainNib instantiateWithOwner:application topLevelObjects:nil];
[mainNib release];
}
} // namespace electron

View File

@@ -24,6 +24,8 @@
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>10.10.0</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>AtomApplication</string>
<key>NSSupportsAutomaticGraphicsSwitching</key>

View File

@@ -128,11 +128,9 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
// Locate & retain the recent documents menu item
if (!recentDocumentsMenuItem_) {
base::string16 title = base::ASCIIToUTF16("Open Recent");
NSString* openTitle = l10n_util::FixUpWindowsStyleLabel(title);
recentDocumentsMenuItem_.reset([[[[[NSApp mainMenu]
itemWithTitle:@"Electron"] submenu] itemWithTitle:openTitle] retain]);
recentDocumentsMenuItem_.reset(
[[[[[NSApp mainMenu] itemWithTitle:@"Electron"] submenu]
itemWithTitle:@"Open Recent"] retain]);
}
model_ = model;
@@ -195,17 +193,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
// Replaces the item's submenu instance with the singleton recent documents
// menu. Previously replaced menu items will be recovered.
- (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item {
NSMenu* recentDocumentsMenu = [recentDocumentsMenuItem_ submenu];
if (!recentDocumentsMenu) {
base::string16 title = base::ASCIIToUTF16("Clear Menu");
NSString* clearTitle = l10n_util::FixUpWindowsStyleLabel(title);
recentDocumentsMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
[recentDocumentsMenu
addItem:[[[NSMenuItem alloc]
initWithTitle:clearTitle
action:@selector(clearRecentDocuments:)
keyEquivalent:@""] autorelease]];
}
NSMenu* recentDocumentsMenu =
[[[recentDocumentsMenuItem_ submenu] retain] autorelease];
// Remove menu items in recent documents back to swap menu
[self moveMenuItems:recentDocumentsMenu to:recentDocumentsMenuSwap_];