diff --git a/Cargo.toml b/Cargo.toml index e38d46e29a..dcbe781f6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -142,6 +142,7 @@ features = [ "NSApplication", "NSBitmapImageRep", "NSButton", + "NSColor", "NSControl", "NSCursor", "NSDragging", diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 882a11ef47..1e3675f1ca 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -10,7 +10,7 @@ use objc2::runtime::{AnyObject, ProtocolObject}; use objc2::{declare_class, msg_send_id, mutability, sel, ClassType, DeclaredClass}; use objc2_app_kit::{ NSAppKitVersionNumber, NSAppKitVersionNumber10_12, NSAppearance, NSApplication, - NSApplicationPresentationOptions, NSBackingStoreType, NSDraggingDestination, + NSApplicationPresentationOptions, NSBackingStoreType, NSColor, NSDraggingDestination, NSFilenamesPboardType, NSPasteboard, NSRequestUserAttentionType, NSScreen, NSView, NSWindowButton, NSWindowDelegate, NSWindowFullScreenButton, NSWindowLevel, NSWindowOcclusionState, NSWindowOrderingMode, NSWindowSharingType, NSWindowStyleMask, @@ -613,6 +613,8 @@ fn new_window( if attrs.transparent { window.setOpaque(false); + // See `set_transparent` for details on why we do this. + window.setBackgroundColor(unsafe { Some(&NSColor::clearColor()) }); } // register for drag and drop operations. @@ -821,7 +823,23 @@ impl WindowDelegate { } pub fn set_transparent(&self, transparent: bool) { - self.window().setOpaque(!transparent) + // This is just a hint for Quartz, it doesn't actually speculate with window alpha. + // Providing a wrong value here could result in visual artifacts, when the window is + // transparent. + self.window().setOpaque(!transparent); + + // AppKit draws the window with a background color by default, which is usually really + // nice, but gets in the way when we want to allow the contents of the window to be + // transparent, as in that case, the transparent contents will just be drawn on top of + // the background color. As such, to allow the window to be transparent, we must also set + // the background color to one with an empty alpha channel. + let color = if transparent { + unsafe { NSColor::clearColor() } + } else { + unsafe { NSColor::windowBackgroundColor() } + }; + + self.window().setBackgroundColor(Some(&color)); } pub fn set_blur(&self, blur: bool) { diff --git a/src/window.rs b/src/window.rs index f443a71db4..76fa34e405 100644 --- a/src/window.rs +++ b/src/window.rs @@ -942,8 +942,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **macOS:** If you're not drawing to the window yourself, you might have to set the - /// background color of the window to enable transparency. + /// - **macOS:** This will reset the window's background color. /// - **Web / iOS / Android:** Unsupported. /// - **X11:** Can only be set while building the window, with /// [`WindowAttributes::with_transparent`].