Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macOS] Fix transparent and borderless flags interaction with full-screen mode. #84683

Merged
merged 1 commit into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion platform/macos/display_server_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class DisplayServerMacOS : public DisplayServer {
bool mpass = false;
bool focused = false;
bool is_visible = true;
bool extend_to_title = false;

Rect2i parent_safe_rect;
};
Expand Down Expand Up @@ -209,7 +210,6 @@ class DisplayServerMacOS : public DisplayServer {

WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
void _update_window_style(WindowData p_wd);
void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);

void _update_displays_arrangement();
Point2i _get_screens_origin() const;
Expand Down Expand Up @@ -261,6 +261,7 @@ class DisplayServerMacOS : public DisplayServer {
void window_destroy(WindowID p_window);
void window_resize(WindowID p_window, int p_width, int p_height);
void window_set_custom_window_buttons(WindowData &p_wd, bool p_enabled);
void set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);

virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
Expand Down
92 changes: 49 additions & 43 deletions platform/macos/display_server_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -270,53 +270,46 @@
}
}

void DisplayServerMacOS::_set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) {
void DisplayServerMacOS::set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];

if (!OS::get_singleton()->is_layered_allowed()) {
return;
}
if (wd.layered_window != p_enabled) {
if (p_enabled) {
[wd.window_object setBackgroundColor:[NSColor clearColor]];
[wd.window_object setOpaque:NO];
[wd.window_object setHasShadow:NO];
CALayer *layer = [(NSView *)wd.window_view layer];
if (layer) {
[layer setBackgroundColor:[NSColor clearColor].CGColor];
[layer setOpaque:NO];
}
if (p_enabled) {
[wd.window_object setBackgroundColor:[NSColor clearColor]];
[wd.window_object setOpaque:NO];
[wd.window_object setHasShadow:NO];
CALayer *layer = [(NSView *)wd.window_view layer];
if (layer) {
[layer setBackgroundColor:[NSColor clearColor].CGColor];
[layer setOpaque:NO];
}
#if defined(GLES3_ENABLED)
if (gl_manager_legacy) {
gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, true);
}
if (gl_manager_legacy) {
gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, true);
}
#endif
wd.layered_window = true;
} else {
NSColor *bg_color = [NSColor windowBackgroundColor];
Color _bg_color;
if (_get_window_early_clear_override(_bg_color)) {
bg_color = [NSColor colorWithCalibratedRed:_bg_color.r green:_bg_color.g blue:_bg_color.b alpha:1.f];
}
[wd.window_object setBackgroundColor:bg_color];
[wd.window_object setOpaque:YES];
[wd.window_object setHasShadow:YES];
CALayer *layer = [(NSView *)wd.window_view layer];
if (layer) {
[layer setBackgroundColor:bg_color.CGColor];
[layer setOpaque:YES];
}
} else {
NSColor *bg_color = [NSColor windowBackgroundColor];
Color _bg_color;
if (_get_window_early_clear_override(_bg_color)) {
bg_color = [NSColor colorWithCalibratedRed:_bg_color.r green:_bg_color.g blue:_bg_color.b alpha:1.f];
}
[wd.window_object setBackgroundColor:bg_color];
[wd.window_object setOpaque:YES];
[wd.window_object setHasShadow:YES];
CALayer *layer = [(NSView *)wd.window_view layer];
if (layer) {
[layer setBackgroundColor:bg_color.CGColor];
[layer setOpaque:YES];
}
#if defined(GLES3_ENABLED)
if (gl_manager_legacy) {
gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, false);
}
#endif
wd.layered_window = false;
if (gl_manager_legacy) {
gl_manager_legacy->window_set_per_pixel_transparency_enabled(p_window, false);
}
NSRect frameRect = [wd.window_object frame];
[wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:YES];
[wd.window_object setFrame:frameRect display:YES];
#endif
}
}

Expand Down Expand Up @@ -3295,7 +3288,6 @@ - (void)popupAction:(id)sender {
}

