diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index cd606418ccf7..19b27416a16d 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -147,9 +147,13 @@ void Browser::SetUserActivity(const std::string& type, } std::string Browser::GetCurrentActivityType() { - NSUserActivity* userActivity = - [[AtomApplication sharedApplication] getCurrentActivity]; - return base::SysNSStringToUTF8(userActivity.activityType); + if (@available(macOS 10.10, *)) { + NSUserActivity* userActivity = + [[AtomApplication sharedApplication] getCurrentActivity]; + return base::SysNSStringToUTF8(userActivity.activityType); + } else { + return std::string(); + } } void Browser::InvalidateCurrentActivity() { diff --git a/atom/browser/mac/atom_application.h b/atom/browser/mac/atom_application.h index 5015608d6fc6..b0a8742ee98b 100644 --- a/atom/browser/mac/atom_application.h +++ b/atom/browser/mac/atom_application.h @@ -11,7 +11,7 @@ NSUserActivityDelegate> { @private BOOL handlingSendEvent_; - base::scoped_nsobject currentActivity_; + base::scoped_nsobject currentActivity_ API_AVAILABLE(macosx(10.10)); NSCondition* handoffLock_; BOOL updateReceived_; base::Callback shouldShutdown_; @@ -27,7 +27,7 @@ // CrAppControlProtocol: - (void)setHandlingSendEvent:(BOOL)handlingSendEvent; -- (NSUserActivity*)getCurrentActivity; +- (NSUserActivity*)getCurrentActivity API_AVAILABLE(macosx(10.10)); - (void)setCurrentActivity:(NSString*)type withUserInfo:(NSDictionary*)userInfo withWebpageURL:(NSURL*)webpageURL; diff --git a/atom/browser/mac/atom_application.mm b/atom/browser/mac/atom_application.mm index 226c09091bc8..eb00a415bf24 100644 --- a/atom/browser/mac/atom_application.mm +++ b/atom/browser/mac/atom_application.mm @@ -58,13 +58,15 @@ inline void dispatch_sync_main(dispatch_block_t block) { - (void)setCurrentActivity:(NSString*)type withUserInfo:(NSDictionary*)userInfo withWebpageURL:(NSURL*)webpageURL { - currentActivity_ = base::scoped_nsobject( - [[NSUserActivity alloc] initWithActivityType:type]); - [currentActivity_ setUserInfo:userInfo]; - [currentActivity_ setWebpageURL:webpageURL]; - [currentActivity_ setDelegate:self]; - [currentActivity_ becomeCurrent]; - [currentActivity_ setNeedsSave:YES]; + if (@available(macOS 10.10, *)) { + currentActivity_ = base::scoped_nsobject( + [[NSUserActivity alloc] initWithActivityType:type]); + [currentActivity_ setUserInfo:userInfo]; + [currentActivity_ setWebpageURL:webpageURL]; + [currentActivity_ setDelegate:self]; + [currentActivity_ becomeCurrent]; + [currentActivity_ setNeedsSave:YES]; + } } - (NSUserActivity*)getCurrentActivity { @@ -90,7 +92,8 @@ inline void dispatch_sync_main(dispatch_block_t block) { [handoffLock_ unlock]; } -- (void)userActivityWillSave:(NSUserActivity*)userActivity { +- (void)userActivityWillSave:(NSUserActivity*)userActivity + API_AVAILABLE(macosx(10.10)) { __block BOOL shouldWait = NO; dispatch_sync_main(^{ std::string activity_type( @@ -118,7 +121,8 @@ inline void dispatch_sync_main(dispatch_block_t block) { [userActivity setNeedsSave:YES]; } -- (void)userActivityWasContinued:(NSUserActivity*)userActivity { +- (void)userActivityWasContinued:(NSUserActivity*)userActivity + API_AVAILABLE(macosx(10.10)) { dispatch_async(dispatch_get_main_queue(), ^{ std::string activity_type( base::SysNSStringToUTF8(userActivity.activityType)); diff --git a/atom/browser/mac/atom_application_delegate.mm b/atom/browser/mac/atom_application_delegate.mm index 8dfa6e81a073..683f7a84bcaa 100644 --- a/atom/browser/mac/atom_application_delegate.mm +++ b/atom/browser/mac/atom_application_delegate.mm @@ -98,7 +98,8 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session; - (BOOL)application:(NSApplication*)sender continueUserActivity:(NSUserActivity*)userActivity restorationHandler: - (void (^)(NSArray* restorableObjects))restorationHandler { + (void (^)(NSArray* restorableObjects))restorationHandler + API_AVAILABLE(macosx(10.10)) { std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType)); std::unique_ptr user_info = atom::NSDictionaryToDictionaryValue(userActivity.userInfo); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index bbaee5f1d672..dd343c6e2a20 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -153,6 +153,8 @@ class NativeWindowMac : public NativeWindow { private: void InternalSetParentWindow(NativeWindow* parent, bool attach); + void ShowWindowButton(NSWindowButton button); + void SetForwardMouseMessages(bool forward); AtomNSWindow* window_; // Weak ref, managed by widget_. diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 6f808936ebca..ba28d4f501bd 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -295,9 +295,11 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options, } NSUInteger styleMask = NSTitledWindowMask; - if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER && - (!useStandardWindow || transparent() || !has_frame())) { - styleMask = NSFullSizeContentViewWindowMask; + if (@available(macOS 10.10, *)) { + if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER && + (!useStandardWindow || transparent() || !has_frame())) { + styleMask = NSFullSizeContentViewWindowMask; + } } if (minimizable) { styleMask |= NSMiniaturizableWindowMask; @@ -352,10 +354,11 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options, [window_ setDisableKeyOrMainWindow:YES]; if (transparent() || !has_frame()) { - // Don't show title bar. - [window_ setTitlebarAppearsTransparent:YES]; - [window_ setTitleVisibility:NSWindowTitleHidden]; - + if (@available(macOS 10.10, *)) { + // Don't show title bar. + [window_ setTitlebarAppearsTransparent:YES]; + [window_ setTitleVisibility:NSWindowTitleHidden]; + } // Remove non-transparent corners, see http://git.io/vfonD. [window_ setOpaque:NO]; } @@ -374,15 +377,22 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options, // Hide the title bar background if (title_bar_style_ != NORMAL) { - [window_ setTitlebarAppearsTransparent:YES]; + if (@available(macOS 10.10, *)) { + [window_ setTitlebarAppearsTransparent:YES]; + } } // Hide the title bar. if (title_bar_style_ == HIDDEN_INSET) { - base::scoped_nsobject toolbar( - [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); - [toolbar setShowsBaselineSeparator:NO]; - [window_ setToolbar:toolbar]; + if (@available(macOS 10.10, *)) { + base::scoped_nsobject toolbar( + [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); + [toolbar setShowsBaselineSeparator:NO]; + [window_ setToolbar:toolbar]; + } else { + [window_ enableWindowButtonsOffset]; + [window_ setWindowButtonsOffset:NSMakePoint(12, 10)]; + } } // Resize to content bounds. @@ -435,8 +445,9 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options, SetContentView(new views::View()); // Make sure the bottom corner is rounded for non-modal windows: - // http://crbug.com/396264. - if (!is_modal()) { + // http://crbug.com/396264. But do not enable it on OS X 10.9 for transparent + // window, otherwise a semi-transparent frame would show. + if (!(transparent() && base::mac::IsOS10_9()) && !is_modal()) { base::scoped_nsobject background_layer([[CALayer alloc] init]); [background_layer setAutoresizingMask:kCALayerWidthSizable | kCALayerHeightSizable]; @@ -468,6 +479,11 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options, [[window_ contentView] addSubview:buttons_view_]; } else { if (title_bar_style_ != NORMAL) { + if (base::mac::IsOS10_9()) { + ShowWindowButton(NSWindowZoomButton); + ShowWindowButton(NSWindowMiniaturizeButton); + ShowWindowButton(NSWindowCloseButton); + } return; } @@ -842,11 +858,17 @@ void NativeWindowMac::Invalidate() { } void NativeWindowMac::SetTitle(const std::string& title) { + // For macOS <= 10.9, the setTitleVisibility API is not available, we have + // to avoid calling setTitle for frameless window. + if (!base::mac::IsAtLeastOS10_10() && (transparent() || !has_frame())) + return; + [window_ setTitle:base::SysUTF8ToNSString(title)]; } std::string NativeWindowMac::GetTitle() { return base::SysNSStringToUTF8([window_ title]); + ; } void NativeWindowMac::FlashFrame(bool flash) { @@ -1156,83 +1178,86 @@ bool NativeWindowMac::AddTabbedWindow(NativeWindow* window) { } void NativeWindowMac::SetVibrancy(const std::string& type) { - NSView* vibrant_view = [window_ vibrantView]; + if (@available(macOS 10.10, *)) { + NSView* vibrant_view = [window_ vibrantView]; + + if (type.empty()) { + if (background_color_before_vibrancy_) { + [window_ setBackgroundColor:background_color_before_vibrancy_]; + [window_ setTitlebarAppearsTransparent:transparency_before_vibrancy_]; + } + if (vibrant_view == nil) + return; + + [vibrant_view removeFromSuperview]; + [window_ setVibrantView:nil]; + ui::GpuSwitchingManager::SetTransparent(transparent()); - if (type.empty()) { - if (background_color_before_vibrancy_) { - [window_ setBackgroundColor:background_color_before_vibrancy_]; - [window_ setTitlebarAppearsTransparent:transparency_before_vibrancy_]; - } - if (vibrant_view == nil) return; - - [vibrant_view removeFromSuperview]; - [window_ setVibrantView:nil]; - ui::GpuSwitchingManager::SetTransparent(transparent()); - - return; - } - - background_color_before_vibrancy_.reset([[window_ backgroundColor] retain]); - transparency_before_vibrancy_ = [window_ titlebarAppearsTransparent]; - ui::GpuSwitchingManager::SetTransparent(true); - - if (title_bar_style_ != NORMAL) { - [window_ setTitlebarAppearsTransparent:YES]; - [window_ setBackgroundColor:[NSColor clearColor]]; - } - - NSVisualEffectView* effect_view = (NSVisualEffectView*)vibrant_view; - if (effect_view == nil) { - effect_view = [[[NSVisualEffectView alloc] - initWithFrame:[[window_ contentView] bounds]] autorelease]; - [window_ setVibrantView:(NSView*)effect_view]; - - [effect_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [effect_view setBlendingMode:NSVisualEffectBlendingModeBehindWindow]; - [effect_view setState:NSVisualEffectStateActive]; - [[window_ contentView] addSubview:effect_view - positioned:NSWindowBelow - relativeTo:nil]; - } - - NSVisualEffectMaterial vibrancyType = NSVisualEffectMaterialLight; - - if (type == "appearance-based") { - vibrancyType = NSVisualEffectMaterialAppearanceBased; - } else if (type == "light") { - vibrancyType = NSVisualEffectMaterialLight; - } else if (type == "dark") { - vibrancyType = NSVisualEffectMaterialDark; - } else if (type == "titlebar") { - vibrancyType = NSVisualEffectMaterialTitlebar; - } - - if (@available(macOS 10.11, *)) { - // TODO(kevinsawicki): Use NSVisualEffectMaterial* constants directly once - // they are available in the minimum SDK version - if (type == "selection") { - // NSVisualEffectMaterialSelection - vibrancyType = static_cast(4); - } else if (type == "menu") { - // NSVisualEffectMaterialMenu - vibrancyType = static_cast(5); - } else if (type == "popover") { - // NSVisualEffectMaterialPopover - vibrancyType = static_cast(6); - } else if (type == "sidebar") { - // NSVisualEffectMaterialSidebar - vibrancyType = static_cast(7); - } else if (type == "medium-light") { - // NSVisualEffectMaterialMediumLight - vibrancyType = static_cast(8); - } else if (type == "ultra-dark") { - // NSVisualEffectMaterialUltraDark - vibrancyType = static_cast(9); } - } - [effect_view setMaterial:vibrancyType]; + background_color_before_vibrancy_.reset([[window_ backgroundColor] retain]); + transparency_before_vibrancy_ = [window_ titlebarAppearsTransparent]; + ui::GpuSwitchingManager::SetTransparent(true); + + if (title_bar_style_ != NORMAL) { + [window_ setTitlebarAppearsTransparent:YES]; + [window_ setBackgroundColor:[NSColor clearColor]]; + } + + NSVisualEffectView* effect_view = (NSVisualEffectView*)vibrant_view; + if (effect_view == nil) { + effect_view = [[[NSVisualEffectView alloc] + initWithFrame:[[window_ contentView] bounds]] autorelease]; + [window_ setVibrantView:(NSView*)effect_view]; + + [effect_view + setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [effect_view setBlendingMode:NSVisualEffectBlendingModeBehindWindow]; + [effect_view setState:NSVisualEffectStateActive]; + [[window_ contentView] addSubview:effect_view + positioned:NSWindowBelow + relativeTo:nil]; + } + + NSVisualEffectMaterial vibrancyType = NSVisualEffectMaterialLight; + + if (type == "appearance-based") { + vibrancyType = NSVisualEffectMaterialAppearanceBased; + } else if (type == "light") { + vibrancyType = NSVisualEffectMaterialLight; + } else if (type == "dark") { + vibrancyType = NSVisualEffectMaterialDark; + } else if (type == "titlebar") { + vibrancyType = NSVisualEffectMaterialTitlebar; + } + + if (@available(macOS 10.11, *)) { + // TODO(kevinsawicki): Use NSVisualEffectMaterial* constants directly once + // they are available in the minimum SDK version + if (type == "selection") { + // NSVisualEffectMaterialSelection + vibrancyType = static_cast(4); + } else if (type == "menu") { + // NSVisualEffectMaterialMenu + vibrancyType = static_cast(5); + } else if (type == "popover") { + // NSVisualEffectMaterialPopover + vibrancyType = static_cast(6); + } else if (type == "sidebar") { + // NSVisualEffectMaterialSidebar + vibrancyType = static_cast(7); + } else if (type == "medium-light") { + // NSVisualEffectMaterialMediumLight + vibrancyType = static_cast(8); + } else if (type == "ultra-dark") { + // NSVisualEffectMaterialUltraDark + vibrancyType = static_cast(9); + } + } + + [effect_view setMaterial:vibrancyType]; + } } void NativeWindowMac::SetTouchBar( @@ -1316,6 +1341,11 @@ void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent, [parent->GetNativeWindow() addChildWindow:window_ ordered:NSWindowAbove]; } +void NativeWindowMac::ShowWindowButton(NSWindowButton button) { + auto view = [window_ standardWindowButton:button]; + [view.superview addSubview:view positioned:NSWindowAbove relativeTo:nil]; +} + void NativeWindowMac::SetForwardMouseMessages(bool forward) { [window_ setAcceptsMouseMovedEvents:forward]; } diff --git a/atom/browser/ui/cocoa/atom_ns_window.h b/atom/browser/ui/cocoa/atom_ns_window.h index ee13e7137ce0..7fd8f2a9a2a2 100644 --- a/atom/browser/ui/cocoa/atom_ns_window.h +++ b/atom/browser/ui/cocoa/atom_ns_window.h @@ -29,16 +29,19 @@ class ScopedDisableResize { @interface AtomNSWindow : NativeWidgetMacNSWindow { @private atom::NativeWindowMac* shell_; + CGFloat windowButtonsInterButtonSpacing_; } @property BOOL acceptsFirstMouse; @property BOOL enableLargerThanScreen; @property BOOL disableAutoHideCursor; @property BOOL disableKeyOrMainWindow; +@property NSPoint windowButtonsOffset; @property(nonatomic, retain) NSView* vibrantView; - (id)initWithShell:(atom::NativeWindowMac*)shell styleMask:(NSUInteger)styleMask; - (atom::NativeWindowMac*)shell; - (NSRect)originalContentRectForFrameRect:(NSRect)frameRect; +- (void)enableWindowButtonsOffset; - (void)toggleFullScreenMode:(id)sender; @end diff --git a/atom/browser/ui/cocoa/atom_ns_window.mm b/atom/browser/ui/cocoa/atom_ns_window.mm index 9087f6234338..56ed5dc2319c 100644 --- a/atom/browser/ui/cocoa/atom_ns_window.mm +++ b/atom/browser/ui/cocoa/atom_ns_window.mm @@ -21,6 +21,7 @@ bool ScopedDisableResize::disable_resize_ = false; @synthesize enableLargerThanScreen; @synthesize disableAutoHideCursor; @synthesize disableKeyOrMainWindow; +@synthesize windowButtonsOffset; @synthesize vibrantView; - (id)initWithShell:(atom::NativeWindowMac*)shell @@ -116,6 +117,78 @@ bool ScopedDisableResize::disable_resize_ = false; return !self.disableKeyOrMainWindow; } +- (void)enableWindowButtonsOffset { + auto closeButton = [self standardWindowButton:NSWindowCloseButton]; + auto miniaturizeButton = + [self standardWindowButton:NSWindowMiniaturizeButton]; + auto zoomButton = [self standardWindowButton:NSWindowZoomButton]; + + [closeButton setPostsFrameChangedNotifications:YES]; + [miniaturizeButton setPostsFrameChangedNotifications:YES]; + [zoomButton setPostsFrameChangedNotifications:YES]; + + windowButtonsInterButtonSpacing_ = + NSMinX([miniaturizeButton frame]) - NSMaxX([closeButton frame]); + + auto center = [NSNotificationCenter defaultCenter]; + + [center addObserver:self + selector:@selector(adjustCloseButton:) + name:NSViewFrameDidChangeNotification + object:closeButton]; + + [center addObserver:self + selector:@selector(adjustMiniaturizeButton:) + name:NSViewFrameDidChangeNotification + object:miniaturizeButton]; + + [center addObserver:self + selector:@selector(adjustZoomButton:) + name:NSViewFrameDidChangeNotification + object:zoomButton]; +} + +- (void)adjustCloseButton:(NSNotification*)notification { + [self adjustButton:[notification object] ofKind:NSWindowCloseButton]; +} + +- (void)adjustMiniaturizeButton:(NSNotification*)notification { + [self adjustButton:[notification object] ofKind:NSWindowMiniaturizeButton]; +} + +- (void)adjustZoomButton:(NSNotification*)notification { + [self adjustButton:[notification object] ofKind:NSWindowZoomButton]; +} + +- (void)adjustButton:(NSButton*)button ofKind:(NSWindowButton)kind { + NSRect buttonFrame = [button frame]; + NSRect frameViewBounds = [[self frameView] bounds]; + NSPoint offset = self.windowButtonsOffset; + + buttonFrame.origin = NSMakePoint( + offset.x, (NSHeight(frameViewBounds) - NSHeight(buttonFrame) - offset.y)); + + switch (kind) { + case NSWindowZoomButton: + buttonFrame.origin.x += NSWidth( + [[self standardWindowButton:NSWindowMiniaturizeButton] frame]); + buttonFrame.origin.x += windowButtonsInterButtonSpacing_; + // fallthrough + case NSWindowMiniaturizeButton: + buttonFrame.origin.x += + NSWidth([[self standardWindowButton:NSWindowCloseButton] frame]); + buttonFrame.origin.x += windowButtonsInterButtonSpacing_; + // fallthrough + default: + break; + } + + BOOL didPost = [button postsBoundsChangedNotifications]; + [button setPostsFrameChangedNotifications:NO]; + [button setFrame:buttonFrame]; + [button setPostsFrameChangedNotifications:didPost]; +} + - (NSView*)frameView { return [[self contentView] superview]; } diff --git a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm index 97a441efdfad..78bfe1fcd7b5 100644 --- a/atom/browser/ui/cocoa/atom_ns_window_delegate.mm +++ b/atom/browser/ui/cocoa/atom_ns_window_delegate.mm @@ -168,54 +168,60 @@ shell_->SetResizable(true); // Hide the native toolbar before entering fullscreen, so there is no visual // artifacts. - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - NSWindow* window = shell_->GetNativeWindow(); - [window setToolbar:nil]; + if (@available(macOS 10.10, *)) { + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + NSWindow* window = shell_->GetNativeWindow(); + [window setToolbar:nil]; + } } } - (void)windowDidEnterFullScreen:(NSNotification*)notification { shell_->NotifyWindowEnterFullScreen(); - // For frameless window we don't show set title for normal mode since the - // titlebar is expected to be empty, but after entering fullscreen mode we - // have to set one, because title bar is visible here. - NSWindow* window = shell_->GetNativeWindow(); - if ((shell_->transparent() || !shell_->has_frame()) && - // FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under - // fullscreen mode. - // Show title if fullscreen_window_title flag is set - (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || - shell_->fullscreen_window_title())) { - [window setTitleVisibility:NSWindowTitleVisible]; - } + if (@available(macOS 10.10, *)) { + // For frameless window we don't show set title for normal mode since the + // titlebar is expected to be empty, but after entering fullscreen mode we + // have to set one, because title bar is visible here. + NSWindow* window = shell_->GetNativeWindow(); + if ((shell_->transparent() || !shell_->has_frame()) && + // FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under + // fullscreen mode. + // Show title if fullscreen_window_title flag is set + (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || + shell_->fullscreen_window_title())) { + [window setTitleVisibility:NSWindowTitleVisible]; + } - // Restore the native toolbar immediately after entering fullscreen, if we - // do this before leaving fullscreen, traffic light buttons will be jumping. - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - base::scoped_nsobject toolbar( - [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); - [toolbar setShowsBaselineSeparator:NO]; - [window setToolbar:toolbar]; + // Restore the native toolbar immediately after entering fullscreen, if we + // do this before leaving fullscreen, traffic light buttons will be jumping. + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + base::scoped_nsobject toolbar( + [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); + [toolbar setShowsBaselineSeparator:NO]; + [window setToolbar:toolbar]; - // Set window style to hide the toolbar, otherwise the toolbar will show - // in fullscreen mode. - shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask); + // Set window style to hide the toolbar, otherwise the toolbar will show + // in fullscreen mode. + shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask); + } } } - (void)windowWillExitFullScreen:(NSNotification*)notification { - // Restore the titlebar visibility. - NSWindow* window = shell_->GetNativeWindow(); - if ((shell_->transparent() || !shell_->has_frame()) && - (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || - shell_->fullscreen_window_title())) { - [window setTitleVisibility:NSWindowTitleHidden]; - } + if (@available(macOS 10.10, *)) { + // Restore the titlebar visibility. + NSWindow* window = shell_->GetNativeWindow(); + if ((shell_->transparent() || !shell_->has_frame()) && + (shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET || + shell_->fullscreen_window_title())) { + [window setTitleVisibility:NSWindowTitleHidden]; + } - // Turn off the style for toolbar. - if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { - shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask); + // Turn off the style for toolbar. + if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) { + shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask); + } } } diff --git a/brightray/browser/mac/cocoa_notification.h b/brightray/browser/mac/cocoa_notification.h index 41f6d4b5a423..066528ee490b 100644 --- a/brightray/browser/mac/cocoa_notification.h +++ b/brightray/browser/mac/cocoa_notification.h @@ -29,7 +29,8 @@ class CocoaNotification : public Notification { void NotificationDisplayed(); void NotificationReplied(const std::string& reply); void NotificationActivated(); - void NotificationActivated(NSUserNotificationAction* action); + void NotificationActivated(NSUserNotificationAction* action) + API_AVAILABLE(macosx(10.10)); NSUserNotification* notification() const { return notification_; } diff --git a/brightray/browser/mac/cocoa_notification.mm b/brightray/browser/mac/cocoa_notification.mm index 1f51d64e99f2..6b576497d41a 100644 --- a/brightray/browser/mac/cocoa_notification.mm +++ b/brightray/browser/mac/cocoa_notification.mm @@ -72,18 +72,24 @@ void CocoaNotification::Show(const NotificationOptions& options) { // All of the rest are appended to the list of additional actions NSString* actionIdentifier = [NSString stringWithFormat:@"%@Action%d", identifier, i]; - NSUserNotificationAction* notificationAction = [NSUserNotificationAction - actionWithIdentifier:actionIdentifier - title:base::SysUTF16ToNSString(action.text)]; - [additionalActions addObject:notificationAction]; - additional_action_indices_.insert( - std::make_pair(base::SysNSStringToUTF8(actionIdentifier), i)); + if (@available(macOS 10.10, *)) { + NSUserNotificationAction* notificationAction = + [NSUserNotificationAction + actionWithIdentifier:actionIdentifier + title:base::SysUTF16ToNSString(action.text)]; + [additionalActions addObject:notificationAction]; + additional_action_indices_.insert( + std::make_pair(base::SysNSStringToUTF8(actionIdentifier), i)); + } } } i++; } - if ([additionalActions count] > 0) { - [notification_ setAdditionalActions:additionalActions]; + if ([additionalActions count] > 0 && + [notification_ respondsToSelector:@selector(setAdditionalActions:)]) { + if (@available(macOS 10.10, *)) { + [notification_ setAdditionalActions:additionalActions]; + } } if (options.has_reply) { diff --git a/brightray/browser/mac/notification_center_delegate.mm b/brightray/browser/mac/notification_center_delegate.mm index ea4c53bfa9a8..7ae24b8979b4 100644 --- a/brightray/browser/mac/notification_center_delegate.mm +++ b/brightray/browser/mac/notification_center_delegate.mm @@ -48,9 +48,12 @@ NSUserNotificationActivationTypeReplied) { notification->NotificationReplied([notif.response.string UTF8String]); } else { - if (notif.activationType == - NSUserNotificationActivationTypeAdditionalActionClicked) { - notification->NotificationActivated([notif additionalActivationAction]); + if (@available(macOS 10.10, *)) { + if (notif.activationType == + NSUserNotificationActivationTypeAdditionalActionClicked) { + notification->NotificationActivated( + [notif additionalActivationAction]); + } } } } diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 868f0621e73c..46e496407a8d 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -21,10 +21,11 @@ win.show() ### Alternatives on macOS -There's an alternative way to specify a chromeless window. -Instead of setting `frame` to `false` which disables both the titlebar and window controls, -you may want to have the title bar hidden and your content extend to the full window size, -yet still preserve the window controls ("traffic lights") for standard window actions. +On macOS 10.9 Mavericks and newer, there's an alternative way to specify +a chromeless window. Instead of setting `frame` to `false` which disables +both the titlebar and window controls, you may want to have the title bar +hidden and your content extend to the full window size, yet still preserve +the window controls ("traffic lights") for standard window actions. You can do so by specifying the `titleBarStyle` option: #### `hidden` diff --git a/docs/tutorial/development-environment.md b/docs/tutorial/development-environment.md index 741d6c35560c..3a5b956208e5 100644 --- a/docs/tutorial/development-environment.md +++ b/docs/tutorial/development-environment.md @@ -7,7 +7,7 @@ rudimentary understanding of your operating system's command line client. ## Setting up macOS -> Electron supports OS X Yosemite (version 10.10) and up. Apple +> Electron supports Mac OS X 10.9 (and all versions named macOS) and up. Apple does not allow running macOS in virtual machines unless the host computer is already an Apple computer, so if you find yourself in need of a Mac, consider using a cloud service that rents access to Macs (like [MacInCloud][macincloud] diff --git a/docs/tutorial/support.md b/docs/tutorial/support.md index db8c496cd3d2..bdb3b8678485 100644 --- a/docs/tutorial/support.md +++ b/docs/tutorial/support.md @@ -61,7 +61,7 @@ Following platforms are supported by Electron: ### macOS Only 64bit binaries are provided for macOS, and the minimum macOS version -supported is OS X Yosemite (version 10.10). +supported is macOS 10.9. ### Windows @@ -79,7 +79,7 @@ Ubuntu 12.04, the `armv7l` binary is built against ARM v7 with hard-float ABI an NEON for Debian Wheezy. [Until the release of Electron 2.0][arm-breaking-change], Electron will also -continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries +continue to release the `armv7l` binary with a simple `arm` suffix. Both binaries are identical. Whether the prebuilt binary can run on a distribution depends on whether the