Files
searchi/apps/desktop/src-tauri/src/appearance.rs
T

129 lines
4.5 KiB
Rust

//! Native materials are applied on the UI thread. Unsupported systems stay
//! opaque; stored preferences are retained for the user's next supported session.
use crate::settings::BackgroundMaterial;
use serde::Serialize;
use tauri::WebviewWindow;
#[derive(Clone, Debug, Serialize)]
pub struct AppearanceStatus {
pub requested_material: BackgroundMaterial,
pub effective_material: BackgroundMaterial,
pub opacity: u8,
pub native_effect: bool,
pub fallback_reason: Option<String>,
}
pub fn apply(
window: &WebviewWindow,
material: BackgroundMaterial,
opacity: u8,
high_contrast: bool,
) -> AppearanceStatus {
let mut status = AppearanceStatus {
requested_material: material,
effective_material: BackgroundMaterial::Solid,
opacity,
native_effect: false,
fallback_reason: None,
};
if high_contrast || material == BackgroundMaterial::Solid || opacity == 100 {
#[cfg(windows)]
{
let _ = window_vibrancy::clear_acrylic(window);
}
if high_contrast {
status.fallback_reason = Some("High contrast uses an opaque background.".into());
}
return status;
}
#[cfg(windows)]
{
if !native_backdrop_available() {
status.fallback_reason = Some("Glass requires Windows 11 22H2 or newer with desktop composition enabled and high contrast off. Using a solid background.".into());
return status;
}
let _ = window_vibrancy::clear_acrylic(window);
// Keep the webview clear; the frontend draws a theme-aware readable tint.
let result = window
.set_background_color(Some(tauri::window::Color(0, 0, 0, 0)))
.map_err(|error| error.to_string())
.and_then(|()| {
match material {
BackgroundMaterial::Glass => {
window_vibrancy::apply_acrylic(window, Some((0, 0, 0, 0)))
}
BackgroundMaterial::Frosted => {
window_vibrancy::apply_acrylic(window, Some((0, 0, 0, 0)))
}
BackgroundMaterial::Solid => unreachable!(),
}
.map_err(|error| error.to_string())
});
match result {
Ok(()) => {
status.effective_material = material;
status.native_effect = true;
}
Err(_) => {
status.fallback_reason =
Some("Native transparency is unavailable. Using a solid background.".into());
}
}
}
#[cfg(not(windows))]
{
let _ = window;
status.fallback_reason = Some(
if cfg!(target_os = "macos") {
"Native glass is unavailable in this macOS build. Using a solid background."
} else {
"Native glass is unavailable on this desktop. Using a solid background."
}
.into(),
);
}
status
}
#[cfg(windows)]
fn native_backdrop_available() -> bool {
use windows_sys::Win32::UI::Accessibility::{HCF_HIGHCONTRASTON, HIGHCONTRASTW};
use windows_sys::Win32::{
Graphics::Dwm::DwmIsCompositionEnabled,
UI::WindowsAndMessaging::{SystemParametersInfoW, SPI_GETHIGHCONTRAST},
};
let mut composition = 0;
let mut contrast = HIGHCONTRASTW {
cbSize: std::mem::size_of::<HIGHCONTRASTW>() as u32,
dwFlags: 0,
lpszDefaultScheme: std::ptr::null_mut(),
};
// Failure to query accessibility/composition is treated conservatively.
unsafe {
if DwmIsCompositionEnabled(&mut composition) < 0
|| composition == 0
|| SystemParametersInfoW(
SPI_GETHIGHCONTRAST,
contrast.cbSize,
&mut contrast as *mut _ as *mut _,
0,
) == 0
|| contrast.dwFlags & HCF_HIGHCONTRASTON != 0
{
return false;
}
}
// The established crate checks the HRESULT of the public backdrop API on
// Windows 11 22H2+. Its older undocumented path cannot confirm success.
let mut version = windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW {
dwOSVersionInfoSize: std::mem::size_of::<
windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW,
>() as u32,
..unsafe { std::mem::zeroed() }
};
unsafe {
windows_sys::Wdk::System::SystemServices::RtlGetVersion(&mut version) >= 0
&& version.dwBuildNumber >= 22621
}
}