diff --git a/atom/browser/mac/atom_application_delegate.mm b/atom/browser/mac/atom_application_delegate.mm index 9e245f99078d..4c6a938fba59 100644 --- a/atom/browser/mac/atom_application_delegate.mm +++ b/atom/browser/mac/atom_application_delegate.mm @@ -10,10 +10,6 @@ #include "base/strings/sys_string_conversions.h" #include "base/values.h" -@interface NSWindow (SierraSDK) -@property(class) BOOL allowsAutomaticWindowTabbing; -@end - @implementation AtomApplicationDelegate - (void)setApplicationDockMenu:(atom::AtomMenuModel*)model { @@ -25,10 +21,6 @@ // Don't add the "Enter Full Screen" menu item automatically. [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"]; - // Don't add the "Show Tab Bar" menu item. - if ([NSWindow respondsToSelector:@selector(allowsAutomaticWindowTabbing)]) - NSWindow.allowsAutomaticWindowTabbing = NO; - atom::Browser::Get()->WillFinishLaunching(); } diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index c88469a9c8a1..2912022bd634 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -336,6 +336,14 @@ bool ScopedDisableResize::disable_resize_ = false; @end +enum { + NSWindowTabbingModeDisallowed = 2 +}; +@interface NSWindow (SierraSDK) +- (void)setTabbingMode:(NSInteger)mode; +- (void)setTabbingIdentifier:(NSString *)identifier; +@end + @interface AtomNSWindow : EventDispatchingWindow { @private atom::NativeWindowMac* shell_; @@ -682,6 +690,9 @@ NativeWindowMac::NativeWindowMac( options.Get(options::kTitleBarStyle, &title_bar_style_); + std::string tabbingIdentifier; + options.Get(options::kTabbingIdentifier, &tabbingIdentifier); + std::string windowType; options.Get(options::kType, &windowType); @@ -754,6 +765,18 @@ NativeWindowMac::NativeWindowMac( [window_ setOpaque:NO]; } + // Create a tab only if tabbing identifier is specified and window has + // a native title bar. + if (tabbingIdentifier.empty() || transparent() || !has_frame()) { + if ([window_ respondsToSelector:@selector(tabbingMode)]) { + [window_ setTabbingMode:NSWindowTabbingModeDisallowed]; + } + } else { + if ([window_ respondsToSelector:@selector(tabbingIdentifier)]) { + [window_ setTabbingIdentifier:base::SysUTF8ToNSString(tabbingIdentifier)]; + } + } + // We will manage window's lifetime ourselves. [window_ setReleasedWhenClosed:NO]; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index d040489b9f76..288fcd3a0753 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -51,6 +51,9 @@ const char kZoomToPageWidth[] = "zoomToPageWidth"; // The requested title bar style for the window const char kTitleBarStyle[] = "titleBarStyle"; +// Tabbing identifier for the window if native tabs are enabled on macOS. +const char kTabbingIdentifier[] = "tabbingIdentifier"; + // The menu bar is hidden unless "Alt" is pressed. const char kAutoHideMenuBar[] = "autoHideMenuBar"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index dd2824c55c74..9e1a71ca5bda 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -36,6 +36,7 @@ extern const char kAcceptFirstMouse[]; extern const char kUseContentSize[]; extern const char kZoomToPageWidth[]; extern const char kTitleBarStyle[]; +extern const char kTabbingIdentifier[]; extern const char kAutoHideMenuBar[]; extern const char kEnableLargerThanScreen[]; extern const char kDarkTheme[]; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 182e798158b1..01f5431ecf73 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -211,6 +211,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. width of the web page when zoomed, `false` will cause it to zoom to the width of the screen. This will also affect the behavior when calling `maximize()` directly. Default is `false`. + * `tabbingIdentifier` String (optional) - Tab group name, allows opening the + window as a native tab on macOS 10.12+. Windows with the same tabbing + identifier will be grouped together. * `webPreferences` Object (optional) - Settings of web page's features. * `devTools` Boolean (optional) - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`. * `nodeIntegration` Boolean (optional) - Whether node integration is enabled. Default diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index b5985e4b7406..d83c173f26f1 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -692,7 +692,7 @@ describe('BrowserWindow module', function () { }) }) - describe('"title-bar-style" option', function () { + describe('"titleBarStyle" option', function () { if (process.platform !== 'darwin') { return } @@ -772,6 +772,20 @@ describe('BrowserWindow module', function () { }) }) + describe('"tabbingIdentifier" option', function () { + it('can be set on a window', function () { + w.destroy() + w = new BrowserWindow({ + tabbingIdentifier: 'group1' + }) + w.destroy() + w = new BrowserWindow({ + tabbingIdentifier: 'group2', + frame: false + }) + }) + }) + describe('"web-preferences" option', function () { afterEach(function () { ipcMain.removeAllListeners('answer')