From 493c8dc89072a746795d4e7b94363cfef3e0ee89 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sun, 24 Mar 2024 09:03:59 +0400 Subject: Implement block-out-from window rule, fix alpha on window screenshots --- src/window/mapped.rs | 45 ++++++++++++++++++++++++++++++++++++--------- src/window/mod.rs | 9 ++++++++- 2 files changed, 44 insertions(+), 10 deletions(-) (limited to 'src/window') diff --git a/src/window/mapped.rs b/src/window/mapped.rs index 52b9ac92..8a4b2473 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -1,7 +1,9 @@ +use std::cell::RefCell; use std::cmp::{max, min}; -use niri_config::WindowRule; -use smithay::backend::renderer::element::{AsRenderElements as _, Id}; +use niri_config::{BlockOutFrom, WindowRule}; +use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; +use smithay::backend::renderer::element::{AsRenderElements as _, Id, Kind}; use smithay::desktop::space::SpaceElement as _; use smithay::desktop::Window; use smithay::output::Output; @@ -16,6 +18,7 @@ use super::{ResolvedWindowRules, WindowRef}; use crate::layout::{LayoutElement, LayoutElementRenderElement}; use crate::niri::WindowOffscreenId; use crate::render_helpers::renderer::NiriRenderer; +use crate::render_helpers::RenderTarget; #[derive(Debug)] pub struct Mapped { @@ -32,6 +35,9 @@ pub struct Mapped { /// Whether this window has the keyboard focus. is_focused: bool, + + /// Buffer to draw instead of the window when it should be blocked out. + block_out_buffer: RefCell, } impl Mapped { @@ -41,6 +47,7 @@ impl Mapped { rules, need_to_recompute_rules: false, is_focused: false, + block_out_buffer: RefCell::new(SolidColorBuffer::new((0, 0), [0., 0., 0., 1.])), } } @@ -109,14 +116,34 @@ impl LayoutElement for Mapped { location: Point, scale: Scale, alpha: f32, + target: RenderTarget, ) -> Vec> { - let buf_pos = location - self.window.geometry().loc; - self.window.render_elements( - renderer, - buf_pos.to_physical_precise_round(scale), - scale, - alpha, - ) + let block_out = match self.rules.block_out_from { + None => false, + Some(BlockOutFrom::Screencast) => target == RenderTarget::Screencast, + Some(BlockOutFrom::ScreenCapture) => target != RenderTarget::Output, + }; + + if block_out { + let mut buffer = self.block_out_buffer.borrow_mut(); + buffer.resize(self.window.geometry().size); + let elem = SolidColorRenderElement::from_buffer( + &buffer, + location.to_physical_precise_round(scale), + scale, + alpha, + Kind::Unspecified, + ); + vec![elem.into()] + } else { + let buf_pos = location - self.window.geometry().loc; + self.window.render_elements( + renderer, + buf_pos.to_physical_precise_round(scale), + scale, + alpha, + ) + } } fn request_size(&self, size: Size) { diff --git a/src/window/mod.rs b/src/window/mod.rs index ddf712b0..3c46e9e5 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -1,4 +1,4 @@ -use niri_config::{Match, WindowRule}; +use niri_config::{BlockOutFrom, Match, WindowRule}; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::wayland::compositor::with_states; use smithay::wayland::shell::xdg::{ @@ -55,6 +55,9 @@ pub struct ResolvedWindowRules { /// Extra opacity to draw this window with. pub opacity: Option, + + /// Whether to block out this window from certain render targets. + pub block_out_from: Option, } impl<'a> WindowRef<'a> { @@ -86,6 +89,7 @@ impl ResolvedWindowRules { max_height: None, draw_border_with_background: None, opacity: None, + block_out_from: None, } } @@ -160,6 +164,9 @@ impl ResolvedWindowRules { if let Some(x) = rule.opacity { resolved.opacity = Some(x); } + if let Some(x) = rule.block_out_from { + resolved.block_out_from = Some(x); + } } resolved.open_on_output = open_on_output.map(|x| x.to_owned()); -- cgit