Skip to content

Commit 7174bf4

Browse files
committed
Implement clear_vibrancy via removing the blurred view from the window; implement a NSVisualEffectView subview with tag for matching the blurred view in the window; add IntelliJ IDEA and macOS-specific files to gitignore
1 parent 44f5fea commit 7174bf4

7 files changed

+274
-150
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44

55
/target
66
Cargo.lock
7+
.idea/
8+
*.iml
9+
.DS_Store

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ For a more complete example of usage with [tauri](https://tauri.app/), see [`exa
3636

3737
## Available functions
3838

39-
| Function | Supported platforms | Notes |
40-
| :--- | :---: | :--- |
41-
| `apply_blur`&`clear_blur` | Windows 7/10/11 (22H1 only) | Bad performance when resizing/dragging the window on Windows 11 build 22621+. |
42-
| `apply_acrylic`&`clear_acrylic` | Windows 10/11 | Bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000. |
43-
| `apply_mica`&`clear_mica` | Windows 11 | |
44-
| `apply_vibrancy` | macOS 10.10 and newer | |
39+
| Function | Supported platforms | Notes |
40+
|:----------------------------------|:----------------------------:|:---------------------------------------------------------------------------------------------------|
41+
| `apply_blur`&`clear_blur` | Windows 7/10/11 (22H1 only) | Bad performance when resizing/dragging the window on Windows 11 build 22621+. |
42+
| `apply_acrylic`&`clear_acrylic` | Windows 10/11 | Bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000. |
43+
| `apply_mica`&`clear_mica` | Windows 11 | |
44+
| `apply_vibrancy`&`clear_vibrancy` | macOS 10.10 and newer | |
4545

4646
## Screenshots
4747

src/lib.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
mod macos;
2727
mod windows;
2828

29-
pub use macos::{NSVisualEffectMaterial, NSVisualEffectState};
29+
pub use macos::{NSVisualEffectMaterial, NSVisualEffectState, NSVisualEffectViewTagged};
3030

3131
/// a tuple of RGBA colors. Each value has minimum of 0 and maximum of 255.
3232
pub type Color = (u8, u8, u8, u8);
@@ -229,6 +229,28 @@ pub fn apply_vibrancy(
229229
}
230230
}
231231

