diff --git a/CHANGELOG.md b/CHANGELOG.md index 282a4f2d6e8..bf1bdcd1a6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Unreleased` header. - On Wayland, use `configure_bounds` to constrain `with_inner_size` when compositor wants users to pick size. - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. - On macOS, fix deadlock when entering a nested event loop from an event handler. +- On macOS, add support for `Window::set_blur`. # 0.29.2 diff --git a/src/platform_impl/macos/appkit/window.rs b/src/platform_impl/macos/appkit/window.rs index 74b2bf3b3ef..5f5d8f179f3 100644 --- a/src/platform_impl/macos/appkit/window.rs +++ b/src/platform_impl/macos/appkit/window.rs @@ -36,6 +36,9 @@ extern_methods!( #[method(frame)] pub(crate) fn frame(&self) -> NSRect; + #[method(windowNumber)] + pub(crate) fn windowNumber(&self) -> NSInteger; + #[method(backingScaleFactor)] pub(crate) fn backingScaleFactor(&self) -> CGFloat; diff --git a/src/platform_impl/macos/ffi.rs b/src/platform_impl/macos/ffi.rs index 05397facf0b..e6115166fbf 100644 --- a/src/platform_impl/macos/ffi.rs +++ b/src/platform_impl/macos/ffi.rs @@ -2,6 +2,7 @@ #![allow(dead_code, non_snake_case, non_upper_case_globals)] +use objc2::{ffi::NSInteger, runtime::AnyObject}; use std::ffi::c_void; use core_foundation::{ @@ -113,6 +114,14 @@ extern "C" { pub fn CGDisplayModeCopyPixelEncoding(mode: CGDisplayModeRef) -> CFStringRef; pub fn CGDisplayModeRetain(mode: CGDisplayModeRef); pub fn CGDisplayModeRelease(mode: CGDisplayModeRef); + + // Wildly used private APIs, even Apple uses them for their Terminal.app. + pub fn CGSMainConnectionID() -> *mut AnyObject; + pub fn CGSSetWindowBackgroundBlurRadius( + connection_id: *mut AnyObject, + window_id: NSInteger, + radius: i64, + ) -> i32; } mod core_video { diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index 0096a6bd06b..7e7d6f383ef 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -46,6 +46,8 @@ use super::appkit::{ NSView, NSWindow, NSWindowButton, NSWindowLevel, NSWindowSharingType, NSWindowStyleMask, NSWindowTabbingMode, NSWindowTitleVisibility, }; +use super::ffi::CGSMainConnectionID; +use super::ffi::CGSSetWindowBackgroundBlurRadius; pub(crate) struct Window { window: MainThreadBound>, @@ -494,6 +496,10 @@ impl WinitWindow { this.setBackgroundColor(&NSColor::clear()); } + if attrs.blur { + this.set_blur(attrs.blur); + } + if let Some(dim) = attrs.min_inner_size { this.set_min_inner_size(Some(dim)); } @@ -582,7 +588,15 @@ impl WinitWindow { self.setOpaque(!transparent) } - pub fn set_blur(&self, _blur: bool) {} + pub fn set_blur(&self, blur: bool) { + // NOTE: in general we want to specify the blur radius, but the choice of 80 + // should be a reasonable default. + let radius = if blur { 80 } else { 0 }; + let window_number = self.windowNumber(); + unsafe { + CGSSetWindowBackgroundBlurRadius(CGSMainConnectionID(), window_number, radius); + } + } pub fn set_visible(&self, visible: bool) { match visible { diff --git a/src/window.rs b/src/window.rs index 3352abbadd4..83e698af8f5 100644 --- a/src/window.rs +++ b/src/window.rs @@ -918,7 +918,7 @@ impl Window { /// /// ## Platform-specific /// - /// - **Android / iOS / macOS / X11 / Web / Windows:** Unsupported. + /// - **Android / iOS / X11 / Web / Windows:** Unsupported. /// - **Wayland:** Only works with org_kde_kwin_blur_manager protocol. #[inline] pub fn set_blur(&self, blur: bool) {