Skip to content

Commit

Permalink
macOS: fix opacity handling
Browse files Browse the repository at this point in the history
Not using `NSColor::clearColor()` results in Quartz thinking that the
window is not transparent at all, which results in artifacts.

However, not setting the `windowBackgroundColor` in
`Window::set_transparent` results in border not properly rendered.

Fixes: 94664ff (Don't set the background color)
  • Loading branch information
kchibisov committed Jun 15, 2024
1 parent 96388f4 commit b512ed1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ features = [
"NSApplication",
"NSBitmapImageRep",
"NSButton",
"NSColor",
"NSControl",
"NSCursor",
"NSDragging",
Expand Down
22 changes: 20 additions & 2 deletions src/platform_impl/macos/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
Expand Down

0 comments on commit b512ed1

Please sign in to comment.