Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: clear_vibrancy, NSVisualEffectViewTagged #169

Merged
merged 3 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@

/target
Cargo.lock
.idea/
*.iml
.DS_Store
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ For a more complete example of usage with [tauri](https://tauri.app/), see [`exa

## Available functions

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

## Screenshots

Expand Down
24 changes: 23 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
mod macos;
mod windows;

pub use macos::{NSVisualEffectMaterial, NSVisualEffectState};
pub use macos::{NSVisualEffectMaterial, NSVisualEffectState, NSVisualEffectViewTagged};

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

/// Clears vibrancy effect applied to window. Works only on macOS 10.10 or newer.
///
/// ## Platform-specific
///
/// - **Linux / Windows**: Unsupported.
///
/// # Returns
///
/// - `Ok(true)` if the vibrancy effect was cleared
/// - `Ok(false)` if the vibrancy effect was not previously applied by this crate.
pub fn clear_vibrancy(window: impl raw_window_handle::HasWindowHandle) -> Result<bool, Error> {
match window.window_handle()?.as_raw() {
#[cfg(target_os = "macos")]
raw_window_handle::RawWindowHandle::AppKit(handle) => unsafe {
macos::clear_vibrancy(handle.ns_view)
},
_ => Err(Error::UnsupportedPlatform(
"\"clear_vibrancy()\" is only supported on macOS.",
)),
}
}

#[derive(Debug)]
pub enum Error {
UnsupportedPlatform(&'static str),
Expand Down
143 changes: 0 additions & 143 deletions src/macos.rs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just moved from macos.rs to macos/mod.rs + macos/internal.rs + macos/ns_visual_effect_view_tagged.rs.
Public API contract of this crate is not affected

This file was deleted.

81 changes: 81 additions & 0 deletions src/macos/internal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#![cfg(target_os = "macos")]

use objc2_app_kit::{
NSAppKitVersionNumber, NSAppKitVersionNumber10_10, NSAppKitVersionNumber10_11,
NSAppKitVersionNumber10_14, NSAutoresizingMaskOptions, NSView, NSVisualEffectBlendingMode,
NSVisualEffectMaterial, NSVisualEffectState, NSWindowOrderingMode,
};
use objc2_foundation::{MainThreadMarker, NSInteger};
use std::{ffi::c_void, ptr::NonNull};

use crate::macos::NSVisualEffectViewTagged;
use crate::Error;

/// NSView::tag for NSVisualEffectViewTagged, just a random number
pub const NS_VIEW_TAG_BLUR_VIEW: NSInteger = 91376254;

#[allow(deprecated)]
pub unsafe fn apply_vibrancy(
ns_view: NonNull<c_void>,
appearance: super::NSVisualEffectMaterial,
state: Option<super::NSVisualEffectState>,
radius: Option<f64>,
) -> Result<(), Error> {
let mtm = MainThreadMarker::new().ok_or(Error::NotMainThread(
"\"apply_vibrancy()\" can only be used on the main thread.",
))?;

unsafe {
let view: &NSView = ns_view.cast().as_ref();

if NSAppKitVersionNumber < NSAppKitVersionNumber10_10 {
return Err(Error::UnsupportedPlatformVersion(
"\"apply_vibrancy()\" is only available on macOS 10.0 or newer.",
));
}

let mut m = NSVisualEffectMaterial(appearance as isize);
if (appearance as u32 > 9 && NSAppKitVersionNumber < NSAppKitVersionNumber10_14)
|| (appearance as u32 > 4 && NSAppKitVersionNumber < NSAppKitVersionNumber10_11)
{
m = NSVisualEffectMaterial::AppearanceBased;
}

let bounds = view.bounds();
let blurred_view =
NSVisualEffectViewTagged::initWithFrame(mtm.alloc(), bounds, NS_VIEW_TAG_BLUR_VIEW);

blurred_view.setMaterial(m);
blurred_view.setCornerRadius(radius.unwrap_or(0.0));
blurred_view.setBlendingMode(NSVisualEffectBlendingMode::BehindWindow);
blurred_view.setState(
state
.map(|state| NSVisualEffectState(state as isize))
.unwrap_or(NSVisualEffectState::FollowsWindowActiveState),
);
blurred_view.setAutoresizingMask(
NSAutoresizingMaskOptions::NSViewWidthSizable
| NSAutoresizingMaskOptions::NSViewHeightSizable,
);

view.addSubview_positioned_relativeTo(
&blurred_view,
NSWindowOrderingMode::NSWindowBelow,
None,
);
}

Ok(())
}

pub unsafe fn clear_vibrancy(ns_view: NonNull<c_void>) -> Result<bool, Error> {
let view: &NSView = ns_view.cast().as_ref();
let blurred_view = view.viewWithTag(NS_VIEW_TAG_BLUR_VIEW);

if let Some(blurred_view) = blurred_view {
blurred_view.removeFromSuperview();
return Ok(true);
}

Ok(false)
}
83 changes: 83 additions & 0 deletions src/macos/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2019-2022 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT

// The use of NSVisualEffectView comes from https://github.com/joboet/winit/tree/macos_blurred_background
// with a bit of rewrite by @youngsing to make it more like cocoa::appkit style.
/// <https://developer.apple.com/documentation/appkit/nsvisualeffectview/material>
#[repr(u64)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum NSVisualEffectMaterial {
#[deprecated(
since = "macOS 10.14",
note = "A default material appropriate for the view's effectiveAppearance. You should instead choose an appropriate semantic material."
)]
AppearanceBased = 0,
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
Light = 1,
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
Dark = 2,
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
MediumLight = 8,
#[deprecated(since = "macOS 10.14", note = "Use a semantic material instead.")]
UltraDark = 9,

/// macOS 10.10+
Titlebar = 3,
/// macOS 10.10+
Selection = 4,

/// macOS 10.11+
Menu = 5,
/// macOS 10.11+
Popover = 6,
/// macOS 10.11+
Sidebar = 7,

/// macOS 10.14+
HeaderView = 10,
/// macOS 10.14+
Sheet = 11,
/// macOS 10.14+
WindowBackground = 12,
/// macOS 10.14+
HudWindow = 13,
/// macOS 10.14+
FullScreenUI = 15,
/// macOS 10.14+
Tooltip = 17,
/// macOS 10.14+
ContentBackground = 18,
/// macOS 10.14+
UnderWindowBackground = 21,
/// macOS 10.14+
UnderPageBackground = 22,
}

/// <https://developer.apple.com/documentation/appkit/nsvisualeffectview/state>
#[allow(dead_code)]
#[repr(u64)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum NSVisualEffectState {
/// Make window vibrancy state follow the window's active state
FollowsWindowActiveState = 0,
/// Make window vibrancy state always active
Active = 1,
/// Make window vibrancy state always inactive
Inactive = 2,
}

#[cfg(target_os = "macos")]
mod internal;

#[cfg(target_os = "macos")]
pub use internal::apply_vibrancy;

#[cfg(target_os = "macos")]
pub use internal::clear_vibrancy;

#[cfg(target_os = "macos")]
mod ns_visual_effect_view_tagged;

#[cfg(target_os = "macos")]
pub use ns_visual_effect_view_tagged::NSVisualEffectViewTagged;
Loading
Loading