Skip to content

Commit

Permalink
fix: Redo config for window vibrancy
Browse files Browse the repository at this point in the history
  • Loading branch information
veryard committed Nov 5, 2024
1 parent 33d2124 commit a8715ab
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 57 deletions.
10 changes: 0 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions packages/desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
netdev = "0.24"
regex = "1"
window-vibrancy = "0.5.2"
csscolorparser = "0.7.0"
window-vibrancy = "0.5"

[target.'cfg(target_os = "windows")'.dependencies]
komorebi-client = { git = "https://github.com/LGUG2Z/komorebi", tag = "v0.1.28" }
Expand Down
2 changes: 2 additions & 0 deletions packages/desktop/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod format_bytes;
mod fs_util;
mod length_value;
mod parse_rgba;
mod path_ext;
mod window_ext;

pub use format_bytes::*;
pub use fs_util::*;
pub use length_value::*;
pub use parse_rgba::*;
pub use path_ext::*;
pub use window_ext::*;
79 changes: 79 additions & 0 deletions packages/desktop/src/common/parse_rgba.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#[derive(Debug)]
pub enum ColorError {
InvalidFormat,
InvalidValue,
}

pub fn parse_rgba(
color_str: &str,
) -> Result<(u8, u8, u8, u8), ColorError> {
let content = color_str
.trim_start_matches("rgba(")
.trim_end_matches(")")
.trim();

let parts: Vec<&str> = content.split(',').map(|s| s.trim()).collect();

if parts.len() != 4 {
return Err(ColorError::InvalidFormat);
}

let r = parts[0].parse().map_err(|_| ColorError::InvalidValue)?;
let g = parts[1].parse().map_err(|_| ColorError::InvalidValue)?;
let b = parts[2].parse().map_err(|_| ColorError::InvalidValue)?;

let a = if parts[3].ends_with('%') {
let percent = parts[3]
.trim_end_matches('%')
.parse::<f32>()
.map_err(|_| ColorError::InvalidValue)?;
if percent < 0.0 || percent > 100.0 {
return Err(ColorError::InvalidValue);
}
(percent / 100.0 * 255.0) as u8
} else {
let alpha = parts[3]
.parse::<f32>()
.map_err(|_| ColorError::InvalidValue)?;
if alpha < 0.0 || alpha > 1.0 {
return Err(ColorError::InvalidValue);
}
(alpha * 255.0) as u8
};

Ok((r, g, b, a))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_parse_rgba() {
// Test valid inputs
assert_eq!(
parse_rgba("rgba(255, 0, 0, 1.0)").unwrap(),
(255, 0, 0, 255)
);
assert_eq!(
parse_rgba("rgba(255, 0, 0, 0.5)").unwrap(),
(255, 0, 0, 127)
);
assert_eq!(
parse_rgba("rgba(255, 0, 0, 100%)").unwrap(),
(255, 0, 0, 255)
);
assert_eq!(
parse_rgba("rgba(255, 0, 0, 50%)").unwrap(),
(255, 0, 0, 127)
);

// Test invalid inputs
assert!(parse_rgba("rgb(255, 0, 0)").is_err());
assert!(parse_rgba("rgba(300, 0, 0, 1.0)").is_err());
assert!(parse_rgba("rgba(255, 0, 0, 1.5)").is_err());
assert!(parse_rgba("rgba(255, 0, 0, 101%)").is_err());
assert!(parse_rgba("rgba(255, 0, 0)").is_err());
assert!(parse_rgba("rgba(255, 0, 0, invalid)").is_err());
}
}
51 changes: 37 additions & 14 deletions packages/desktop/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,6 @@ pub struct WidgetConfig {
/// Whether the window frame should have an effect
pub background_effect: Option<BackgroundEffect>,

// Background effect color (Windows 10 v1903+, no effect on Windows 7 or Windows 11)
pub background_effect_color: Option<String>,

// Background Dark on Mica (Windows only)
pub background_effect_mica_dark: Option<bool>,

/// Where to place the widget. Add alias for `defaultPlacements` for
/// compatibility with v2.3.0 and earlier.
#[serde(alias = "defaultPlacements")]
Expand Down Expand Up @@ -170,15 +164,44 @@ pub enum MonitorSelection {
Name(String),
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, ValueEnum)]
#[clap(rename_all = "snake_case")]
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub struct BackgroundEffect {
pub windows: Option<WindowsBackgroundEffect>,
pub mac_os: Option<MacOsBackgroundEffect>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum BackgroundEffect {
None,
Blur, // For Windows
Acrylic, // For Windows
Mica, // For Windows
Vibrancy // For macOS; the string represents the material
pub enum WindowsBackgroundEffect {
Blur { color: String },
Acrylic { color: String },
Mica { prefer_dark: bool },
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum MacOsBackgroundEffect {
Vibrancy { material: VibrancyMaterial },
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
#[repr(u64)]
pub enum VibrancyMaterial {
Titlebar = 3,
Selection = 4,
Menu = 5,
Popover = 6,
Sidebar = 7,
HeaderView = 10,
Sheet = 11,
WindowBackground = 12,
HudWindow = 13,
FullScreenUI = 15,
Tooltip = 17,
ContentBackground = 18,
UnderWindowBackground = 21,
UnderPageBackground = 22,
}

#[derive(Debug)]
Expand Down
72 changes: 41 additions & 31 deletions packages/desktop/src/widget_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use std::{
};

use anyhow::Context;
use csscolorparser::Color;
use serde::Serialize;
use tauri::{
AppHandle, Manager, PhysicalPosition, PhysicalSize, WebviewUrl,
Expand All @@ -19,12 +18,13 @@ use tokio::{
task,
};
use tracing::{error, info};
use window_vibrancy::apply_vibrancy;

use crate::{
common::{PathExt, WindowExt},
common::{parse_rgba, PathExt, WindowExt},
config::{
AnchorPoint, BackgroundEffect, Config, WidgetConfig, WidgetPlacement,
ZOrder,
AnchorPoint, Config, MacOsBackgroundEffect, WidgetConfig,
WidgetPlacement, WindowsBackgroundEffect,
},
monitor_state::MonitorState,
};
Expand Down Expand Up @@ -262,38 +262,48 @@ impl WidgetFactory {

#[cfg(target_os = "windows")]
{
if let Some(window_effect) = &widget_config.background_effect {
if *window_effect != BackgroundEffect::None {
let color = if let Some(color_str) =
&widget_config.background_effect_color
{
let color = csscolorparser::parse(color_str)?.to_rgba8();
Some((color[1], color[2], color[3], color[4]))
} else {
Some((18, 18, 18, 125))
};
use window_vibrancy::{apply_acrylic, apply_blur, apply_mica};

use window_vibrancy::{apply_acrylic, apply_blur, apply_mica};
match window_effect {
BackgroundEffect::Blur => {
if let Err(e) = apply_blur(&window, color) {
error!("Failed to apply blur: {:?}", e);
if let Some(window_effect) = &widget_config.background_effect {
if let Some(effect) = &window_effect.windows {
let result = match effect {
WindowsBackgroundEffect::Blur { color }
| WindowsBackgroundEffect::Acrylic { color } => {
let color =
parse_rgba(color).unwrap_or((255, 255, 255, 200));
match effect {
WindowsBackgroundEffect::Blur { .. } => {
apply_blur(&window, Some(color))
}
_ => apply_acrylic(&window, Some(color)),
}
}
BackgroundEffect::Acrylic => {
if let Err(e) = apply_acrylic(&window, color) {
error!("Failed to apply acrylic: {:?}", e);
}
WindowsBackgroundEffect::Mica { prefer_dark } => {
apply_mica(&window, Some(*prefer_dark))
}
BackgroundEffect::Mica => {
let mica_dark = widget_config
.background_effect_mica_dark
.unwrap_or(false);
if let Err(e) = apply_mica(&window, Some(mica_dark)) {
error!("Failed to apply mica: {:?}", e);
}
};

if let Err(e) = result {
error!("Failed to apply effect: {:?}", e);
}
}
}
}

#[cfg(target_os = "macos")]
{
use window_vibrancy::apply_vibrancy;

if let Some(window_effect) = &widget_config.background_effect {
if let Some(effect) = &window_effect.mac_os {
let result = match effect {
MacOsBackgroundEffect::Vibrancy { material } => {
apply_vibrancy(&window, *material, None, None);
}
_ => {}
};

if let Err(e) = result {
error!("Failed to apply macos effect: {:?}", e);
}
}
}
Expand Down

0 comments on commit a8715ab

Please sign in to comment.