Skip to main content

winio_ui_windows_common/
backdrop.rs

1#![warn(missing_docs)]
2
3use windows::core::{Error, HRESULT};
4use windows_sys::Win32::{
5    Foundation::HWND,
6    Graphics::Dwm::{
7        DWMSBT_AUTO, DWMSBT_MAINWINDOW, DWMSBT_TABBEDWINDOW, DWMSBT_TRANSIENTWINDOW,
8        DWMWA_SYSTEMBACKDROP_TYPE, DwmGetWindowAttribute, DwmSetWindowAttribute,
9    },
10};
11
12use crate::{Result, get_nt_build};
13
14/// Backdrop effects for windows.
15#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
16#[non_exhaustive]
17pub enum Backdrop {
18    /// Default window style.
19    None,
20    /// Acrylic effect.
21    Acrylic,
22    /// Mica effect.
23    Mica,
24    /// Mica Alt effect.
25    MicaAlt,
26}
27
28/// Get the current backdrop effect of a window.
29/// # Safety
30/// The caller must ensure that `handle` is a valid window handle.
31pub unsafe fn get_backdrop(handle: HWND) -> Result<Backdrop> {
32    if get_nt_build() < 22621 {
33        return Ok(Backdrop::None);
34    }
35    let mut style = 0;
36    let res = unsafe {
37        DwmGetWindowAttribute(
38            handle,
39            DWMWA_SYSTEMBACKDROP_TYPE as _,
40            &mut style as *mut _ as _,
41            4,
42        )
43    };
44    if res < 0 {
45        return Err(Error::from_hresult(HRESULT(res)));
46    }
47    let style = match style {
48        DWMSBT_TRANSIENTWINDOW => Backdrop::Acrylic,
49        DWMSBT_MAINWINDOW => Backdrop::Mica,
50        DWMSBT_TABBEDWINDOW => Backdrop::MicaAlt,
51        _ => Backdrop::None,
52    };
53    Ok(style)
54}
55
56/// Set the backdrop effect of a window.
57/// # Safety
58/// The caller must ensure that `handle` is a valid window handle.
59pub unsafe fn set_backdrop(handle: HWND, backdrop: Backdrop) -> Result<bool> {
60    if get_nt_build() < 22621 {
61        return Ok(false);
62    }
63    let style = match backdrop {
64        Backdrop::Acrylic => DWMSBT_TRANSIENTWINDOW,
65        Backdrop::Mica => DWMSBT_MAINWINDOW,
66        Backdrop::MicaAlt => DWMSBT_TABBEDWINDOW,
67        _ => DWMSBT_AUTO,
68    };
69    let res = unsafe {
70        DwmSetWindowAttribute(
71            handle,
72            DWMWA_SYSTEMBACKDROP_TYPE as _,
73            &style as *const _ as _,
74            4,
75        )
76    };
77    if res >= 0 {
78        Ok(style > 0)
79    } else {
80        Err(Error::from_hresult(HRESULT(res)))
81    }
82}