From 92b7dcccc14492cb0fb9870b70eb4bd34866c39a Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 28 Oct 2023 14:22:10 +0400 Subject: [PATCH] On macOS, add support for `Window::set_blur` --- CHANGELOG.md | 1 + src/platform_impl/macos/appkit/window.rs | 3 +++ src/platform_impl/macos/ffi.rs | 9 +++++++++ src/platform_impl/macos/window.rs | 16 +++++++++++++++- src/window.rs | 2 +- 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20eaef64..3ec858b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Unreleased` header. - On Windows, fix deadlock when accessing the state during `Cursor{Enter,Leave}`. - On Windows, add support for `Window::set_transparent`. - 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 74b2bf3b..5f5d8f17 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 05397fac..5396d325 100644 --- a/src/platform_impl/macos/ffi.rs +++ b/src/platform_impl/macos/ffi.rs @@ -11,6 +11,7 @@ use core_graphics::{ base::CGError, display::{CGDirectDisplayID, CGDisplayConfigRef}, }; +use objc2::{ffi::NSInteger, runtime::AnyObject}; pub type CGDisplayFadeInterval = f32; pub type CGDisplayReservationInterval = f32; @@ -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; 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 0096a6bd..7e7d6f38 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 3a00fd2b..e3950c34 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) {