floem_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::HasRawWindowHandle = 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/// a tuple of RGBA colors. Each value has minimum of 0 and maximum of 255.
32pub type Color = (u8, u8, u8, u8);
33
34/// Applies blur effect to window. Works only on Windows 7, Windows 10 v1809 or newer.
35///
36/// ## WARNING:
37///
38/// This method has poor performance on Windows 11 build 22621,
39/// the window will lag when resizing or dragging.
40/// It is an issue in the undocumented api used for this method
41/// and microsoft needs to fix it (they probably won't).
42///
43/// ## Platform-specific
44///
45/// - **Windows**: *`color`* is ignored on Windows 7 and has no effect.
46/// - **Linux / macOS**: Unsupported.
47pub fn apply_blur(
48    window: impl raw_window_handle::HasRawWindowHandle,
49    #[allow(unused)] color: Option<Color>,
50) -> Result<(), Error> {
51    match window.raw_window_handle() {
52        #[cfg(target_os = "windows")]
53        raw_window_handle::RawWindowHandle::Win32(handle) => {
54            windows::apply_blur(handle.hwnd as _, color)
55        }
56        _ => Err(Error::UnsupportedPlatform(
57            "\"apply_blur()\" is only supported on Windows.",
58        )),
59    }
60}
61
62/// Clears blur effect applied to window. Works only on Windows 7, Windows 10 v1809 or newer.
63///
64/// ## Platform-specific
65///
66/// - **Linux / macOS**: Unsupported.
67pub fn clear_blur(window: impl raw_window_handle::HasRawWindowHandle) -> Result<(), Error> {
68    match window.raw_window_handle() {
69        #[cfg(target_os = "windows")]
70        raw_window_handle::RawWindowHandle::Win32(handle) => windows::clear_blur(handle.hwnd as _),
71        _ => Err(Error::UnsupportedPlatform(
72            "\"clear_blur()\" is only supported on Windows.",
73        )),
74    }
75}
76
77/// Applies Acrylic effect to you window. Works only on Windows 10 v1809 or newer.
78///
79/// ## WARNING:
80///
81/// This method has poor performance on Windows 10 v1903+ and Windows 11 build 22000,
82/// the window will lag when resizing or dragging.
83/// It is an issue in the undocumented api used for this method
84/// and microsoft needs to fix it (they probably won't).
85///
86/// ## Platform-specific
87///
88/// - **Windows**: *`color`* is ignored on Windows 7 and has no effect.
89/// - **Linux / macOS**: Unsupported.
90pub fn apply_acrylic(
91    window: impl raw_window_handle::HasRawWindowHandle,
92    #[allow(unused)] color: Option<Color>,
93) -> Result<(), Error> {
94    match window.raw_window_handle() {
95        #[cfg(target_os = "windows")]
96        raw_window_handle::RawWindowHandle::Win32(handle) => {
97            windows::apply_acrylic(handle.hwnd as _, color)
98        }
99        _ => Err(Error::UnsupportedPlatform(
100            "\"apply_acrylic()\" is only supported on Windows.",
101        )),
102    }
103}
104
105/// Clears acrylic effect applied to window. Works only on Windows 10 v1809 or newer.
106///
107/// ## Platform-specific
108///
109/// - **Linux / macOS**: Unsupported.
110pub fn clear_acrylic(window: impl raw_window_handle::HasRawWindowHandle) -> Result<(), Error> {
111    match window.raw_window_handle() {
112        #[cfg(target_os = "windows")]
113        raw_window_handle::RawWindowHandle::Win32(handle) => {
114            windows::clear_acrylic(handle.hwnd as _)
115        }
116        _ => Err(Error::UnsupportedPlatform(
117            "\"clear_acrylic()\" is only supported on Windows.",
118        )),
119    }
120}
121
122/// Applies mica effect to window. Works only on Windows 11.
123///
124/// ## Arguments
125///
126/// - `dark`: If `None` is provide, it will match the system preference
127///
128/// ## Platform-specific
129///
130/// - **Linux / macOS**: Unsupported.
131pub fn apply_mica(
132    window: impl raw_window_handle::HasRawWindowHandle,
133    dark: Option<bool>,
134) -> Result<(), Error> {
135    #[cfg(not(target_os = "windows"))]
136    let _ = dark;
137    match window.raw_window_handle() {
138        #[cfg(target_os = "windows")]
139        raw_window_handle::RawWindowHandle::Win32(handle) => {
140            windows::apply_mica(handle.hwnd as _, dark)
141        }
142        _ => Err(Error::UnsupportedPlatform(
143            "\"apply_mica()\" is only supported on Windows.",
144        )),
145    }
146}
147
148/// Clears mica effect applied to window. Works only on Windows 11.
149///
150/// ## Platform-specific
151///
152/// - **Linux / macOS**: Unsupported.
153pub fn clear_mica(window: impl raw_window_handle::HasRawWindowHandle) -> Result<(), Error> {
154    match window.raw_window_handle() {
155        #[cfg(target_os = "windows")]
156        raw_window_handle::RawWindowHandle::Win32(handle) => windows::clear_mica(handle.hwnd as _),
157        _ => Err(Error::UnsupportedPlatform(
158            "\"clear_mica()\" is only supported on Windows.",
159        )),
160    }
161}
162
163/// Applies mica tabbed effect to window. Works only on Windows 11.
164///
165/// ## Arguments
166///
167/// - `dark`: If `None` is provide, it will match the system preference
168///
169/// ## Platform-specific
170///
171/// - **Linux / macOS**: Unsupported.
172pub fn apply_tabbed(
173    window: impl raw_window_handle::HasRawWindowHandle,
174    dark: Option<bool>,
175) -> Result<(), Error> {
176    #[cfg(not(target_os = "windows"))]
177    let _ = dark;
178    match window.raw_window_handle() {
179        #[cfg(target_os = "windows")]
180        raw_window_handle::RawWindowHandle::Win32(handle) => {
181            windows::apply_tabbed(handle.hwnd as _, dark)
182        }
183        _ => Err(Error::UnsupportedPlatform(
184            "\"apply_tabbed()\" is only supported on Windows.",
185        )),
186    }
187}
188
189/// Clears mica tabbed effect applied to window. Works only on Windows 11.
190///
191/// ## Platform-specific
192///
193/// - **Linux / macOS**: Unsupported.
194pub fn clear_tabbed(window: impl raw_window_handle::HasRawWindowHandle) -> Result<(), Error> {
195    match window.raw_window_handle() {
196        #[cfg(target_os = "windows")]
197        raw_window_handle::RawWindowHandle::Win32(handle) => {
198            windows::clear_tabbed(handle.hwnd as _)
199        }
200        _ => Err(Error::UnsupportedPlatform(
201            "\"clear_tabbed()\" is only supported on Windows.",
202        )),
203    }
204}
205
206/// Applies macos vibrancy effect to window. Works only on macOS 10.10 or newer.
207///
208/// ## Platform-specific
209///
210/// - **Linux / Windows**: Unsupported.
211pub fn apply_vibrancy(
212    window: impl raw_window_handle::HasRawWindowHandle,
213    #[allow(unused)] effect: NSVisualEffectMaterial,
214    #[allow(unused)] state: Option<NSVisualEffectState>,
215    #[allow(unused)] radius: Option<f64>,
216) -> Result<(), Error> {
217    match window.raw_window_handle() {
218        #[cfg(target_os = "macos")]
219        raw_window_handle::RawWindowHandle::AppKit(handle) => {
220            macos::apply_vibrancy(handle.ns_window as _, effect, state, radius)
221        }
222        _ => Err(Error::UnsupportedPlatform(
223            "\"apply_vibrancy()\" is only supported on macOS.",
224        )),
225    }
226}
227
228#[derive(Debug)]
229pub enum Error {
230    UnsupportedPlatform(&'static str),
231    UnsupportedPlatformVersion(&'static str),
232    NotMainThread(&'static str),
233}
234
235impl std::fmt::Display for Error {
236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237        match self {
238            Error::UnsupportedPlatform(e)
239            | Error::UnsupportedPlatformVersion(e)
240            | Error::NotMainThread(e) => {
241                write!(f, "{}", e)
242            }
243        }
244    }
245}
246
247impl std::error::Error for Error {}