diff options
Diffstat (limited to 'crates/core/src')
| -rw-r--r-- | crates/core/src/manager.rs | 31 | ||||
| -rw-r--r-- | crates/core/src/rules.rs | 2 | ||||
| -rw-r--r-- | crates/core/src/window.rs | 8 |
3 files changed, 41 insertions, 0 deletions
diff --git a/crates/core/src/manager.rs b/crates/core/src/manager.rs index 2c92ac1..d45eaf6 100644 --- a/crates/core/src/manager.rs +++ b/crates/core/src/manager.rs @@ -266,6 +266,9 @@ impl WindowManager { if let Some(pinned) = a.pinned { window.always_on_top = pinned; } + if let Some(opacity) = a.opacity { + window.opacity = opacity.clamp(0.0, 1.0); + } } if let Some(monitor) = self.primary_monitor() { @@ -338,6 +341,9 @@ impl WindowManager { if let Some(pinned) = actions.pinned { window.always_on_top = pinned; } + if let Some(opacity) = actions.opacity { + window.opacity = opacity.clamp(0.0, 1.0); + } if let Some(geometry) = actions.geometry { window.geometry = geometry; } @@ -1807,6 +1813,31 @@ mod tests { } #[test] + fn opacity_rule_applies_on_the_deferred_retry_same_as_other_actions() { + // Regression test: `opacity` was added to `add_window`'s own rule + // application but missed here, in the deferred retry + // `reapply_rules_if_pending` - confirmed live: a rule like + // `srd.rule({ class = "Alacritty" }, { opacity = 0.4 })` never took + // effect for any real native Wayland client, since (per the test + // above) that's the *only* path a class-based rule actually + // matches through for one of those - `add_window`'s own match + // attempt always fails first, against an as-yet-empty `app_id`. + let mut wm = wm_with_monitor(); + wm.add_rule(WindowRule { + matcher: crate::rules::WindowMatch { class: Some("alacritty".into()), ..Default::default() }, + actions: crate::rules::WindowRuleActions { opacity: Some(0.4), ..Default::default() }, + }); + let id = wm.alloc_window_id(); + wm.add_window(Window::new(id, "")); + assert_eq!(wm.window(id).unwrap().opacity, 1.0, "no app_id yet, so no match - must not have applied early"); + + let w = wm.window_mut(id).unwrap(); + w.app_id = "Alacritty".into(); + wm.reapply_rules_if_pending(id); + assert_eq!(wm.window(id).unwrap().opacity, 0.4, "app_id now known - the rule must apply on retry"); + } + + #[test] fn fullscreen_from_maximized_still_restores_the_pre_maximize_size() { // Both share `restore_geometry`; entering fullscreen from a // maximised window must not overwrite it with the monitor rect, or diff --git a/crates/core/src/rules.rs b/crates/core/src/rules.rs index 148b627..e0e87cb 100644 --- a/crates/core/src/rules.rs +++ b/crates/core/src/rules.rs @@ -88,6 +88,8 @@ pub struct WindowRuleActions { pub border_width: Option<u32>, /// Always-on-top (Hyprland's `pin`). pub pinned: Option<bool>, + /// Content opacity, `0.0`..=`1.0` (Hyprland's `windowrule = opacity`). + pub opacity: Option<f32>, } #[derive(Debug, Clone, Default)] diff --git a/crates/core/src/window.rs b/crates/core/src/window.rs index e30f501..774b0e2 100644 --- a/crates/core/src/window.rs +++ b/crates/core/src/window.rs @@ -90,6 +90,13 @@ pub struct Window { pub always_on_top: bool, pub border_color: (u8, u8, u8), pub border_width: u32, + /// This window's own content opacity, `0.0`..=`1.0`. Only the content + /// (the client's own surface tree) is affected - srdwm's own + /// decoration (titlebar/border/shadow) always renders fully opaque + /// regardless, the same way a native macOS/Windows translucent-window + /// effect still keeps its frame legible. Set via `srd.window. + /// set_opacity()` or a rule's `opacity` action. + pub opacity: f32, pub workspace: usize, pub monitor: u32, /// Whether `WindowManager`'s class/title-matched rules have already @@ -135,6 +142,7 @@ impl Window { always_on_top: false, border_color: (136, 192, 208), // Nord accent, matches legacy theme default border_width: 2, + opacity: 1.0, workspace: 0, monitor: 0, rules_applied: false, |