Browse Source

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.
Birunthan Mohanathas 6 years ago
parent
commit
a42ca9eecc

+ 9 - 0
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)

+ 1 - 0
atom/browser/api/atom_api_top_level_window.h

@@ -173,6 +173,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
   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);

+ 4 - 0
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_;
 }

+ 3 - 0
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();

+ 6 - 0
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<mate::PersistentDictionary>& 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<bool> window_button_visibility_;
+
   // Simple (pre-Lion) Fullscreen Settings
   bool always_simple_fullscreen_ = false;
   bool is_simple_fullscreen_ = false;

+ 25 - 7
atom/browser/native_window_mac.mm

@@ -884,8 +884,9 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
       // 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 NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
     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 @@ bool NativeWindowMac::AddTabbedWindow(NativeWindow* window) {
   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];

+ 7 - 0
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

+ 27 - 0
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(() => {