From 0b032de3f221d94bedde2da7d53cc02dff9cc311 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Fri, 3 Jun 2022 09:47:19 +0200 Subject: [PATCH] fix: fullscreen windows aren't resizable on macOS --- shell/browser/native_window_mac.h | 1 + shell/browser/native_window_mac.mm | 20 ++++++++++++------- .../ui/cocoa/electron_ns_window_delegate.mm | 6 ++++-- spec-main/api-browser-window-spec.ts | 20 +++++++++++++++++-- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/shell/browser/native_window_mac.h b/shell/browser/native_window_mac.h index e9c6245085caa..21ccecc767a26 100644 --- a/shell/browser/native_window_mac.h +++ b/shell/browser/native_window_mac.h @@ -169,6 +169,7 @@ class NativeWindowMac : public NativeWindow, void UpdateWindowOriginalFrame(); // Set the attribute of NSWindow while work around a bug of zoom button. + bool HasStyleMask(NSUInteger flag) const; void SetStyleMask(bool on, NSUInteger flag); void SetCollectionBehavior(bool on, NSUInteger flag); void SetWindowLevel(int level); diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index a740aa263b327..2047b4c3241ea 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -646,7 +646,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } bool NativeWindowMac::IsMaximized() { - if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0) + if (HasStyleMask(NSWindowStyleMaskResizable) != 0) return [window_ isZoomed]; NSRect rectScreen = GetAspectRatio() > 0.0 @@ -729,7 +729,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } bool NativeWindowMac::IsFullscreen() const { - return [window_ styleMask] & NSWindowStyleMaskFullScreen; + return HasStyleMask(NSWindowStyleMaskFullScreen); } void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) { @@ -830,7 +830,10 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } bool NativeWindowMac::IsResizable() { - return [window_ styleMask] & NSWindowStyleMaskResizable; + bool in_fs_transition = + fullscreen_transition_state() != FullScreenTransitionState::NONE; + bool has_rs_mask = HasStyleMask(NSWindowStyleMaskResizable); + return has_rs_mask && !IsFullscreen() && !in_fs_transition; } void NativeWindowMac::SetMovable(bool movable) { @@ -846,7 +849,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } bool NativeWindowMac::IsMinimizable() { - return [window_ styleMask] & NSMiniaturizableWindowMask; + return HasStyleMask(NSWindowStyleMaskMiniaturizable); } void NativeWindowMac::SetMaximizable(bool maximizable) { @@ -876,7 +879,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { } bool NativeWindowMac::IsClosable() { - return [window_ styleMask] & NSWindowStyleMaskClosable; + return HasStyleMask(NSWindowStyleMaskClosable); } void NativeWindowMac::SetAlwaysOnTop(ui::ZOrderLevel z_order, @@ -1391,8 +1394,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { NSVisualEffectView* vibrantView = [window_ vibrantView]; if (vibrantView != nil && !vibrancy_type_.empty()) { - const bool no_rounded_corner = - !([window_ styleMask] & NSWindowStyleMaskTitled); + const bool no_rounded_corner = !HasStyleMask(NSWindowStyleMaskTitled); if (!has_frame() && !is_modal() && !no_rounded_corner) { CGFloat radius; if (fullscreen) { @@ -1767,6 +1769,10 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { AddContentViewLayers(); } +bool NativeWindowMac::HasStyleMask(NSUInteger flag) const { + return [window_ styleMask] & flag; +} + void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) { // Changing the styleMask of a frameless windows causes it to change size so // we explicitly disable resizing while setting it. diff --git a/shell/browser/ui/cocoa/electron_ns_window_delegate.mm b/shell/browser/ui/cocoa/electron_ns_window_delegate.mm index 79b2bc8faecc1..dc17a4f82254d 100644 --- a/shell/browser/ui/cocoa/electron_ns_window_delegate.mm +++ b/shell/browser/ui/cocoa/electron_ns_window_delegate.mm @@ -235,12 +235,14 @@ - (void)windowDidEndLiveResize:(NSNotification*)notification { } - (void)windowWillEnterFullScreen:(NSNotification*)notification { + // Store resizable mask so it can be restored after exiting fullscreen. + is_resizable_ = shell_->HasStyleMask(NSWindowStyleMaskResizable); + shell_->SetFullScreenTransitionState(FullScreenTransitionState::ENTERING); shell_->NotifyWindowWillEnterFullScreen(); - // Setting resizable to true before entering fullscreen. - is_resizable_ = shell_->IsResizable(); + // Set resizable to true before entering fullscreen. shell_->SetResizable(true); } diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 9d48cb77e6cb6..147b374e2a9b0 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -4892,12 +4892,13 @@ describe('BrowserWindow module', () => { }); ifdescribe(process.platform === 'darwin')('fullscreen state with resizable set', () => { - it('resizable flag should be set to true and restored', async () => { + it('resizable flag should be set to false and restored', async () => { const w = new BrowserWindow({ resizable: false }); + const enterFullScreen = emittedOnce(w, 'enter-full-screen'); w.setFullScreen(true); await enterFullScreen; - expect(w.resizable).to.be.true('resizable'); + expect(w.resizable).to.be.false('resizable'); await delay(); const leaveFullScreen = emittedOnce(w, 'leave-full-screen'); @@ -4905,6 +4906,21 @@ describe('BrowserWindow module', () => { await leaveFullScreen; expect(w.resizable).to.be.false('resizable'); }); + + it('default resizable flag should be restored after entering/exiting fullscreen', async () => { + const w = new BrowserWindow(); + + const enterFullScreen = emittedOnce(w, 'enter-full-screen'); + w.setFullScreen(true); + await enterFullScreen; + expect(w.resizable).to.be.false('resizable'); + + await delay(); + const leaveFullScreen = emittedOnce(w, 'leave-full-screen'); + w.setFullScreen(false); + await leaveFullScreen; + expect(w.resizable).to.be.true('resizable'); + }); }); ifdescribe(process.platform === 'darwin')('fullscreen state', () => {