fix: fullscreen windows aren't resizable on macOS (#34379)

This commit is contained in:
Shelley Vohr 2022-06-03 09:47:19 +02:00 committed by GitHub
parent b00c026a54
commit 6038e42c23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 11 deletions

View file

@ -167,6 +167,7 @@ class NativeWindowMac : public NativeWindow,
void UpdateVibrancyRadii(bool fullscreen); void UpdateVibrancyRadii(bool fullscreen);
// Set the attribute of NSWindow while work around a bug of zoom button. // 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 SetStyleMask(bool on, NSUInteger flag);
void SetCollectionBehavior(bool on, NSUInteger flag); void SetCollectionBehavior(bool on, NSUInteger flag);
void SetWindowLevel(int level); void SetWindowLevel(int level);

View file

@ -642,7 +642,7 @@ void NativeWindowMac::Unmaximize() {
} }
bool NativeWindowMac::IsMaximized() { bool NativeWindowMac::IsMaximized() {
if (([window_ styleMask] & NSWindowStyleMaskResizable) != 0) if (HasStyleMask(NSWindowStyleMaskResizable) != 0)
return [window_ isZoomed]; return [window_ isZoomed];
NSRect rectScreen = GetAspectRatio() > 0.0 NSRect rectScreen = GetAspectRatio() > 0.0
@ -725,7 +725,7 @@ void NativeWindowMac::SetFullScreen(bool fullscreen) {
} }
bool NativeWindowMac::IsFullscreen() const { bool NativeWindowMac::IsFullscreen() const {
return [window_ styleMask] & NSWindowStyleMaskFullScreen; return HasStyleMask(NSWindowStyleMaskFullScreen);
} }
void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) { void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
@ -825,7 +825,10 @@ void NativeWindowMac::SetResizable(bool resizable) {
} }
bool NativeWindowMac::IsResizable() { 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) { void NativeWindowMac::SetMovable(bool movable) {
@ -841,7 +844,7 @@ void NativeWindowMac::SetMinimizable(bool minimizable) {
} }
bool NativeWindowMac::IsMinimizable() { bool NativeWindowMac::IsMinimizable() {
return [window_ styleMask] & NSWindowStyleMaskMiniaturizable; return HasStyleMask(NSWindowStyleMaskMiniaturizable);
} }
void NativeWindowMac::SetMaximizable(bool maximizable) { void NativeWindowMac::SetMaximizable(bool maximizable) {
@ -871,7 +874,7 @@ void NativeWindowMac::SetClosable(bool closable) {
} }
bool NativeWindowMac::IsClosable() { bool NativeWindowMac::IsClosable() {
return [window_ styleMask] & NSWindowStyleMaskClosable; return HasStyleMask(NSWindowStyleMaskClosable);
} }
void NativeWindowMac::SetAlwaysOnTop(ui::ZOrderLevel z_order, void NativeWindowMac::SetAlwaysOnTop(ui::ZOrderLevel z_order,
@ -1379,8 +1382,7 @@ void NativeWindowMac::UpdateVibrancyRadii(bool fullscreen) {
NSVisualEffectView* vibrantView = [window_ vibrantView]; NSVisualEffectView* vibrantView = [window_ vibrantView];
if (vibrantView != nil && !vibrancy_type_.empty()) { if (vibrantView != nil && !vibrancy_type_.empty()) {
const bool no_rounded_corner = const bool no_rounded_corner = !HasStyleMask(NSWindowStyleMaskTitled);
!([window_ styleMask] & NSWindowStyleMaskTitled);
if (!has_frame() && !is_modal() && !no_rounded_corner) { if (!has_frame() && !is_modal() && !no_rounded_corner) {
CGFloat radius; CGFloat radius;
if (fullscreen) { if (fullscreen) {
@ -1731,6 +1733,10 @@ void NativeWindowMac::OverrideNSWindowContentView() {
AddContentViewLayers(); AddContentViewLayers();
} }
bool NativeWindowMac::HasStyleMask(NSUInteger flag) const {
return [window_ styleMask] & flag;
}
void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) { void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) {
// Changing the styleMask of a frameless windows causes it to change size so // Changing the styleMask of a frameless windows causes it to change size so
// we explicitly disable resizing while setting it. // we explicitly disable resizing while setting it.

View file

@ -234,12 +234,14 @@ using FullScreenTransitionState =
} }
- (void)windowWillEnterFullScreen:(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_->SetFullScreenTransitionState(FullScreenTransitionState::ENTERING);
shell_->NotifyWindowWillEnterFullScreen(); shell_->NotifyWindowWillEnterFullScreen();
// Setting resizable to true before entering fullscreen. // Set resizable to true before entering fullscreen.
is_resizable_ = shell_->IsResizable();
shell_->SetResizable(true); shell_->SetResizable(true);
} }

View file

@ -4650,12 +4650,13 @@ describe('BrowserWindow module', () => {
}); });
ifdescribe(process.platform === 'darwin')('fullscreen state with resizable set', () => { 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 w = new BrowserWindow({ resizable: false });
const enterFullScreen = emittedOnce(w, 'enter-full-screen'); const enterFullScreen = emittedOnce(w, 'enter-full-screen');
w.setFullScreen(true); w.setFullScreen(true);
await enterFullScreen; await enterFullScreen;
expect(w.resizable).to.be.true('resizable'); expect(w.resizable).to.be.false('resizable');
await delay(); await delay();
const leaveFullScreen = emittedOnce(w, 'leave-full-screen'); const leaveFullScreen = emittedOnce(w, 'leave-full-screen');
@ -4663,6 +4664,21 @@ describe('BrowserWindow module', () => {
await leaveFullScreen; await leaveFullScreen;
expect(w.resizable).to.be.false('resizable'); 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', () => { ifdescribe(process.platform === 'darwin')('fullscreen state', () => {