From f28cae416ac0d9cc743775499f6e21960e50114b Mon Sep 17 00:00:00 2001 From: jackssrt <33695699+jackssrt@users.noreply.github.com> Date: Tue, 3 Dec 2024 20:41:11 +0200 Subject: [PATCH] refactor: change transparency to opacity --- packages/wm/src/app_command.rs | 8 +-- .../wm/src/common/commands/platform_sync.rs | 22 ++++--- .../wm/src/common/platform/native_window.rs | 28 +++++---- packages/wm/src/common/transparency_value.rs | 58 +++++++++---------- packages/wm/src/user_config.rs | 6 +- resources/assets/sample-config.yaml | 8 +-- 6 files changed, 63 insertions(+), 67 deletions(-) diff --git a/packages/wm/src/app_command.rs b/packages/wm/src/app_command.rs index 15453c51..36226ce9 100644 --- a/packages/wm/src/app_command.rs +++ b/packages/wm/src/app_command.rs @@ -12,7 +12,7 @@ use crate::{ cycle_focus, disable_binding_mode, enable_binding_mode, reload_config, shell_exec, toggle_pause, }, - Direction, LengthValue, RectDelta, TilingDirection, TransparencyValue, + Direction, LengthValue, OpacityValue, RectDelta, TilingDirection, }, containers::{ commands::{ @@ -228,7 +228,7 @@ pub enum InvokeCommand { }, SetTransparency { #[clap(required = true, allow_hyphen_values = true)] - transparency: TransparencyValue, + opacity: OpacityValue, }, ShellExec { #[clap(long, action)] @@ -606,10 +606,10 @@ impl InvokeCommand { _ => Ok(()), } } - InvokeCommand::SetTransparency { transparency } => { + InvokeCommand::SetTransparency { opacity } => { match subject_container.as_window_container() { Ok(window) => { - _ = window.native().set_transparency(transparency.clone()); + _ = window.native().set_opacity(opacity.clone()); Ok(()) } _ => Ok(()), diff --git a/packages/wm/src/common/commands/platform_sync.rs b/packages/wm/src/common/commands/platform_sync.rs index 94d91d2d..0a30b0f1 100644 --- a/packages/wm/src/common/commands/platform_sync.rs +++ b/packages/wm/src/common/commands/platform_sync.rs @@ -5,9 +5,7 @@ use tokio::task; use tracing::warn; use crate::{ - common::{ - platform::Platform, DisplayState, TransparencyUnit, TransparencyValue, - }, + common::{platform::Platform, DisplayState, OpacityUnit, OpacityValue}, containers::{ traits::{CommonGetters, PositionGetters}, Container, WindowContainer, @@ -293,19 +291,19 @@ fn apply_transparency_effect( window: &WindowContainer, effect_config: &WindowEffectConfig, ) { - _ = window.native().set_transparency( - if effect_config.transparency.enabled { - effect_config.transparency.transparency.clone() + _ = window + .native() + .set_opacity(if effect_config.transparency.enabled { + effect_config.transparency.opacity.clone() } else { // This code is only reached if the transparency effect is only // enabled in one of the two window effect configurations. In - // this case, reset the transparency to default. - TransparencyValue { - amount: 0.0, - unit: TransparencyUnit::Exact, + // this case, reset the opacity to default. + OpacityValue { + amount: 255.0, + unit: OpacityUnit::Alpha, delta_sign: false, is_delta: false, } - }, - ) + }) } diff --git a/packages/wm/src/common/platform/native_window.rs b/packages/wm/src/common/platform/native_window.rs index 7066271a..c19f192c 100644 --- a/packages/wm/src/common/platform/native_window.rs +++ b/packages/wm/src/common/platform/native_window.rs @@ -46,7 +46,7 @@ use windows::{ use super::{iapplication_view_collection, iservice_provider, COM_INIT}; use crate::{ - common::{Color, LengthValue, Memo, Rect, RectDelta, TransparencyValue}, + common::{Color, LengthValue, Memo, OpacityValue, Rect, RectDelta}, user_config::{CornerStyle, HideMethod}, windows::WindowState, }; @@ -398,9 +398,9 @@ impl NativeWindow { Ok(()) } - pub fn set_transparency( + pub fn set_opacity( &self, - transparency: TransparencyValue, + opacity_value: OpacityValue, ) -> anyhow::Result<()> { // Make the window layered if it isn't already. let ex_style = @@ -417,7 +417,7 @@ impl NativeWindow { } } - // Get the window's transparency information. + // Get the window's opacity information. let mut previous_opacity = MaybeUninit::uninit(); let mut flag = MaybeUninit::uninit(); unsafe { @@ -439,22 +439,20 @@ impl NativeWindow { } // Calculate the new opacity value. - let transparency_value = transparency.to_exact(); - let new_opacity = if transparency.is_delta { - // Flip the sign of the delta to get the *opacity* delta. - // TODO: Use saturating_sub_signed when it's stable - if !transparency.delta_sign { - // -(-x) is x - previous_opacity.saturating_add(transparency_value) + let exact_opacity_value = opacity_value.to_exact(); + let new_opacity = if opacity_value.is_delta { + // TODO: Enable feature for saturing_sub_signed + // TODO: Use a signed value for delta + if !opacity_value.delta_sign { + previous_opacity.saturating_sub(exact_opacity_value) } else { - // -(x) is -x - previous_opacity.saturating_sub(transparency_value) + previous_opacity.saturating_add(exact_opacity_value) } } else { - 255u8.saturating_sub(transparency_value) + exact_opacity_value }; - // Set new transparency if needed. + // Set the new opacity if needed. if new_opacity != previous_opacity { unsafe { SetLayeredWindowAttributes( diff --git a/packages/wm/src/common/transparency_value.rs b/packages/wm/src/common/transparency_value.rs index 8fd9e020..820dc6a5 100644 --- a/packages/wm/src/common/transparency_value.rs +++ b/packages/wm/src/common/transparency_value.rs @@ -5,65 +5,65 @@ use regex::Regex; use serde::{Deserialize, Deserializer, Serialize}; #[derive(Debug, Clone, PartialEq, Serialize)] -pub struct TransparencyValue { +pub struct OpacityValue { pub amount: f32, - pub unit: TransparencyUnit, + pub unit: OpacityUnit, pub is_delta: bool, pub delta_sign: bool, } #[derive(Debug, Deserialize, Clone, PartialEq, Serialize)] #[serde(rename_all = "snake_case")] -pub enum TransparencyUnit { - Exact, +pub enum OpacityUnit { + Alpha, Percentage, } -impl TransparencyValue { +impl OpacityValue { pub fn to_exact(&self) -> u8 { match self.unit { - TransparencyUnit::Exact => self.amount as u8, - TransparencyUnit::Percentage => (self.amount * 255.0) as u8, + OpacityUnit::Alpha => self.amount as u8, + OpacityUnit::Percentage => (self.amount * 255.0) as u8, } } } -impl Default for TransparencyValue { +impl Default for OpacityValue { fn default() -> Self { Self { - amount: 1.0, - unit: TransparencyUnit::Exact, + amount: 255.0, + unit: OpacityUnit::Alpha, is_delta: false, delta_sign: false, } } } -impl FromStr for TransparencyValue { +impl FromStr for OpacityValue { type Err = anyhow::Error; - /// Parses a string for a transparency value. The string can be a number + /// Parses a string for an opacity value. The string can be a number /// or a percentage. If the string starts with a sign, the value is /// interpreted as a delta. /// /// Example: /// ``` - /// # use wm::common::{TransparencyValue, TransparencyUnit}; + /// # use wm::common::{OpacityValue, OpacityUnit}; /// # use std::str::FromStr; - /// let check = TransparencyValue { + /// let check = OpacityValue { /// amount: 0.75, - /// unit: TransparencyUnit::Percentage, + /// unit: OpacityUnit::Percentage, /// is_delta: false, /// delta_sign: false, /// }; - /// let parsed = TransparencyValue::from_str("75%"); + /// let parsed = OpacityValue::from_str("75%"); /// assert_eq!(parsed.unwrap(), check); /// ``` fn from_str(unparsed: &str) -> anyhow::Result { let units_regex = Regex::new(r"([+-]?)(\d+)(%?)")?; let err_msg = format!( - "Not a valid transparency value '{}'. Must be of format '255', '100%', '+10%' or '-128'.", + "Not a valid opacity value '{}'. Must be of format '255', '100%', '+10%' or '-128'.", unparsed ); @@ -79,8 +79,8 @@ impl FromStr for TransparencyValue { let unit_str = captures.get(3).map_or("", |m| m.as_str()); let unit = match unit_str { - "" => TransparencyUnit::Exact, - "%" => TransparencyUnit::Percentage, + "" => OpacityUnit::Alpha, + "%" => OpacityUnit::Percentage, _ => bail!(err_msg), }; @@ -89,12 +89,12 @@ impl FromStr for TransparencyValue { .and_then(|amount_str| f32::from_str(amount_str.into()).ok()) // Store percentage units as a fraction of 1. .map(|amount| match unit { - TransparencyUnit::Exact => amount, - TransparencyUnit::Percentage => amount / 100.0, + OpacityUnit::Alpha => amount, + OpacityUnit::Percentage => amount / 100.0, }) .context(err_msg.to_string())?; - Ok(TransparencyValue { + Ok(OpacityValue { amount, unit, is_delta, @@ -103,26 +103,26 @@ impl FromStr for TransparencyValue { } } -/// Deserialize a `TransparencyValue` from either a string or a struct. -impl<'de> Deserialize<'de> for TransparencyValue { +/// Deserialize an `OpacityValue` from either a string or a struct. +impl<'de> Deserialize<'de> for OpacityValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { #[derive(Deserialize)] #[serde(untagged, rename_all = "camelCase")] - enum TransparencyValueDe { + enum OpacityValueDe { Struct { amount: f32, - unit: TransparencyUnit, + unit: OpacityUnit, is_delta: bool, delta_sign: bool, }, String(String), } - match TransparencyValueDe::deserialize(deserializer)? { - TransparencyValueDe::Struct { + match OpacityValueDe::deserialize(deserializer)? { + OpacityValueDe::Struct { amount, unit, is_delta, @@ -133,7 +133,7 @@ impl<'de> Deserialize<'de> for TransparencyValue { is_delta, delta_sign, }), - TransparencyValueDe::String(str) => { + OpacityValueDe::String(str) => { Self::from_str(&str).map_err(serde::de::Error::custom) } } diff --git a/packages/wm/src/user_config.rs b/packages/wm/src/user_config.rs index 249bc39b..35f144a8 100644 --- a/packages/wm/src/user_config.rs +++ b/packages/wm/src/user_config.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ app_command::InvokeCommand, - common::{Color, LengthValue, RectDelta, TransparencyValue}, + common::{Color, LengthValue, OpacityValue, RectDelta}, containers::{traits::CommonGetters, WindowContainer}, monitors::Monitor, windows::traits::WindowGetters, @@ -569,9 +569,9 @@ pub struct TransparencyEffectConfig { #[serde(default = "default_bool::")] pub enabled: bool, - /// Amount of transparency to apply. + /// The opacity to apply. #[serde(default)] - pub transparency: TransparencyValue, + pub opacity: OpacityValue, } #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/resources/assets/sample-config.yaml b/resources/assets/sample-config.yaml index ea6688a8..6e722dcd 100644 --- a/resources/assets/sample-config.yaml +++ b/resources/assets/sample-config.yaml @@ -77,9 +77,9 @@ window_effects: # Change the transparency of the window. transparency: enabled: false - # Can be something like '15' or '5%' for slightly transparent windows - # '255' or '100%' is fully transparent (and, by consequence, unfocusable) - transparency: '5%' + # Can be something like '240' or '95%' for slightly transparent windows + # '0' or '0%' is fully transparent (and, by consequence, unfocusable) + opacity: '95%' # Visual effects to apply to non-focused windows. other_windows: @@ -93,7 +93,7 @@ window_effects: style: 'square' transparency: enabled: false - transparency: '10%' + opacity: '0%' window_behavior: # New windows are created in this state whenever possible.