232+
/// Clears vibrancy effect applied to window. Works only on macOS 10.10 or newer.
233+
///
234+
/// ## Platform-specific
235+
///
236+
/// - **Linux / Windows**: Unsupported.
237+
///
238+
/// # Returns
239+
///
240+
/// - `Ok(true)` if the vibrancy effect was cleared
241+
/// - `Ok(false)` if the vibrancy effect was not previously applied by this crate.
242+
pub fn clear_vibrancy(window: impl raw_window_handle::HasWindowHandle) -> Result<bool, Error> {
243+
match window.window_handle()?.as_raw() {
244+
#[cfg(target_os = "macos")]
245+
raw_window_handle::RawWindowHandle::AppKit(handle) => unsafe {
246+
macos::clear_vibrancy(handle.ns_view)
247+
},
248+
_ => Err(Error::UnsupportedPlatform(
249+
"\"clear_vibrancy()\" is only supported on macOS.",
250+
)),
251+
}
252+
}
253+
232254
#[derive(Debug)]
233255
pub enum Error {
234256
UnsupportedPlatform(&'static str),

src/macos.rs

-143
This file was deleted.

src/macos/internal.rs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#![cfg(target_os = "macos")]
2+
3+
use objc2_app_kit::{
4+
NSAppKitVersionNumber, NSAppKitVersionNumber10_10, NSAppKitVersionNumber10_11,
5+
NSAppKitVersionNumber10_14, NSAutoresizingMaskOptions, NSView, NSVisualEffectBlendingMode,
6+
NSVisualEffectMaterial, NSVisualEffectState, NSWindowOrderingMode,
7+
};
8+
use objc2_foundation::{MainThreadMarker, NSInteger};
9+
use std::{ffi::c_void, ptr::NonNull};
10+
11+
use crate::macos::NSVisualEffectViewTagged;
12+
use crate::Error;
13+
14+
/// NSView::tag for NSVisualEffectViewTagged, just a random number
15+
pub const NS_VIEW_TAG_BLUR_VIEW: NSInteger = 91376254;
16+
17+
#[allow(deprecated)]
18+
pub unsafe fn apply_vibrancy(
19+
ns_view: NonNull<c_void>,
20+
appearance: super::NSVisualEffectMaterial,
21+
state: Option<super::NSVisualEffectState>,
22+
radius: Option<f64>,
23+
) -> Result<(), Error> {
24+
let mtm = MainThreadMarker::new().ok_or(Error::NotMainThread(
25+
"\"apply_vibrancy()\" can only be used on the main thread.",
26+
))?;
27+
28+
unsafe {
29+
let view: &NSView = ns_view.cast().as_ref();
30+
31+
if NSAppKitVersionNumber < NSAppKitVersionNumber10_10 {
32+
return Err(Error::UnsupportedPlatformVersion(
33+
"\"apply_vibrancy()\" is only available on macOS 10.0 or newer.",
34+
));
35+
}
36+
37+
let mut m = NSVisualEffectMaterial(appearance as isize);
38+
if (appearance as u32 > 9 && NSAppKitVersionNumber < NSAppKitVersionNumber10_14)
39+
|| (appearance as u32 > 4 && NSAppKitVersionNumber < NSAppKitVersionNumber10_11)
40+
{
41+
m = NSVisualEffectMaterial::AppearanceBased;
42+
}
43+
44+
let bounds = view.bounds();
45+
let blurred_view =
46+
NSVisualEffectViewTagged::initWithFrame(mtm.alloc(), bounds, NS_VIEW_TAG_BLUR_VIEW);
47+
48+
blurred_view.setMaterial(m);
49+
blurred_view.setCornerRadius(radius.unwrap_or(0.0));
50+
blurred_view.setBlendingMode(NSVisualEffectBlendingMode::BehindWindow);
51+
blurred_view.setState(
52+
state
53+
.map(|state| NSVisualEffectState(state as isize))
54+
.unwrap_or(NSVisualEffectState::FollowsWindowActiveState),
55+
);
56+
blurred_view.setAutoresizingMask(
57+
NSAutoresizingMaskOptions::NSViewWidthSizable
58+
| NSAutoresizingMaskOptions::NSViewHeightSizable,
59+
);
60+
61+
view.addSubview_positioned_relativeTo(
62+
&blurred_view,
63+
NSWindowOrderingMode::NSWindowBelow,
64+
None,
65+
);
66+
}
67+
68+
Ok(())
69+
}
70+
71+
pub unsafe fn clear_vibrancy(ns_view: NonNull<c_void>) -> Result<bool, Error> {
72+
let view: &NSView = ns_view.cast().as_ref();
73+
let blurred_view = view.viewWithTag(NS_VIEW_TAG_BLUR_VIEW);
74+
75+
if let Some(blurred_view) = blurred_view {
76+
blurred_view.removeFromSuperview();
77+
return Ok(true);
78+
}
79+
80+
Ok(false)
81+
}

src/macos/mod.rs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2019-2022 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
// The use of NSVisualEffectView comes from https://github.com/joboet/winit/tree/macos_blurred_background
6+
// with a bit of rewrite by @youngsing to make it more like cocoa::appkit style.
7+
/// <https://developer.apple.com/documentation/appkit/nsvisualeffectview/material>
8+
#[repr(u64)]
9+
#[derive(Clone, Copy, Debug, PartialEq)]
10+
pub enum NSVisualEffectMaterial {
11+
#[deprecated(
12+
since = "macOS 10.14",
13+
note = "A default material appropriate for the view's effectiveAppearance. You should instead choose an appropriate semantic material."
14+
)]
15+
AppearanceBased = 0,
16+
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
17+
Light = 1,
18+
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
19+
Dark = 2,
20+
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
21+
MediumLight = 8,
22+
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
23+
UltraDark = 9,
24+
25+
/// macOS 10.10+
26+
Titlebar = 3,
27+
/// macOS 10.10+
28+
Selection = 4,
29+
30+
/// macOS 10.11+
31+
Menu = 5,
32+
/// macOS 10.11+
33+
Popover = 6,
34+
/// macOS 10.11+
35+
Sidebar = 7,
36+
37+
/// macOS 10.14+
38+
HeaderView = 10,
39+
/// macOS 10.14+
40+
Sheet = 11,
41+
/// macOS 10.14+
42+
WindowBackground = 12,
43+
/// macOS 10.14+
44+
HudWindow = 13,
45+
/// macOS 10.14+
46+
FullScreenUI = 15,
47+
/// macOS 10.14+
48+
Tooltip = 17,
49+
/// macOS 10.14+
50+
ContentBackground = 18,
51+
/// macOS 10.14+
52+
UnderWindowBackground = 21,
53+
/// macOS 10.14+
54+
UnderPageBackground = 22,
55+
}
56+
57+
/// <https://developer.apple.com/documentation/appkit/nsvisualeffectview/state>
58+
#[allow(dead_code)]
59+
#[repr(u64)]
60+
#[derive(Clone, Copy, Debug, PartialEq)]
61+
pub enum NSVisualEffectState {
62+
/// Make window vibrancy state follow the window's active state
63+
FollowsWindowActiveState = 0,
64+
/// Make window vibrancy state always active
65+
Active = 1,
66+
/// Make window vibrancy state always inactive
67+
Inactive = 2,
68+
}
69+
70+
#[cfg(target_os = "macos")]
71+
mod internal;
72+
73+
#[cfg(target_os = "macos")]
74+
pub use internal::apply_vibrancy;
75+
76+
#[cfg(target_os = "macos")]
77+
pub use internal::clear_vibrancy;
78+
79+
#[cfg(target_os = "macos")]
80+
mod ns_visual_effect_view_tagged;
81+
82+
#[cfg(target_os = "macos")]
83+
pub use ns_visual_effect_view_tagged::NSVisualEffectViewTagged;

0 commit comments

Comments
 (0)