[(NSWindow *)wd.window_object setLevel:NSNormalWindowLevel];
_set_window_per_pixel_transparency_enabled(true, p_window);
if (wd.resize_disabled) { // Restore resize disabled.
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
}
Expand Down Expand Up @@ -3332,7 +3324,6 @@ - (void)popupAction:(id)sender {
} break;
case WINDOW_MODE_EXCLUSIVE_FULLSCREEN:
case WINDOW_MODE_FULLSCREEN: {
_set_window_per_pixel_transparency_enabled(false, p_window);
if (wd.resize_disabled) { // Fullscreen window should be resizable to work.
[wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable];
}
Expand Down Expand Up @@ -3489,6 +3480,7 @@ - (void)popupAction:(id)sender {
} break;
case WINDOW_FLAG_EXTEND_TO_TITLE: {
NSRect rect = [wd.window_object frame];
wd.extend_to_title = p_enabled;
if (p_enabled) {
[wd.window_object setTitlebarAppearsTransparent:YES];
[wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskFullSizeContentView];
Expand All @@ -3508,6 +3500,9 @@ - (void)popupAction:(id)sender {
send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE);
} break;
case WINDOW_FLAG_BORDERLESS: {
if (wd.fullscreen) {
return;
}
// OrderOut prevents a lose focus bug with the window.
bool was_visible = false;
if ([wd.window_object isVisible]) {
Expand All @@ -3518,8 +3513,11 @@ - (void)popupAction:(id)sender {
if (p_enabled) {
[wd.window_object setStyleMask:NSWindowStyleMaskBorderless];
} else {
_set_window_per_pixel_transparency_enabled(false, p_window);
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
if (wd.layered_window) {
wd.layered_window = false;
set_window_per_pixel_transparency_enabled(false, p_window);
}
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.extend_to_title ? NSWindowStyleMaskFullSizeContentView : 0) | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
// Force update of the window styles.
NSRect frameRect = [wd.window_object frame];
[wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
Expand Down Expand Up @@ -3548,12 +3546,20 @@ - (void)popupAction:(id)sender {
}
} break;
case WINDOW_FLAG_TRANSPARENT: {
if (wd.fullscreen) {
return;
}
if (p_enabled) {
[wd.window_object setStyleMask:NSWindowStyleMaskBorderless]; // Force borderless.
} else if (!wd.borderless) {
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.extend_to_title ? NSWindowStyleMaskFullSizeContentView : 0) | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
}
_set_window_per_pixel_transparency_enabled(p_enabled, p_window);
wd.layered_window = p_enabled;
set_window_per_pixel_transparency_enabled(p_enabled, p_window);
// Force update of the window styles.
NSRect frameRect = [wd.window_object frame];
[wd.window_object setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
[wd.window_object setFrame:frameRect display:NO];
} break;
case WINDOW_FLAG_NO_FOCUS: {
wd.no_focus = p_enabled;
Expand Down
19 changes: 16 additions & 3 deletions platform/macos/godot_window_delegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ - (void)windowWillEnterFullScreen:(NSNotification *)notification {

DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
wd.fs_transition = true;

// Temporary disable borderless and transparent state.
if ([wd.window_object styleMask] == NSWindowStyleMaskBorderless) {
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable];
}
if (wd.layered_window) {
ds->set_window_per_pixel_transparency_enabled(false, window_id);
}
}

- (void)windowDidFailToEnterFullScreen:(NSWindow *)window {
Expand Down Expand Up @@ -175,9 +183,14 @@ - (void)windowDidExitFullScreen:(NSNotification *)notification {
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}

// Restore resizability state.
if (wd.resize_disabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
// Restore borderless, transparent and resizability state.
if (wd.borderless || wd.layered_window) {
[wd.window_object setStyleMask:NSWindowStyleMaskBorderless];
} else {
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.extend_to_title ? NSWindowStyleMaskFullSizeContentView : 0) | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
}
if (wd.layered_window) {
ds->set_window_per_pixel_transparency_enabled(true, window_id);
}

// Restore on-top state.
Expand Down
Loading