Skip to content

Commit 953f69a

Browse files
feat: clear_vibrancy (#169)
1 parent 44f5fea commit 953f69a

8 files changed

+313
-149
lines changed

.changes/clear-vibrancy.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"window-vibrancy": "patch:enhance"
3+
---
4+
5+
Add `clear_vibrancy` function on macOS.

.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

+25
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ mod windows;
2828

2929
pub use macos::{NSVisualEffectMaterial, NSVisualEffectState};
3030

31+
#[cfg(target_os = "macos")]
32+
pub use macos::NSVisualEffectViewTagged;
33+
3134
/// a tuple of RGBA colors. Each value has minimum of 0 and maximum of 255.
3235
pub type Color = (u8, u8, u8, u8);
3336

@@ -229,6 +232,28 @@ pub fn apply_vibrancy(
229232
}
230233
}
231234

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

src/macos.rs

-143
This file was deleted.

src/macos/internal.rs

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

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)