From a42ca9eecc6e82c087604f92a3e6581de66ece5a Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 3 Jul 2018 10:20:56 +0200 Subject: [PATCH] feat: Add BrowserWindow.setWindowButtonVisibility() Fixes #12701 and supersedes #13131. Ideally we would have added `setTitleBarStyle()`, but that is a significantly more involved change. For example, consider the case where we switch from `hidden` to `normal`. We would not only have to show the traffic light buttons, we would also have to switch the window from a frameless to a framed window and deal with various other window state. Lets instead implement a simple solution for #12701. --- atom/browser/api/atom_api_top_level_window.cc | 9 ++++++ atom/browser/api/atom_api_top_level_window.h | 1 + atom/browser/native_window.cc | 4 +++ atom/browser/native_window.h | 3 ++ atom/browser/native_window_mac.h | 6 ++++ atom/browser/native_window_mac.mm | 32 +++++++++++++++---- docs/api/browser-window.md | 7 ++++ spec/api-browser-window-spec.js | 27 ++++++++++++++++ 8 files changed, 82 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_top_level_window.cc b/atom/browser/api/atom_api_top_level_window.cc index dda8bb6ca0bda..365f97f0d8fb0 100644 --- a/atom/browser/api/atom_api_top_level_window.cc +++ b/atom/browser/api/atom_api_top_level_window.cc @@ -738,6 +738,13 @@ void TopLevelWindow::AddTabbedWindow(NativeWindow* window, args->ThrowError("AddTabbedWindow cannot be called by a window on itself."); } +void TopLevelWindow::SetWindowButtonVisibility(bool visible, + mate::Arguments* args) { + if (!window_->SetWindowButtonVisibility(visible)) { + args->ThrowError("Not supported for this window"); + } +} + void TopLevelWindow::SetAutoHideMenuBar(bool auto_hide) { window_->SetAutoHideMenuBar(auto_hide); } @@ -1030,6 +1037,8 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate, .SetMethod("moveTabToNewWindow", &TopLevelWindow::MoveTabToNewWindow) .SetMethod("toggleTabBar", &TopLevelWindow::ToggleTabBar) .SetMethod("addTabbedWindow", &TopLevelWindow::AddTabbedWindow) + .SetMethod("setWindowButtonVisibility", + &TopLevelWindow::SetWindowButtonVisibility) #endif .SetMethod("setAutoHideMenuBar", &TopLevelWindow::SetAutoHideMenuBar) .SetMethod("isMenuBarAutoHide", &TopLevelWindow::IsMenuBarAutoHide) diff --git a/atom/browser/api/atom_api_top_level_window.h b/atom/browser/api/atom_api_top_level_window.h index bf64ac7c616af..fe7c8b3b95ab1 100644 --- a/atom/browser/api/atom_api_top_level_window.h +++ b/atom/browser/api/atom_api_top_level_window.h @@ -173,6 +173,7 @@ class TopLevelWindow : public mate::TrackableObject, void MoveTabToNewWindow(); void ToggleTabBar(); void AddTabbedWindow(NativeWindow* window, mate::Arguments* args); + void SetWindowButtonVisibility(bool visible, mate::Arguments* args); void SetAutoHideMenuBar(bool auto_hide); bool IsMenuBarAutoHide(); void SetMenuBarVisibility(bool visible); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 4048e2a32b251..a339a2d23a331 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -355,6 +355,10 @@ bool NativeWindow::IsMenuBarVisible() { return true; } +bool NativeWindow::SetWindowButtonVisibility(bool visible) { + return false; +} + double NativeWindow::GetAspectRatio() { return aspect_ratio_; } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 759d7cb202101..d28a387b83726 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -187,6 +187,9 @@ class NativeWindow : public base::SupportsUserData, virtual void ToggleTabBar(); virtual bool AddTabbedWindow(NativeWindow* window); + // Returns false if unsupported. + virtual bool SetWindowButtonVisibility(bool visible); + // Toggle the menu bar. virtual void SetAutoHideMenuBar(bool auto_hide); virtual bool IsMenuBarAutoHide(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 54891c5b35af7..44a78198f44cd 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -119,6 +119,8 @@ class NativeWindowMac : public NativeWindow { void ToggleTabBar() override; bool AddTabbedWindow(NativeWindow* window) override; + bool SetWindowButtonVisibility(bool visible) override; + void SetVibrancy(const std::string& type) override; void SetTouchBar( const std::vector& items) override; @@ -193,6 +195,10 @@ class NativeWindowMac : public NativeWindow { // The "titleBarStyle" option. TitleBarStyle title_bar_style_ = NORMAL; + // The visibility mode of window button controls when explicitly set through + // setWindowButtonVisibility(). + base::Optional window_button_visibility_; + // Simple (pre-Lion) Fullscreen Settings bool always_simple_fullscreen_ = false; bool is_simple_fullscreen_ = false; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 2d8149668e598..004263ec12770 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -884,8 +884,9 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { // 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 + } else if (!window_button_visibility_.has_value()) { + // Lets keep previous behaviour - hide window controls in titled + // fullscreen mode when not specified otherwise. [[window standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; [[window standardWindowButton:NSWindowCloseButton] setHidden:YES]; @@ -904,13 +905,17 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { 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]; } + // Restore window controls visibility state + const bool window_button_hidden = !window_button_visibility_.value_or(true); + [[window standardWindowButton:NSWindowZoomButton] + setHidden:window_button_hidden]; + [[window standardWindowButton:NSWindowMiniaturizeButton] + setHidden:window_button_hidden]; + [[window standardWindowButton:NSWindowCloseButton] + setHidden:window_button_hidden]; + [window setFrame:original_frame_ display:YES animate:YES]; [NSApp setPresentationOptions:simple_fullscreen_options_]; @@ -1148,6 +1153,19 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { return true; } +bool NativeWindowMac::SetWindowButtonVisibility(bool visible) { + if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) { + return false; + } + + window_button_visibility_ = visible; + + [[window_ standardWindowButton:NSWindowCloseButton] setHidden:!visible]; + [[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:!visible]; + [[window_ standardWindowButton:NSWindowZoomButton] setHidden:!visible]; + return true; +} + void NativeWindowMac::SetVibrancy(const std::string& type) { if (@available(macOS 10.10, *)) { NSView* vibrant_view = [window_ vibrantView]; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 384f412254d05..a01d1037ee746 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -1342,6 +1342,13 @@ Same as `webContents.showDefinitionForSelection()`. Changes window icon. +#### `win.setWindowButtonVisibility(visible)` _macOS_ + +* `visible` Boolean + +Sets whether the window traffic light buttons should be visible. This has no +effect when `titleBarStyle` is set to `customButtonsOnHover`. + #### `win.setAutoHideMenuBar(hide)` * `hide` Boolean diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 9235db80f1d0b..9ff66b646a4a2 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -765,6 +765,33 @@ describe('BrowserWindow module', () => { }) }) + describe('BrowserWindow.setWindowButtonVisibility()', () => { + before(function () { + if (process.platform !== 'darwin') { + this.skip() + } + }) + + it('does not throw', () => { + assert.doesNotThrow(() => { + w.setWindowButtonVisibility(true) + w.setWindowButtonVisibility(false) + }) + }) + + it('throws with custom title bar buttons', () => { + assert.throws(() => { + w.destroy() + w = new BrowserWindow({ + show: false, + titleBarStyle: 'customButtonsOnHover', + frame: false + }) + w.setWindowButtonVisibility(true) + }, /Not supported for this window/) + }) + }) + describe('BrowserWindow.setVibrancy(type)', () => { it('allows setting, changing, and removing the vibrancy', () => { assert.doesNotThrow(() => {