From ba5fa2c8b1a98278dce864d525036add0bba4d3a Mon Sep 17 00:00:00 2001 From: Zachary Flower Date: Sun, 13 Aug 2017 00:28:33 -0600 Subject: [PATCH 1/5] Add support for simple (pre-Lion) fullscreen on Mac OS --- atom/browser/api/atom_api_window.cc | 10 ++++ atom/browser/api/atom_api_window.h | 2 + atom/browser/native_window.h | 2 + atom/browser/native_window_mac.h | 17 ++++++ atom/browser/native_window_mac.mm | 90 ++++++++++++++++++++++++++++- atom/browser/native_window_views.cc | 8 +++ atom/browser/native_window_views.h | 2 + atom/common/options_switches.cc | 2 + atom/common/options_switches.h | 1 + 9 files changed, 133 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 34366e2db5d..1f95f6851d8 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -603,6 +603,14 @@ void Window::SetSkipTaskbar(bool skip) { window_->SetSkipTaskbar(skip); } +void Window::SetSimpleFullScreen(bool simple_fullscreen) { + window_->SetSimpleFullScreen(simple_fullscreen); +} + +bool Window::IsSimpleFullScreen() { + return window_->IsSimpleFullScreen(); +} + void Window::SetKiosk(bool kiosk) { window_->SetKiosk(kiosk); } @@ -1018,6 +1026,8 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("getTitle", &Window::GetTitle) .SetMethod("flashFrame", &Window::FlashFrame) .SetMethod("setSkipTaskbar", &Window::SetSkipTaskbar) + .SetMethod("setSimpleFullScreen", &Window::SetSimpleFullScreen) + .SetMethod("isSimpleFullScreen", &Window::IsSimpleFullScreen) .SetMethod("setKiosk", &Window::SetKiosk) .SetMethod("isKiosk", &Window::IsKiosk) .SetMethod("setBackgroundColor", &Window::SetBackgroundColor) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 22f7e730778..b7e81241061 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -154,6 +154,8 @@ class Window : public mate::TrackableObject, std::string GetTitle(); void FlashFrame(bool flash); void SetSkipTaskbar(bool skip); + void SetSimpleFullScreen(bool simple_fullscreen); + bool IsSimpleFullScreen(); void SetKiosk(bool kiosk); bool IsKiosk(); void SetBackgroundColor(const std::string& color_name); diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index dd874057895..69b3816ab38 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -134,6 +134,8 @@ class NativeWindow : public base::SupportsUserData, virtual std::string GetTitle() = 0; virtual void FlashFrame(bool flash) = 0; virtual void SetSkipTaskbar(bool skip) = 0; + virtual void SetSimpleFullScreen(bool simple_fullscreen) = 0; + virtual bool IsSimpleFullScreen() = 0; virtual void SetKiosk(bool kiosk) = 0; virtual bool IsKiosk() = 0; virtual void SetBackgroundColor(const std::string& color_name) = 0; diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 3dfb88d5398..f2a27e9e522 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -76,6 +76,8 @@ class NativeWindowMac : public NativeWindow, std::string GetTitle() override; void FlashFrame(bool flash) override; void SetSkipTaskbar(bool skip) override; + void SetSimpleFullScreen(bool simple_fullscreen) override; + bool IsSimpleFullScreen() override; void SetKiosk(bool kiosk) override; bool IsKiosk() override; void SetBackgroundColor(const std::string& color_name) override; @@ -135,6 +137,8 @@ class NativeWindowMac : public NativeWindow, bool fullscreen_window_title() const { return fullscreen_window_title_; } + bool simple_fullscreen() const { return simple_fullscreen_; } + protected: // Return a vector of non-draggable regions that fill a window of size // |width| by |height|, but leave gaps where the window should be draggable. @@ -189,6 +193,19 @@ class NativeWindowMac : public NativeWindow, // The "titleBarStyle" option. TitleBarStyle title_bar_style_; + // Simple (pre-Lion) Fullscreen Settings + bool simple_fullscreen_; + bool is_simple_fullscreen_; + bool was_maximized_; + bool was_minimizable_; + bool was_maximizable_; + bool was_resizable_; + bool was_movable_; + NSRect original_frame_; + + // The presentation options before entering simple fullscreen mode. + NSApplicationPresentationOptions simple_fullscreen_options_; + DISALLOW_COPY_AND_ASSIGN(NativeWindowMac); }; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 2719c672954..e44e5ec5cf1 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -720,6 +720,13 @@ enum { [super performClose:sender]; } +- (void)toggleFullScreen:(id)sender { + if (shell_->simple_fullscreen()) + shell_->SetSimpleFullScreen(!shell_->IsSimpleFullScreen()); + else + [super toggleFullScreen:sender]; +} + - (void)performMiniaturize:(id)sender { if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER) [self miniaturize:self]; @@ -819,7 +826,9 @@ NativeWindowMac::NativeWindowMac( zoom_to_page_width_(false), fullscreen_window_title_(false), attention_request_id_(0), - title_bar_style_(NORMAL) { + title_bar_style_(NORMAL), + simple_fullscreen_(false), + is_simple_fullscreen_(false) { int width = 800, height = 600; options.Get(options::kWidth, &width); options.Get(options::kHeight, &height); @@ -965,6 +974,8 @@ NativeWindowMac::NativeWindowMac( options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_); + options.Get(options::kSimpleFullScreen, &simple_fullscreen_); + // Enable the NSView to accept first mouse event. bool acceptsFirstMouse = false; options.Get(options::kAcceptFirstMouse, &acceptsFirstMouse); @@ -1351,6 +1362,83 @@ void NativeWindowMac::FlashFrame(bool flash) { void NativeWindowMac::SetSkipTaskbar(bool skip) { } +void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) { + NSWindow* window = GetNativeWindow(); + + if (simple_fullscreen && !is_simple_fullscreen_) { + is_simple_fullscreen_ = true; + + // Take note of the current window size + original_frame_ = [window frame]; + + simple_fullscreen_options_ = [NSApp currentSystemPresentationOptions]; + + // We can simulate the pre-Lion fullscreen by auto-hiding the dock and menu bar + NSApplicationPresentationOptions options = + NSApplicationPresentationAutoHideDock + + NSApplicationPresentationAutoHideMenuBar; + [NSApp setPresentationOptions:options]; + + was_maximized_ = IsMaximized(); + was_minimizable_ = IsMinimizable(); + was_maximizable_ = IsMaximizable(); + was_resizable_ = IsResizable(); + was_movable_ = IsMovable(); + + // if (!was_maximized_) Maximize(); + + NSRect fullscreenFrame = [window.screen frame]; + + if ( !fullscreen_window_title() ) { + // Hide the titlebar + SetStyleMask(false, NSTitledWindowMask); + + // Resize the window to accomodate the _entire_ screen size + fullscreenFrame.size.height -= [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + } else { + // No need to hide the title, but we should still hide the window buttons + [[window standardWindowButton:NSWindowZoomButton] setHidden:YES]; + [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; + [[window standardWindowButton:NSWindowCloseButton] setHidden:YES]; + } + + [window setFrame:fullscreenFrame display: YES animate: YES]; + + // Fullscreen windows can't be resized, minimized, etc. + if (was_minimizable_) SetMinimizable(false); + if (was_maximizable_) SetMaximizable(false); + if (was_resizable_) SetResizable(false); + if (was_movable_) SetMovable(false); + } else if (!simple_fullscreen && is_simple_fullscreen_) { + is_simple_fullscreen_ = false; + + if ( !fullscreen_window_title() ) { + // Restore the titlebar + SetStyleMask(true, NSTitledWindowMask); + } else { + // Show the window buttons + [[window standardWindowButton:NSWindowZoomButton] setHidden:NO]; + [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:NO]; + [[window standardWindowButton:NSWindowCloseButton] setHidden:NO]; + } + + [window setFrame:original_frame_ display: YES animate: YES]; + + [NSApp setPresentationOptions:simple_fullscreen_options_]; + + // Restore window manipulation abilities + // if (!was_maximized_) Unmaximize(); + if (was_minimizable_) SetMinimizable(true); + if (was_maximizable_) SetMaximizable(true); + if (was_resizable_) SetResizable(true); + if (was_movable_) SetMovable(true); + } +} + +bool NativeWindowMac::IsSimpleFullScreen() { + return is_simple_fullscreen_; +} + void NativeWindowMac::SetKiosk(bool kiosk) { if (kiosk && !is_kiosk_) { kiosk_options_ = [NSApp currentSystemPresentationOptions]; diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 94e2f09c964..27f68756eec 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -754,6 +754,14 @@ void NativeWindowViews::SetSkipTaskbar(bool skip) { #endif } +void NativeWindowViews::SetSimpleFullScreen(bool simple_fullscreen) { + SetFullScreen(simple_fullscreen); +} + +bool NativeWindowViews::IsSimpleFullScreen() { + return IsFullscreen(); +} + void NativeWindowViews::SetKiosk(bool kiosk) { SetFullScreen(kiosk); } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 5d94c2255bb..88030fb4bd8 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -96,6 +96,8 @@ class NativeWindowViews : public NativeWindow, std::string GetTitle() override; void FlashFrame(bool flash) override; void SetSkipTaskbar(bool skip) override; + void SetSimpleFullScreen(bool simple_fullscreen) override; + bool IsSimpleFullScreen() override; void SetKiosk(bool kiosk) override; bool IsKiosk() override; void SetBackgroundColor(const std::string& color_name) override; diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index 8822c55f9a4..76aa1903f79 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -36,6 +36,8 @@ const char kSkipTaskbar[] = "skipTaskbar"; // http://www.opera.com/support/mastering/kiosk/ const char kKiosk[] = "kiosk"; +const char kSimpleFullScreen[] = "simpleFullscreen"; + // Make windows stays on the top of all other windows. const char kAlwaysOnTop[] = "alwaysOnTop"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index 171e6b5a79f..fde740cd919 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -31,6 +31,7 @@ extern const char kClosable[]; extern const char kFullscreen[]; extern const char kSkipTaskbar[]; extern const char kKiosk[]; +extern const char kSimpleFullScreen[]; extern const char kAlwaysOnTop[]; extern const char kAcceptFirstMouse[]; extern const char kUseContentSize[]; From 8a2c35023fac9d6d55b2ebc6699b25d14d45456a Mon Sep 17 00:00:00 2001 From: Zachary Flower Date: Sun, 13 Aug 2017 00:35:03 -0600 Subject: [PATCH 2/5] :memo: Document simple fullscreen functionality [ci skip] --- docs/api/browser-window.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index e08c8de8c91..660db87ef5b 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -176,6 +176,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `fullscreenable` Boolean (optional) - Whether the window can be put into fullscreen mode. On macOS, also whether the maximize/zoom button should toggle full screen mode or maximize window. Default is `true`. + * `simpleFullscreen` Boolean (optional) - Use pre-Lion fullscreen on macOS. Default is `false`. * `skipTaskbar` Boolean (optional) - Whether to show the window in taskbar. Default is `false`. * `kiosk` Boolean (optional) - The kiosk mode. Default is `false`. @@ -766,6 +767,16 @@ Sets whether the window should be in fullscreen mode. Returns `Boolean` - Whether the window is in fullscreen mode. +#### `win.setSimpleFullScreen(flag)` _macOS_ + +* `flag` Boolean + +Sets whether the window should be in simple fullscreen mode. + +#### `win.isSimpleFullScreen()` _macOS_ + +Returns `Boolean` - Whether the window is in simple fullscreen mode. + #### `win.setAspectRatio(aspectRatio[, extraSize])` _macOS_ * `aspectRatio` Float - The aspect ratio to maintain for some portion of the From f256967414f0da826c4eb420a4429c9a1cbe403c Mon Sep 17 00:00:00 2001 From: Zachary Flower Date: Mon, 11 Sep 2017 23:09:45 -0600 Subject: [PATCH 3/5] :memo: make clear what simple fullscreen mode is --- docs/api/browser-window.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 660db87ef5b..64e244f3010 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -771,11 +771,13 @@ Returns `Boolean` - Whether the window is in fullscreen mode. * `flag` Boolean -Sets whether the window should be in simple fullscreen mode. +Enters or leaves simple fullscreen mode. + +Simple fullscreen mode emulates the native fullscreen behavior found in versions of Mac OS X prior to Lion (10.7). #### `win.isSimpleFullScreen()` _macOS_ -Returns `Boolean` - Whether the window is in simple fullscreen mode. +Returns `Boolean` - Whether the window is in simple (pre-Lion) fullscreen mode. #### `win.setAspectRatio(aspectRatio[, extraSize])` _macOS_ From fa4d52f042d5440be16b50b79a5ce7883ff96f8a Mon Sep 17 00:00:00 2001 From: Zachary Flower Date: Tue, 12 Sep 2017 12:27:30 -0600 Subject: [PATCH 4/5] :art: Track/restore original stylemask, rather than individual states. --- atom/browser/native_window_mac.h | 4 +--- atom/browser/native_window_mac.mm | 29 +++++++++++++---------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index f2a27e9e522..5515ed72e73 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -196,12 +196,10 @@ class NativeWindowMac : public NativeWindow, // Simple (pre-Lion) Fullscreen Settings bool simple_fullscreen_; bool is_simple_fullscreen_; - bool was_maximized_; - bool was_minimizable_; bool was_maximizable_; - bool was_resizable_; bool was_movable_; NSRect original_frame_; + NSUInteger simple_fullscreen_mask_; // The presentation options before entering simple fullscreen mode. NSApplicationPresentationOptions simple_fullscreen_options_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index e44e5ec5cf1..72e9441804a 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -1372,6 +1372,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) { original_frame_ = [window frame]; simple_fullscreen_options_ = [NSApp currentSystemPresentationOptions]; + simple_fullscreen_mask_ = [window styleMask]; // We can simulate the pre-Lion fullscreen by auto-hiding the dock and menu bar NSApplicationPresentationOptions options = @@ -1379,14 +1380,9 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) { NSApplicationPresentationAutoHideMenuBar; [NSApp setPresentationOptions:options]; - was_maximized_ = IsMaximized(); - was_minimizable_ = IsMinimizable(); was_maximizable_ = IsMaximizable(); - was_resizable_ = IsResizable(); was_movable_ = IsMovable(); - // if (!was_maximized_) Maximize(); - NSRect fullscreenFrame = [window.screen frame]; if ( !fullscreen_window_title() ) { @@ -1404,11 +1400,11 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) { [window setFrame:fullscreenFrame display: YES animate: YES]; - // Fullscreen windows can't be resized, minimized, etc. - if (was_minimizable_) SetMinimizable(false); - if (was_maximizable_) SetMaximizable(false); - if (was_resizable_) SetResizable(false); - if (was_movable_) SetMovable(false); + // Fullscreen windows can't be resized, minimized, maximized, or moved + SetMinimizable(false); + SetResizable(false); + SetMaximizable(false); + SetMovable(false); } else if (!simple_fullscreen && is_simple_fullscreen_) { is_simple_fullscreen_ = false; @@ -1425,13 +1421,14 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) { [window setFrame:original_frame_ display: YES animate: YES]; [NSApp setPresentationOptions:simple_fullscreen_options_]; - + + // Restore original style mask + ScopedDisableResize disable_resize; + [window_ setStyleMask:simple_fullscreen_mask_]; + // Restore window manipulation abilities - // if (!was_maximized_) Unmaximize(); - if (was_minimizable_) SetMinimizable(true); - if (was_maximizable_) SetMaximizable(true); - if (was_resizable_) SetResizable(true); - if (was_movable_) SetMovable(true); + SetMaximizable(was_maximizable_); + SetMovable(was_movable_); } } From 432b912c6ac7385228d5a64e9685b3f4540917f8 Mon Sep 17 00:00:00 2001 From: Zachary Flower Date: Wed, 13 Sep 2017 12:16:37 -0600 Subject: [PATCH 5/5] :art: Rename ambiguous simple_fullscreen_ variable to always_simple_fullscreen_ --- atom/browser/native_window_mac.h | 4 ++-- atom/browser/native_window_mac.mm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 5515ed72e73..bab6671d676 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -137,7 +137,7 @@ class NativeWindowMac : public NativeWindow, bool fullscreen_window_title() const { return fullscreen_window_title_; } - bool simple_fullscreen() const { return simple_fullscreen_; } + bool simple_fullscreen() const { return always_simple_fullscreen_; } protected: // Return a vector of non-draggable regions that fill a window of size @@ -194,7 +194,7 @@ class NativeWindowMac : public NativeWindow, TitleBarStyle title_bar_style_; // Simple (pre-Lion) Fullscreen Settings - bool simple_fullscreen_; + bool always_simple_fullscreen_; bool is_simple_fullscreen_; bool was_maximizable_; bool was_movable_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 72e9441804a..e47fe513d23 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -827,7 +827,7 @@ NativeWindowMac::NativeWindowMac( fullscreen_window_title_(false), attention_request_id_(0), title_bar_style_(NORMAL), - simple_fullscreen_(false), + always_simple_fullscreen_(false), is_simple_fullscreen_(false) { int width = 800, height = 600; options.Get(options::kWidth, &width); @@ -974,7 +974,7 @@ NativeWindowMac::NativeWindowMac( options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_); - options.Get(options::kSimpleFullScreen, &simple_fullscreen_); + options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_); // Enable the NSView to accept first mouse event. bool acceptsFirstMouse = false;