From 6e9a46042da30cbec7ec8f961e3030b5e047ebce Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Tue, 8 Jul 2025 15:22:52 +0200 Subject: [PATCH] fix: fullscreen for windows without rounded corners (#47682) Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr --- shell/browser/native_window_mac.h | 2 + shell/browser/native_window_mac.mm | 17 ++++--- shell/browser/ui/cocoa/electron_ns_window.mm | 3 -- .../ui/cocoa/electron_ns_window_delegate.h | 2 + .../ui/cocoa/electron_ns_window_delegate.mm | 5 ++ spec/api-browser-window-spec.ts | 48 +++++++++++++++++++ 6 files changed, 67 insertions(+), 10 deletions(-) diff --git a/shell/browser/native_window_mac.h b/shell/browser/native_window_mac.h index 5420e14aecd7..9eb4df3c22d7 100644 --- a/shell/browser/native_window_mac.h +++ b/shell/browser/native_window_mac.h @@ -175,6 +175,8 @@ class NativeWindowMac : public NativeWindow, // cleanup in destructor. void Cleanup(); + void SetBorderless(bool borderless); + void UpdateVibrancyRadii(bool fullscreen); void UpdateWindowOriginalFrame(); diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 9278ece8ea14..4e3c14b399eb 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -158,13 +158,6 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options, NSUInteger styleMask = NSWindowStyleMaskTitled; - // The NSWindowStyleMaskFullSizeContentView style removes rounded corners - // for frameless window. - const bool rounded_corner = - options.ValueOrDefault(options::kRoundedCorners, true); - if (!rounded_corner && !has_frame()) - styleMask = NSWindowStyleMaskBorderless; - if (minimizable) styleMask |= NSWindowStyleMaskMiniaturizable; if (closable) @@ -224,6 +217,11 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options, SetParentWindow(parent); } + const bool rounded_corner = + options.ValueOrDefault(options::kRoundedCorners, true); + if (!rounded_corner && !has_frame()) + SetBorderless(!rounded_corner); + if (transparent()) { // Setting the background color to clear will also hide the shadow. [window_ setBackgroundColor:[NSColor clearColor]]; @@ -775,6 +773,11 @@ void NativeWindowMac::MoveTop() { [window_ orderWindowByShuffling:NSWindowAbove relativeTo:0]; } +void NativeWindowMac::SetBorderless(bool borderless) { + SetStyleMask(!borderless, NSWindowStyleMaskTitled); + SetStyleMask(borderless, NSWindowStyleMaskBorderless); +} + void NativeWindowMac::SetResizable(bool resizable) { ScopedDisableResize disable_resize; SetStyleMask(resizable, NSWindowStyleMaskResizable); diff --git a/shell/browser/ui/cocoa/electron_ns_window.mm b/shell/browser/ui/cocoa/electron_ns_window.mm index cf9d479b93fc..3d5daec5df2d 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.mm +++ b/shell/browser/ui/cocoa/electron_ns_window.mm @@ -375,9 +375,6 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) { } - (BOOL)toggleFullScreenMode:(id)sender { - if (!shell_->has_frame() && !shell_->HasStyleMask(NSWindowStyleMaskTitled)) - return NO; - bool is_simple_fs = shell_->IsSimpleFullScreen(); bool always_simple_fs = shell_->always_simple_fullscreen(); diff --git a/shell/browser/ui/cocoa/electron_ns_window_delegate.h b/shell/browser/ui/cocoa/electron_ns_window_delegate.h index f65d78a095d1..1035f9e049e6 100644 --- a/shell/browser/ui/cocoa/electron_ns_window_delegate.h +++ b/shell/browser/ui/cocoa/electron_ns_window_delegate.h @@ -24,6 +24,8 @@ class NativeWindowMac; int level_; bool is_resizable_; + bool is_borderless_; + // Whether the window is currently minimized. Used to work // around a macOS bug with child window minimization. bool is_minimized_; diff --git a/shell/browser/ui/cocoa/electron_ns_window_delegate.mm b/shell/browser/ui/cocoa/electron_ns_window_delegate.mm index d2a64514f12e..df7b7b66eadb 100644 --- a/shell/browser/ui/cocoa/electron_ns_window_delegate.mm +++ b/shell/browser/ui/cocoa/electron_ns_window_delegate.mm @@ -299,6 +299,8 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle; - (void)windowWillEnterFullScreen:(NSNotification*)notification { // Store resizable mask so it can be restored after exiting fullscreen. is_resizable_ = shell_->HasStyleMask(NSWindowStyleMaskResizable); + // Store borderless mask so it can be restored after exiting fullscreen. + is_borderless_ = !shell_->HasStyleMask(NSWindowStyleMaskTitled); shell_->set_is_transitioning_fullscreen(true); @@ -306,6 +308,8 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle; // Set resizable to true before entering fullscreen. shell_->SetResizable(true); + // Set borderless to false before entering fullscreen. + shell_->SetBorderless(false); } - (void)windowDidEnterFullScreen:(NSNotification*)notification { @@ -341,6 +345,7 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle; shell_->set_is_transitioning_fullscreen(false); shell_->SetResizable(is_resizable_); + shell_->SetBorderless(is_borderless_); shell_->NotifyWindowLeaveFullScreen(); if (shell_->HandleDeferredClose()) diff --git a/spec/api-browser-window-spec.ts b/spec/api-browser-window-spec.ts index a54992049afd..71b62eeb77fa 100755 --- a/spec/api-browser-window-spec.ts +++ b/spec/api-browser-window-spec.ts @@ -5993,6 +5993,54 @@ describe('BrowserWindow module', () => { await leaveFullScreen; }); + it('should not crash if rounded corners are disabled', async () => { + const w = new BrowserWindow({ + frame: false, + roundedCorners: false + }); + + const enterFullScreen = once(w, 'enter-full-screen'); + w.setFullScreen(true); + await enterFullScreen; + + await setTimeout(); + + const leaveFullScreen = once(w, 'leave-full-screen'); + w.setFullScreen(false); + await leaveFullScreen; + }); + + it('should not crash if opening a borderless child window from fullscreen parent', async () => { + const parent = new BrowserWindow(); + + const parentFS = once(parent, 'enter-full-screen'); + parent.setFullScreen(true); + await parentFS; + + await setTimeout(); + + const child = new BrowserWindow({ + width: 400, + height: 300, + show: false, + parent, + frame: false, + roundedCorners: false + }); + + await setTimeout(); + + const childFS = once(child, 'enter-full-screen'); + child.show(); + await childFS; + + await setTimeout(); + + const leaveFullScreen = once(child, 'leave-full-screen'); + child.setFullScreen(false); + await leaveFullScreen; + }); + it('should be able to load a URL while transitioning to fullscreen', async () => { const w = new BrowserWindow({ fullscreen: true }); w.loadFile(path.join(fixtures, 'pages', 'c.html'));