Browse Source

fix: maximized state calculation for non-resizable windows (#30989)

Shelley Vohr 3 years ago
parent
commit
629d8913f6

+ 1 - 1
docs/api/browser-window.md

@@ -988,7 +988,7 @@ the player itself we would call this function with arguments of 16/9 and
 are within the content view--only that they exist. Sum any extra width and
 height areas you have within the overall content view.
 
-The aspect ratio is not respected when window is resized programmingly with
+The aspect ratio is not respected when window is resized programmatically with
 APIs like `win.setSize`.
 
 #### `win.setBackgroundColor(backgroundColor)`

+ 14 - 0
shell/browser/native_window_mac.h

@@ -188,6 +188,19 @@ class NativeWindowMac : public NativeWindow,
   bool zoom_to_page_width() const { return zoom_to_page_width_; }
   bool always_simple_fullscreen() const { return always_simple_fullscreen_; }
 
+  // We need to save the result of windowWillUseStandardFrame:defaultFrame
+  // because macOS calls it with what it refers to as the "best fit" frame for a
+  // zoom. This means that even if an aspect ratio is set, macOS might adjust it
+  // to better fit the screen.
+  //
+  // Thus, we can't just calculate the maximized aspect ratio'd sizing from
+  // the current visible screen and compare that to the current window's frame
+  // to determine whether a window is maximized.
+  NSRect default_frame_for_zoom() const { return default_frame_for_zoom_; }
+  void set_default_frame_for_zoom(NSRect frame) {
+    default_frame_for_zoom_ = frame;
+  }
+
  protected:
   // views::WidgetDelegate:
   views::View* GetContentsView() override;
@@ -263,6 +276,7 @@ class NativeWindowMac : public NativeWindow,
   NSRect original_frame_;
   NSInteger original_level_;
   NSUInteger simple_fullscreen_mask_;
+  NSRect default_frame_for_zoom_;
 
   std::string vibrancy_type_;
 

+ 7 - 9
shell/browser/native_window_mac.mm

@@ -609,16 +609,14 @@ void NativeWindowMac::Unmaximize() {
 }
 
 bool NativeWindowMac::IsMaximized() {
-  if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0) {
+  if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0)
     return [window_ isZoomed];
-  } else {
-    NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
-    NSRect rectWindow = [window_ frame];
-    return (rectScreen.origin.x == rectWindow.origin.x &&
-            rectScreen.origin.y == rectWindow.origin.y &&
-            rectScreen.size.width == rectWindow.size.width &&
-            rectScreen.size.height == rectWindow.size.height);
-  }
+
+  NSRect rectScreen = GetAspectRatio() > 0.0
+                          ? default_frame_for_zoom()
+                          : [[NSScreen mainScreen] visibleFrame];
+
+  return NSEqualRects([window_ frame], rectScreen);
 }
 
 void NativeWindowMac::Minimize() {

+ 7 - 1
shell/browser/ui/cocoa/electron_ns_window_delegate.mm

@@ -63,8 +63,11 @@ using FullScreenTransitionState =
 // menu to determine the "standard size" of the window.
 - (NSRect)windowWillUseStandardFrame:(NSWindow*)window
                         defaultFrame:(NSRect)frame {
-  if (!shell_->zoom_to_page_width())
+  if (!shell_->zoom_to_page_width()) {
+    if (shell_->GetAspectRatio() > 0.0)
+      shell_->set_default_frame_for_zoom(frame);
     return frame;
+  }
 
   // If the shift key is down, maximize.
   if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
@@ -89,6 +92,9 @@ using FullScreenTransitionState =
   // Set the width. Don't touch y or height.
   frame.size.width = zoomed_width;
 
+  if (shell_->GetAspectRatio() > 0.0)
+    shell_->set_default_frame_for_zoom(frame);
+
   return frame;
 }
 

+ 18 - 0
spec-main/api-browser-window-spec.ts

@@ -1113,6 +1113,24 @@ describe('BrowserWindow module', () => {
           await unmaximize;
           expect(w.isMaximized()).to.equal(false);
         });
+        it('returns the correct value for windows with an aspect ratio', async () => {
+          w.destroy();
+          w = new BrowserWindow({
+            show: false,
+            fullscreenable: false
+          });
+
+          w.setAspectRatio(16 / 11);
+
+          const maximize = emittedOnce(w, 'resize');
+          w.show();
+          w.maximize();
+          await maximize;
+
+          expect(w.isMaximized()).to.equal(true);
+          w.resizable = false;
+          expect(w.isMaximized()).to.equal(true);
+        });
       });
 
       ifdescribe(process.platform !== 'linux')('Minimized state', () => {