fix: fullscreen for windows without rounded corners (#47683)

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
trop[bot] 2025-07-08 15:21:41 +02:00 committed by GitHub
parent e39cf315dc
commit c9c4c36a72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 67 additions and 10 deletions

View file

@ -175,6 +175,8 @@ class NativeWindowMac : public NativeWindow,
// cleanup in destructor. // cleanup in destructor.
void Cleanup(); void Cleanup();
void SetBorderless(bool borderless);
void UpdateVibrancyRadii(bool fullscreen); void UpdateVibrancyRadii(bool fullscreen);
void UpdateWindowOriginalFrame(); void UpdateWindowOriginalFrame();

View file

@ -158,13 +158,6 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
NSUInteger styleMask = NSWindowStyleMaskTitled; 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) if (minimizable)
styleMask |= NSWindowStyleMaskMiniaturizable; styleMask |= NSWindowStyleMaskMiniaturizable;
if (closable) if (closable)
@ -223,6 +216,11 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
SetParentWindow(parent); SetParentWindow(parent);
} }
const bool rounded_corner =
options.ValueOrDefault(options::kRoundedCorners, true);
if (!rounded_corner && !has_frame())
SetBorderless(!rounded_corner);
if (transparent()) { if (transparent()) {
// Setting the background color to clear will also hide the shadow. // Setting the background color to clear will also hide the shadow.
[window_ setBackgroundColor:[NSColor clearColor]]; [window_ setBackgroundColor:[NSColor clearColor]];
@ -774,6 +772,11 @@ void NativeWindowMac::MoveTop() {
[window_ orderWindowByShuffling:NSWindowAbove relativeTo:0]; [window_ orderWindowByShuffling:NSWindowAbove relativeTo:0];
} }
void NativeWindowMac::SetBorderless(bool borderless) {
SetStyleMask(!borderless, NSWindowStyleMaskTitled);
SetStyleMask(borderless, NSWindowStyleMaskBorderless);
}
void NativeWindowMac::SetResizable(bool resizable) { void NativeWindowMac::SetResizable(bool resizable) {
ScopedDisableResize disable_resize; ScopedDisableResize disable_resize;
SetStyleMask(resizable, NSWindowStyleMaskResizable); SetStyleMask(resizable, NSWindowStyleMaskResizable);

View file

@ -378,9 +378,6 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
} }
- (BOOL)toggleFullScreenMode:(id)sender { - (BOOL)toggleFullScreenMode:(id)sender {
if (!shell_->has_frame() && !shell_->HasStyleMask(NSWindowStyleMaskTitled))
return NO;
bool is_simple_fs = shell_->IsSimpleFullScreen(); bool is_simple_fs = shell_->IsSimpleFullScreen();
bool always_simple_fs = shell_->always_simple_fullscreen(); bool always_simple_fs = shell_->always_simple_fullscreen();

View file

@ -24,6 +24,8 @@ class NativeWindowMac;
int level_; int level_;
bool is_resizable_; bool is_resizable_;
bool is_borderless_;
// Whether the window is currently minimized. Used to work // Whether the window is currently minimized. Used to work
// around a macOS bug with child window minimization. // around a macOS bug with child window minimization.
bool is_minimized_; bool is_minimized_;

View file

@ -299,6 +299,8 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
- (void)windowWillEnterFullScreen:(NSNotification*)notification { - (void)windowWillEnterFullScreen:(NSNotification*)notification {
// Store resizable mask so it can be restored after exiting fullscreen. // Store resizable mask so it can be restored after exiting fullscreen.
is_resizable_ = shell_->HasStyleMask(NSWindowStyleMaskResizable); 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); shell_->set_is_transitioning_fullscreen(true);
@ -306,6 +308,8 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
// Set resizable to true before entering fullscreen. // Set resizable to true before entering fullscreen.
shell_->SetResizable(true); shell_->SetResizable(true);
// Set borderless to false before entering fullscreen.
shell_->SetBorderless(false);
} }
- (void)windowDidEnterFullScreen:(NSNotification*)notification { - (void)windowDidEnterFullScreen:(NSNotification*)notification {
@ -341,6 +345,7 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
shell_->set_is_transitioning_fullscreen(false); shell_->set_is_transitioning_fullscreen(false);
shell_->SetResizable(is_resizable_); shell_->SetResizable(is_resizable_);
shell_->SetBorderless(is_borderless_);
shell_->NotifyWindowLeaveFullScreen(); shell_->NotifyWindowLeaveFullScreen();
if (shell_->HandleDeferredClose()) if (shell_->HandleDeferredClose())

View file

@ -5993,6 +5993,54 @@ describe('BrowserWindow module', () => {
await leaveFullScreen; 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 () => { it('should be able to load a URL while transitioning to fullscreen', async () => {
const w = new BrowserWindow({ fullscreen: true }); const w = new BrowserWindow({ fullscreen: true });
w.loadFile(path.join(fixtures, 'pages', 'c.html')); w.loadFile(path.join(fixtures, 'pages', 'c.html'));