window_vibrancy/
lib.rs

1// Copyright 2019-2022 Tauri Programme within The Commons Conservancy
2// SPDX-License-Identifier: Apache-2.0
3// SPDX-License-Identifier: MIT
4
5//! Make your windows vibrant.
6//!
7//! ## Platform-specific
8//!
9//! - **Linux**: Unsupported, Blur and any vibrancy effects are controlled by the compositor installed on the end-user system.
10//!
11//! # Example
12//!
13//! ```no_run
14//! use window_vibrancy::{apply_vibrancy, apply_blur, NSVisualEffectMaterial};
15//!
16//! # let window: &dyn raw_window_handle::HasWindowHandle = unsafe { std::mem::zeroed() };
17//! #[cfg(target_os = "macos")]
18//! apply_vibrancy(&window, NSVisualEffectMaterial::AppearanceBased, None, None).expect("Unsupported platform! 'apply_vibrancy' is only supported on macOS");
19//!
20//! #[cfg(target_os = "windows")]
21//! apply_blur(&window, Some((18, 18, 18, 125))).expect("Unsupported platform! 'apply_blur' is only supported on Windows");
22//! ```
23
24#![allow(clippy::deprecated_semver)]
25
26mod macos;
27mod windows;
28
29pub use macos::{NSVisualEffectMaterial, NSVisualEffectState};
30
31#[cfg(target_os = "macos")]
32pub use macos::NSVisualEffectViewTagged;
33
34/// a tuple of RGBA colors. Each value has minimum of 0 and maximum of 255.
35pub type Color = (u8, u8, u8, u8);
36
37/// Applies blur effect to window. Works only on Windows 7, Windows 10 v1809 or newer.
38///
39/// ## WARNING:
40///
41/// This method has poor performance on Windows 11 build 22621,
42/// the window will lag when resizing or dragging.
43/// It is an issue in the undocumented api used for this method
44/// and microsoft needs to fix it (they probably won't).
45///
46/// ## Platform-specific
47///
48/// - **Windows**: *`color`* is ignored on Windows 7 and has no effect.
49/// - **Linux / macOS**: Unsupported.
50pub fn apply_blur(
51    window: impl raw_window_handle::HasWindowHandle,
52    #[allow(unused)] color: Option<Color>,
53) -> Result<(), Error> {
54    match window.window_handle()?.as_raw() {
55        #[cfg(target_os = "windows")]
56        raw_window_handle::RawWindowHandle::Win32(handle) => {
57            windows::apply_blur(handle.hwnd.get() as _, color)
58        }
59        _ => Err(Error::UnsupportedPlatform(
60            "\"apply_blur()\" is only supported on Windows.",
61        )),
62    }
63}
64
65/// Clears blur effect applied to window. Works only on Windows 7, Windows 10 v1809 or newer.
66///
67/// ## Platform-specific
68///
69/// - **Linux / macOS**: Unsupported.
70pub fn clear_blur(window: impl raw_window_handle::HasWindowHandle) -> Result<(), Error> {
71    match window.window_handle()?.as_raw() {
72        #[cfg(target_os = "windows")]
73        raw_window_handle::RawWindowHandle::Win32(handle) => {
74            windows::clear_blur(handle.hwnd.get() as _)
75        }
76        _ => Err(Error::UnsupportedPlatform(
77            "\"clear_blur()\" is only supported on Windows.",
78        )),
79    }
80}
81
82/// Applies acrylic effect to window. Works only on Windows 10 v1809 or newer.
83///
84/// ## WARNING:
85///
86/// This method has poor performance on Windows 10 v1903+ and Windows 11 build 22000,
87/// the window will lag when resizing or dragging.
88/// It is an issue in the undocumented api used for this method
89/// and microsoft needs to fix it (they probably won't).
90///
91/// ## Platform-specific
92///
93/// - **Windows**: *`color`* is ignored on Windows 7 and has no effect.
94/// - **Linux / macOS**: Unsupported.
95pub fn apply_acrylic(
96    window: impl raw_window_handle::HasWindowHandle,
97    #[allow(unused)] color: Option<Color>,
98) -> Result<(), Error> {
99    match window.window_handle()?.as_raw() {
100        #[cfg(target_os = "windows")]
101        raw_window_handle::RawWindowHandle::Win32(handle) => {
102            windows::apply_acrylic(handle.hwnd.get() as _, color)
103        }
104        _ => Err(Error::UnsupportedPlatform(
105            "\"apply_acrylic()\" is only supported on Windows.",
106        )),
107    }
108}
109
110/// Clears acrylic effect applied to window. Works only on Windows 10 v1809 or newer.
111///
112/// ## Platform-specific
113///
114/// - **Linux / macOS**: Unsupported.
115pub fn clear_acrylic(window: impl raw_window_handle::HasWindowHandle) -> Result<(), Error> {
116    match window.window_handle()?.as_raw() {
117        #[cfg(target_os = "windows")]
118        raw_window_handle::RawWindowHandle::Win32(handle) => {
119            windows::clear_acrylic(handle.hwnd.get() as _)
120        }
121        _ => Err(Error::UnsupportedPlatform(
122            "\"clear_acrylic()\" is only supported on Windows.",
123        )),
124    }
125}
126
127/// Applies mica effect to window. Works only on Windows 11.
128///
129/// ## Arguments
130///
131/// - `dark`: If `None` is provide, it will match the system preference
132///
133/// ## Platform-specific
134///
135/// - **Linux / macOS**: Unsupported.
136pub fn apply_mica(
137    window: impl raw_window_handle::HasWindowHandle,
138    dark: Option<bool>,
139) -> Result<(), Error> {
140    #[cfg(not(target_os = "windows"))]
141    let _ = dark;
142    match window.window_handle()?.as_raw() {
143        #[cfg(target_os = "windows")]
144        raw_window_handle::RawWindowHandle::Win32(handle) => {
145            windows::apply_mica(handle.hwnd.get() as _, dark)
146        }
147        _ => Err(Error::UnsupportedPlatform(
148            "\"apply_mica()\" is only supported on Windows.",
149        )),
150    }
151}
152
153/// Clears mica effect applied to window. Works only on Windows 11.
154///
155/// ## Platform-specific
156///
157/// - **Linux / macOS**: Unsupported.
158pub fn clear_mica(window: impl raw_window_handle::HasWindowHandle) -> Result<(), Error> {
159    match window.window_handle()?.as_raw() {
160        #[cfg(target_os = "windows")]
161        raw_window_handle::RawWindowHandle::Win32(handle) => {
162            windows::clear_mica(handle.hwnd.get() as _)
163        }
164        _ => Err(Error::UnsupportedPlatform(
165            "\"clear_mica()\" is only supported on Windows.",
166        )),
167    }
168}
169
170/// Applies mica tabbed effect to window. Works only on Windows 11.
171///
172/// ## Arguments
173///
174/// - `dark`: If `None` is provide, it will match the system preference
175///
176/// ## Platform-specific
177///
178/// - **Linux / macOS**: Unsupported.
179pub fn apply_tabbed(
180    window: impl raw_window_handle::HasWindowHandle,
181    dark: Option<bool>,
182) -> Result<(), Error> {
183    #[cfg(not(target_os = "windows"))]
184    let _ = dark;
185    match window.window_handle()?.as_raw() {
186        #[cfg(target_os = "windows")]
187        raw_window_handle::RawWindowHandle::Win32(handle) => {
188            windows::apply_tabbed(handle.hwnd.get() as _, dark)
189        }
190        _ => Err(Error::UnsupportedPlatform(
191            "\"apply_tabbed()\" is only supported on Windows.",
192        )),
193    }
194}
195
196/// Clears mica tabbed effect applied to window. Works only on Windows 11.
197///
198/// ## Platform-specific
199///
200/// - **Linux / macOS**: Unsupported.
201pub fn clear_tabbed(window: impl raw_window_handle::HasWindowHandle) -> Result<(), Error> {
202    match window.window_handle()?.as_raw() {
203        #[cfg(target_os = "windows")]
204        raw_window_handle::RawWindowHandle::Win32(handle) => {
205            windows::clear_tabbed(handle.hwnd.get() as _)
206        }
207        _ => Err(Error::UnsupportedPlatform(
208            "\"clear_tabbed()\" is only supported on Windows.",
209        )),
210    }
211}
212
213/// Applies macos vibrancy effect to window. Works only on macOS 10.10 or newer.
214///
215/// ## Platform-specific
216///
217/// - **Linux / Windows**: Unsupported.
218pub fn apply_vibrancy(
219    window: impl raw_window_handle::HasWindowHandle,
220    #[allow(unused)] effect: NSVisualEffectMaterial,
221    #[allow(unused)] state: Option<NSVisualEffectState>,
222    #[allow(unused)] radius: Option<f64>,
223) -> Result<(), Error> {
224    match window.window_handle()?.as_raw() {
225        #[cfg(target_os = "macos")]
226        raw_window_handle::RawWindowHandle::AppKit(handle) => unsafe {
227            macos::apply_vibrancy(handle.ns_view, effect, state, radius)
228        },
229        _ => Err(Error::UnsupportedPlatform(
230            "\"apply_vibrancy()\" is only supported on macOS.",
231        )),
232    }
233}
234
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.
245pub 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
257#[derive(Debug)]
258pub enum Error {
259    UnsupportedPlatform(&'static str),
260    UnsupportedPlatformVersion(&'static str),
261    NotMainThread(&'static str),
262    NoWindowHandle(raw_window_handle::HandleError),
263}
264
265impl std::fmt::Display for Error {
266    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267        match self {
268            Error::UnsupportedPlatform(e)
269            | Error::UnsupportedPlatformVersion(e)
270            | Error::NotMainThread(e) => {
271                write!(f, "{}", e)
272            }
273            Error::NoWindowHandle(e) => {
274                write!(f, "{}", e)
275            }
276        }
277    }
278}
279
280impl std::error::Error for Error {}
281
282impl From<raw_window_handle::HandleError> for Error {
283    fn from(err: raw_window_handle::HandleError) -> Self {
284        Error::NoWindowHandle(err)
285    }
286}