X Tutup
Skip to content

Commit d417bbd

Browse files
trop[bot]zcbenz
authored andcommitted
fix: use xib file to construct macOS Menu (electron#20670)
* fix: use xib file to construct macOS Menu * add nib files back to zip manifests * address final review comments
1 parent e6f92f3 commit d417bbd

File tree

10 files changed

+330
-65
lines changed

10 files changed

+330
-65
lines changed

BUILD.gn

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ if (is_mac) {
2626
import("//third_party/icu/config.gni")
2727
import("//ui/gl/features.gni")
2828
import("//v8/gni/v8.gni")
29+
import("build/rules.gni")
2930
}
3031

3132
if (is_linux) {
@@ -655,6 +656,12 @@ if (is_mac) {
655656
electron_framework_version = "A"
656657
electron_version = read_file("ELECTRON_VERSION", "trim string")
657658

659+
mac_xib_bundle_data("electron_xibs") {
660+
sources = [
661+
"shell/common/resources/mac/MainMenu.xib",
662+
]
663+
}
664+
658665
bundle_data("electron_framework_resources") {
659666
public_deps = [
660667
":packed_resources",
@@ -769,6 +776,7 @@ if (is_mac) {
769776
":electron_framework_libraries",
770777
":electron_framework_resources",
771778
":electron_swiftshader_library",
779+
":electron_xibs",
772780
]
773781
if (!is_mas_build) {
774782
deps += [ ":electron_crashpad_helper" ]

build/rules.gni

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import("//build/config/mac/mac_sdk.gni")
2+
3+
# This is imported from /ios becuase this functionality was moved
4+
# after Chromium stopped using xib files for macOS menu functionality
5+
# See https://chromium-review.googlesource.com/c/chromium/src/+/1648695
6+
import("//build/config/ios/rules.gni")
7+
8+
# Template is copied here from Chromium but was removed in
9+
# https://chromium-review.googlesource.com/c/chromium/src/+/1637981
10+
# Template to compile and package Mac XIB files as bundle data.
11+
# Arguments
12+
# sources:
13+
# list of string, sources to comiple
14+
# output_path:
15+
# (optional) string, the path to use for the outputs list in the
16+
# bundle_data step. If unspecified, defaults to bundle_resources_dir.
17+
template("mac_xib_bundle_data") {
18+
_target_name = target_name
19+
_compile_target_name = _target_name + "_compile_ibtool"
20+
21+
compile_ib_files(_compile_target_name) {
22+
forward_variables_from(invoker, [ "testonly" ])
23+
visibility = [ ":$_target_name" ]
24+
sources = invoker.sources
25+
output_extension = "nib"
26+
ibtool_flags = [
27+
"--minimum-deployment-target",
28+
mac_deployment_target,
29+
30+
# TODO(rsesek): Enable this once all the bots are on Xcode 7+.
31+
# "--target-device",
32+
# "mac",
33+
]
34+
}
35+
36+
bundle_data(_target_name) {
37+
forward_variables_from(invoker,
38+
[
39+
"testonly",
40+
"visibility",
41+
])
42+
43+
public_deps = [
44+
":$_compile_target_name",
45+
]
46+
sources = get_target_outputs(":$_compile_target_name")
47+
48+
_output_path = "{{bundle_resources_dir}}"
49+
if (defined(invoker.output_path)) {
50+
_output_path = invoker.output_path
51+
}
52+
53+
outputs = [
54+
"$_output_path/{{source_file_part}}",
55+
]
56+
}
57+
}

script/zip_manifests/dist_zip.mac.x64.manifest

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Librari
1616
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libswiftshader_libGLESv2.dylib
1717
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/
1818
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Info.plist
19+
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib
1920
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/am.lproj/
2021
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/am.lproj/locale.pak
2122
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/ar.lproj/

script/zip_manifests/dist_zip.mac_mas.x64.manifest

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Librari
1616
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libswiftshader_libGLESv2.dylib
1717
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/
1818
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/Info.plist
19+
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/MainMenu.nib
1920
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/am.lproj/
2021
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/am.lproj/locale.pak
2122
Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Resources/ar.lproj/

shell/browser/atom_browser_main_parts.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
534534

535535
void AtomBrowserMainParts::PreMainMessageLoopStartCommon() {
536536
#if defined(OS_MACOSX)
537-
InitializeEmptyApplicationMenu();
537+
InitializeMainNib();
538538
RegisterURLHandler();
539539
#endif
540540
media::SetLocalizedStringProvider(MediaStringProvider);

shell/browser/atom_browser_main_parts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class AtomBrowserMainParts : public content::BrowserMainParts {
106106
#if defined(OS_MACOSX)
107107
void FreeAppDelegate();
108108
void RegisterURLHandler();
109-
void InitializeEmptyApplicationMenu();
109+
void InitializeMainNib();
110110
#endif
111111

112112
#if defined(OS_MACOSX)

shell/browser/atom_browser_main_parts_mac.mm

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,16 @@
44

55
#include "shell/browser/atom_browser_main_parts.h"
66

7+
#include "base/mac/bundle_locations.h"
8+
#include "base/mac/foundation_util.h"
9+
#include "base/path_service.h"
710
#include "shell/browser/atom_paths.h"
811
#import "shell/browser/mac/atom_application.h"
912
#include "shell/browser/mac/atom_application_delegate.h"
13+
#include "ui/base/l10n/l10n_util_mac.h"
1014

1115
namespace electron {
1216

13-
namespace {
14-
15-
base::scoped_nsobject<NSMenuItem> CreateMenuItem(NSString* title,
16-
SEL action,
17-
NSString* key_equivalent) {
18-
return base::scoped_nsobject<NSMenuItem>([[NSMenuItem alloc]
19-
initWithTitle:title
20-
action:action
21-
keyEquivalent:key_equivalent]);
22-
}
23-
24-
// The App Menu refers to the dropdown titled "Electron".
25-
base::scoped_nsobject<NSMenu> BuildAppMenu() {
26-
// The title is not used, as the title will always be the name of the App.
27-
base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
28-
29-
NSString* app_name = [[[NSBundle mainBundle] infoDictionary]
30-
objectForKey:(id)kCFBundleNameKey];
31-
32-
base::scoped_nsobject<NSMenuItem> item =
33-
CreateMenuItem([NSString stringWithFormat:@"Quit %@", app_name],
34-
@selector(terminate:), @"q");
35-
[menu addItem:item];
36-
37-
return menu;
38-
}
39-
40-
base::scoped_nsobject<NSMenu> BuildEmptyMainMenu() {
41-
base::scoped_nsobject<NSMenu> main_menu([[NSMenu alloc] initWithTitle:@""]);
42-
43-
using Builder = base::scoped_nsobject<NSMenu> (*)();
44-
static const Builder kBuilderFuncs[] = {&BuildAppMenu};
45-
for (auto* builder : kBuilderFuncs) {
46-
NSMenuItem* item = [[[NSMenuItem alloc] initWithTitle:@""
47-
action:NULL
48-
keyEquivalent:@""] autorelease];
49-
item.submenu = builder();
50-
[main_menu addItem:item];
51-
}
52-
return main_menu;
53-
}
54-
55-
} // namespace
56-
5717
void AtomBrowserMainParts::PreMainMessageLoopStart() {
5818
// Set our own application delegate.
5919
AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init];
@@ -77,9 +37,37 @@
7737
[[AtomApplication sharedApplication] registerURLHandler];
7838
}
7939

80-
void AtomBrowserMainParts::InitializeEmptyApplicationMenu() {
81-
base::scoped_nsobject<NSMenu> main_menu = BuildEmptyMainMenu();
82-
[[NSApplication sharedApplication] setMainMenu:main_menu];
40+
// Replicates NSApplicationMain, but doesn't start a run loop.
41+
void AtomBrowserMainParts::InitializeMainNib() {
42+
auto infoDictionary = base::mac::OuterBundle().infoDictionary;
43+
44+
auto principalClass =
45+
NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]);
46+
auto application = [principalClass sharedApplication];
47+
48+
NSString* mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"];
49+
50+
NSNib* mainNib;
51+
52+
@try {
53+
mainNib = [[NSNib alloc] initWithNibNamed:mainNibName
54+
bundle:base::mac::FrameworkBundle()];
55+
// Handle failure of initWithNibNamed on SMB shares
56+
// TODO(codebytere): Remove when
57+
// https://bugs.chromium.org/p/chromium/issues/detail?id=932935 is fixed
58+
} @catch (NSException* exception) {
59+
NSString* nibPath =
60+
[NSString stringWithFormat:@"Resources/%@.nib", mainNibName];
61+
nibPath = [base::mac::FrameworkBundle().bundlePath
62+
stringByAppendingPathComponent:nibPath];
63+
64+
NSData* data = [NSData dataWithContentsOfFile:nibPath];
65+
mainNib = [[NSNib alloc] initWithNibData:data
66+
bundle:base::mac::FrameworkBundle()];
67+
}
68+
69+
[mainNib instantiateWithOwner:application topLevelObjects:nil];
70+
[mainNib release];
8371
}
8472

8573
} // namespace electron

shell/browser/resources/mac/Info.plist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
<string>public.app-category.developer-tools</string>
2525
<key>LSMinimumSystemVersion</key>
2626
<string>10.10.0</string>
27+
<key>NSMainNibFile</key>
28+
<string>MainMenu</string>
2729
<key>NSPrincipalClass</key>
2830
<string>AtomApplication</string>
2931
<key>NSSupportsAutomaticGraphicsSwitching</key>

shell/browser/ui/cocoa/atom_menu_controller.mm

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,9 @@ - (void)populateWithModel:(electron::AtomMenuModel*)model {
128128

129129
// Locate & retain the recent documents menu item
130130
if (!recentDocumentsMenuItem_) {
131-
base::string16 title = base::ASCIIToUTF16("Open Recent");
132-
NSString* openTitle = l10n_util::FixUpWindowsStyleLabel(title);
133-
134-
recentDocumentsMenuItem_.reset([[[[[NSApp mainMenu]
135-
itemWithTitle:@"Electron"] submenu] itemWithTitle:openTitle] retain]);
131+
recentDocumentsMenuItem_.reset(
132+
[[[[[NSApp mainMenu] itemWithTitle:@"Electron"] submenu]
133+
itemWithTitle:@"Open Recent"] retain]);
136134
}
137135

138136
model_ = model;
@@ -195,17 +193,8 @@ - (void)moveMenuItems:(NSMenu*)source to:(NSMenu*)destination {
195193
// Replaces the item's submenu instance with the singleton recent documents
196194
// menu. Previously replaced menu items will be recovered.
197195
- (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item {
198-
NSMenu* recentDocumentsMenu = [recentDocumentsMenuItem_ submenu];
199-
if (!recentDocumentsMenu) {
200-
base::string16 title = base::ASCIIToUTF16("Clear Menu");
201-
NSString* clearTitle = l10n_util::FixUpWindowsStyleLabel(title);
202-
recentDocumentsMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
203-
[recentDocumentsMenu
204-
addItem:[[[NSMenuItem alloc]
205-
initWithTitle:clearTitle
206-
action:@selector(clearRecentDocuments:)
207-
keyEquivalent:@""] autorelease]];
208-
}
196+
NSMenu* recentDocumentsMenu =
197+
[[[recentDocumentsMenuItem_ submenu] retain] autorelease];
209198

210199
// Remove menu items in recent documents back to swap menu
211200
[self moveMenuItems:recentDocumentsMenu to:recentDocumentsMenuSwap_];

0 commit comments

Comments
 (0)
X Tutup