aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--niri-config/src/lib.rs2
-rw-r--r--niri-visual-tests/src/cases/window.rs2
-rw-r--r--niri-visual-tests/src/test_window.rs5
-rw-r--r--resources/default-config.kdl10
-rw-r--r--src/layout/mod.rs2
-rw-r--r--src/layout/tile.rs8
-rw-r--r--src/window/mapped.rs3
-rw-r--r--src/window/mod.rs7
8 files changed, 34 insertions, 5 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 6e8bab2e..9bf62e13 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -697,6 +697,8 @@ pub struct WindowRule {
#[knuffel(child, unwrap(argument))]
pub draw_border_with_background: Option<bool>,
+ #[knuffel(child, unwrap(argument))]
+ pub opacity: Option<f32>,
}
// Remember to update the PartialEq impl when adding fields!
diff --git a/niri-visual-tests/src/cases/window.rs b/niri-visual-tests/src/cases/window.rs
index f8f7a1af..a8855f46 100644
--- a/niri-visual-tests/src/cases/window.rs
+++ b/niri-visual-tests/src/cases/window.rs
@@ -49,7 +49,7 @@ impl TestCase for Window {
let location = Point::from(((size.w - win_size.w) / 2, (size.h - win_size.h) / 2));
self.window
- .render(renderer, location, Scale::from(1.))
+ .render(renderer, location, Scale::from(1.), 1.)
.into_iter()
.map(|elem| Box::new(elem) as _)
.collect()
diff --git a/niri-visual-tests/src/test_window.rs b/niri-visual-tests/src/test_window.rs
index 4f89d15e..341f4fbf 100644
--- a/niri-visual-tests/src/test_window.rs
+++ b/niri-visual-tests/src/test_window.rs
@@ -146,6 +146,7 @@ impl LayoutElement for TestWindow {
_renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ alpha: f32,
) -> Vec<LayoutElementRenderElement<R>> {
let inner = self.inner.borrow();
@@ -154,7 +155,7 @@ impl LayoutElement for TestWindow {
&inner.buffer,
location.to_physical_precise_round(scale),
scale,
- 1.,
+ alpha,
Kind::Unspecified,
)
.into(),
@@ -163,7 +164,7 @@ impl LayoutElement for TestWindow {
(location - Point::from((inner.csd_shadow_width, inner.csd_shadow_width)))
.to_physical_precise_round(scale),
scale,
- 1.,
+ alpha,
Kind::Unspecified,
)
.into(),
diff --git a/resources/default-config.kdl b/resources/default-config.kdl
index 485ab649..0878f213 100644
--- a/resources/default-config.kdl
+++ b/resources/default-config.kdl
@@ -414,6 +414,16 @@ animations {
// Set this to `false` to draw them as borders around the window even for
// windows which use client-side decorations.
draw-border-with-background false
+
+ // Set the opacity of the window.
+ // This is applied on top of the window's own opacity, so semitransparent
+ // windows will become even more transparent.
+ // Opacity is applied to every surface of the window individually, so
+ // subsurfaces and pop-up menus will show window content behind them.
+ // Also, focus ring and border with background will show through
+ // semitransparent windows (see prefer-no-csd and
+ // the draw-border-with-background property above).
+ opacity 0.5
}
// Here's a useful example. Work around WezTerm's initial configure bug
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index bc5c8dcf..bbca41c9 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -95,6 +95,7 @@ pub trait LayoutElement {
renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ alpha: f32,
) -> Vec<LayoutElementRenderElement<R>>;
fn request_size(&self, size: Size<i32, Logical>);
@@ -1856,6 +1857,7 @@ mod tests {
_renderer: &mut R,
_location: Point<i32, Logical>,
_scale: Scale<f64>,
+ _alpha: f32,
) -> Vec<LayoutElementRenderElement<R>> {
vec![]
}
diff --git a/src/layout/tile.rs b/src/layout/tile.rs
index 0609583e..faa17840 100644
--- a/src/layout/tile.rs
+++ b/src/layout/tile.rs
@@ -325,9 +325,15 @@ impl<W: LayoutElement> Tile<W> {
view_size: Size<i32, Logical>,
focus_ring: bool,
) -> impl Iterator<Item = TileRenderElement<R>> {
+ let alpha = if self.is_fullscreen {
+ 1.
+ } else {
+ self.window.rules().opacity.unwrap_or(1.).clamp(0., 1.)
+ };
+
let rv = self
.window
- .render(renderer, location + self.window_loc(), scale)
+ .render(renderer, location + self.window_loc(), scale, alpha)
.into_iter()
.map(Into::into);
diff --git a/src/window/mapped.rs b/src/window/mapped.rs
index a48ca636..52b9ac92 100644
--- a/src/window/mapped.rs
+++ b/src/window/mapped.rs
@@ -108,13 +108,14 @@ impl LayoutElement for Mapped {
renderer: &mut R,
location: Point<i32, Logical>,
scale: Scale<f64>,
+ alpha: f32,
) -> Vec<LayoutElementRenderElement<R>> {
let buf_pos = location - self.window.geometry().loc;
self.window.render_elements(
renderer,
buf_pos.to_physical_precise_round(scale),
scale,
- 1.,
+ alpha,
)
}
diff --git a/src/window/mod.rs b/src/window/mod.rs
index 63cdbe3f..ddf712b0 100644
--- a/src/window/mod.rs
+++ b/src/window/mod.rs
@@ -52,6 +52,9 @@ pub struct ResolvedWindowRules {
///
/// `None` means using the SSD heuristic.
pub draw_border_with_background: Option<bool>,
+
+ /// Extra opacity to draw this window with.
+ pub opacity: Option<f32>,
}
impl<'a> WindowRef<'a> {
@@ -82,6 +85,7 @@ impl ResolvedWindowRules {
max_width: None,
max_height: None,
draw_border_with_background: None,
+ opacity: None,
}
}
@@ -153,6 +157,9 @@ impl ResolvedWindowRules {
if let Some(x) = rule.draw_border_with_background {
resolved.draw_border_with_background = Some(x);
}
+ if let Some(x) = rule.opacity {
+ resolved.opacity = Some(x);
+ }
}
resolved.open_on_output = open_on_output.map(|x| x.to_owned());