Skip to content

Commit

Permalink
refactor: change transparency to opacity
Browse files Browse the repository at this point in the history
  • Loading branch information
jackssrt committed Dec 4, 2024
1 parent ea61e61 commit f28cae4
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 67 deletions.
8 changes: 4 additions & 4 deletions packages/wm/src/app_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -228,7 +228,7 @@ pub enum InvokeCommand {
},
SetTransparency {
#[clap(required = true, allow_hyphen_values = true)]
transparency: TransparencyValue,
opacity: OpacityValue,
},
ShellExec {
#[clap(long, action)]
Expand Down Expand Up @@ -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(()),
Expand Down
22 changes: 10 additions & 12 deletions packages/wm/src/common/commands/platform_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
}
},
)
})
}
28 changes: 13 additions & 15 deletions packages/wm/src/common/platform/native_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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 =
Expand All @@ -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 {
Expand All @@ -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(
Expand Down
58 changes: 29 additions & 29 deletions packages/wm/src/common/transparency_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self> {
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
);

Expand All @@ -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),
};

Expand All @@ -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,
Expand All @@ -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<D>(deserializer: D) -> Result<Self, D::Error>
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,
Expand All @@ -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)
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/wm/src/user_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -569,9 +569,9 @@ pub struct TransparencyEffectConfig {
#[serde(default = "default_bool::<false>")]
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)]
Expand Down
8 changes: 4 additions & 4 deletions resources/assets/sample-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.
Expand Down

0 comments on commit f28cae4

Please sign in to comment.