Browse Source

fix: maximized window bounds when toggle setResizable (#40580)

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Tomasz Malinowski <[email protected]>
trop[bot] 1 year ago
parent
commit
917664c68b

+ 30 - 4
shell/browser/native_window_views.cc

@@ -644,11 +644,16 @@ void NativeWindowViews::Unmaximize() {
     if (transparent()) {
       SetBounds(restore_bounds_, false);
       NotifyWindowUnmaximize();
+      UpdateThickFrame();
       return;
     }
 #endif
 
     widget()->Restore();
+
+#if BUILDFLAG(IS_WIN)
+    UpdateThickFrame();
+#endif
   }
 }
 
@@ -681,6 +686,10 @@ void NativeWindowViews::Minimize() {
 
 void NativeWindowViews::Restore() {
   widget()->Restore();
+
+#if BUILDFLAG(IS_WIN)
+  UpdateThickFrame();
+#endif
 }
 
 bool NativeWindowViews::IsMinimized() {
@@ -831,12 +840,13 @@ void NativeWindowViews::SetResizable(bool resizable) {
           extensions::SizeConstraints(content_size, content_size));
     }
   }
-#if BUILDFLAG(IS_WIN)
-  if (has_frame() && thick_frame_)
-    FlipWindowStyle(GetAcceleratedWidget(), resizable, WS_THICKFRAME);
-#endif
+
   resizable_ = resizable;
   SetCanResize(resizable_);
+
+#if BUILDFLAG(IS_WIN)
+  UpdateThickFrame();
+#endif
 }
 
 bool NativeWindowViews::MoveAbove(const std::string& sourceId) {
@@ -1563,6 +1573,22 @@ void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) {
 }
 #endif
 
+#if BUILDFLAG(IS_WIN)
+void NativeWindowViews::UpdateThickFrame() {
+  if (!thick_frame_)
+    return;
+
+  if (IsMaximized() && !transparent()) {
+    // For maximized window add thick frame always, otherwise it will be removed
+    // in HWNDMessageHandler::SizeConstraintsChanged() which will result in
+    // maximized window bounds change.
+    FlipWindowStyle(GetAcceleratedWidget(), true, WS_THICKFRAME);
+  } else if (has_frame()) {
+    FlipWindowStyle(GetAcceleratedWidget(), resizable_, WS_THICKFRAME);
+  }
+}
+#endif
+
 void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
                                                   bool active) {
   if (changed_widget != widget())

+ 2 - 0
shell/browser/native_window_views.h

@@ -187,6 +187,8 @@ class NativeWindowViews : public NativeWindow,
   void set_overlay_symbol_color(SkColor color) {
     overlay_symbol_color_ = color;
   }
+
+  void UpdateThickFrame();
 #endif
 
  private:

+ 10 - 0
shell/browser/ui/win/electron_desktop_native_widget_aura.cc

@@ -30,6 +30,16 @@ void ElectronDesktopNativeWidgetAura::InitNativeWidget(
   views::DesktopNativeWidgetAura::InitNativeWidget(std::move(params));
 }
 
+#if BUILDFLAG(IS_WIN)
+void ElectronDesktopNativeWidgetAura::OnSizeConstraintsChanged() {
+  views::DesktopNativeWidgetAura::OnSizeConstraintsChanged();
+
+  // OnSizeConstraintsChanged can remove thick frame depending from
+  // resizable state, so add it if needed.
+  native_window_view_->UpdateThickFrame();
+}
+#endif
+
 void ElectronDesktopNativeWidgetAura::Activate() {
   // Activate can cause the focused window to be blurred so only
   // call when the window being activated is visible. This prevents

+ 3 - 0
shell/browser/ui/win/electron_desktop_native_widget_aura.h

@@ -27,6 +27,9 @@ class ElectronDesktopNativeWidgetAura : public views::DesktopNativeWidgetAura {
 
   // views::DesktopNativeWidgetAura:
   void InitNativeWidget(views::Widget::InitParams params) override;
+#if BUILDFLAG(IS_WIN)
+  void OnSizeConstraintsChanged() override;
+#endif
 
   // internal::NativeWidgetPrivate:
   void Activate() override;

+ 49 - 0
spec/api-browser-window-spec.ts

@@ -5075,6 +5075,55 @@ describe('BrowserWindow module', () => {
         w.setContentSize(10, 10);
         expectBoundsEqual(w.getContentSize(), [10, 10]);
       });
+
+      ifit(process.platform === 'win32')('do not change window with frame bounds when maximized', () => {
+        const w = new BrowserWindow({
+          show: true,
+          frame: true,
+          thickFrame: true
+        });
+        expect(w.isResizable()).to.be.true('resizable');
+        w.maximize();
+        expect(w.isMaximized()).to.be.true('maximized');
+        const bounds = w.getBounds();
+        w.setResizable(false);
+        expectBoundsEqual(w.getBounds(), bounds);
+        w.setResizable(true);
+        expectBoundsEqual(w.getBounds(), bounds);
+      });
+
+      ifit(process.platform === 'win32')('do not change window without frame bounds when maximized', () => {
+        const w = new BrowserWindow({
+          show: true,
+          frame: false,
+          thickFrame: true
+        });
+        expect(w.isResizable()).to.be.true('resizable');
+        w.maximize();
+        expect(w.isMaximized()).to.be.true('maximized');
+        const bounds = w.getBounds();
+        w.setResizable(false);
+        expectBoundsEqual(w.getBounds(), bounds);
+        w.setResizable(true);
+        expectBoundsEqual(w.getBounds(), bounds);
+      });
+
+      ifit(process.platform === 'win32')('do not change window transparent without frame bounds when maximized', () => {
+        const w = new BrowserWindow({
+          show: true,
+          frame: false,
+          thickFrame: true,
+          transparent: true
+        });
+        expect(w.isResizable()).to.be.true('resizable');
+        w.maximize();
+        expect(w.isMaximized()).to.be.true('maximized');
+        const bounds = w.getBounds();
+        w.setResizable(false);
+        expectBoundsEqual(w.getBounds(), bounds);
+        w.setResizable(true);
+        expectBoundsEqual(w.getBounds(), bounds);
+      });
     });
 
     describe('loading main frame state', () => {