srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/core/src')
-rw-r--r--crates/core/src/manager.rs31
-rw-r--r--crates/core/src/rules.rs2
-rw-r--r--crates/core/src/window.rs8
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,