aboutsummaryrefslogtreecommitdiff
path: root/src/layer
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-01-21 09:40:00 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-01-21 11:31:30 +0300
commitacd4cb51aa0e013bfec14444ee48a01c60ebaf8a (patch)
tree8530bbe3697d4af8a6e6391e5be5997a4b68c6f4 /src/layer
parent5ebcae997e672dcf0b9c73da383fa40f55a85fcc (diff)
downloadniri-acd4cb51aa0e013bfec14444ee48a01c60ebaf8a.tar.gz
niri-acd4cb51aa0e013bfec14444ee48a01c60ebaf8a.tar.bz2
niri-acd4cb51aa0e013bfec14444ee48a01c60ebaf8a.zip
Implement shadows for layer surfaces
Diffstat (limited to 'src/layer')
-rw-r--r--src/layer/mapped.rs37
-rw-r--r--src/layer/mod.rs24
2 files changed, 59 insertions, 2 deletions
diff --git a/src/layer/mapped.rs b/src/layer/mapped.rs
index dfc09fe3..493bbc58 100644
--- a/src/layer/mapped.rs
+++ b/src/layer/mapped.rs
@@ -1,4 +1,5 @@
use niri_config::layer_rule::LayerRule;
+use niri_config::Config;
use smithay::backend::renderer::element::surface::{
render_elements_from_surface_tree, WaylandSurfaceRenderElement,
};
@@ -7,8 +8,10 @@ use smithay::desktop::{LayerSurface, PopupManager};
use smithay::utils::{Logical, Point, Scale, Size};
use super::ResolvedLayerRules;
+use crate::layout::shadow::Shadow;
use crate::niri_render_elements;
use crate::render_helpers::renderer::NiriRenderer;
+use crate::render_helpers::shadow::ShadowRenderElement;
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
use crate::render_helpers::{RenderTarget, SplitElements};
@@ -22,29 +25,56 @@ pub struct MappedLayer {
/// Buffer to draw instead of the surface when it should be blocked out.
block_out_buffer: SolidColorBuffer,
+
+ /// The shadow around the surface.
+ shadow: Shadow,
}
niri_render_elements! {
LayerSurfaceRenderElement<R> => {
Wayland = WaylandSurfaceRenderElement<R>,
SolidColor = SolidColorRenderElement,
+ Shadow = ShadowRenderElement,
}
}
impl MappedLayer {
- pub fn new(surface: LayerSurface, rules: ResolvedLayerRules) -> Self {
+ pub fn new(surface: LayerSurface, rules: ResolvedLayerRules, config: &Config) -> Self {
+ let mut shadow_config = config.layout.shadow;
+ // Shadows for layer surfaces need to be explicitly enabled.
+ shadow_config.on = false;
+ let shadow_config = rules.shadow.resolve_against(shadow_config);
+
Self {
surface,
rules,
block_out_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
+ shadow: Shadow::new(shadow_config),
}
}
+ pub fn update_config(&mut self, config: &Config) {
+ let mut shadow_config = config.layout.shadow;
+ // Shadows for layer surfaces need to be explicitly enabled.
+ shadow_config.on = false;
+ let shadow_config = self.rules.shadow.resolve_against(shadow_config);
+ self.shadow.update_config(shadow_config);
+ }
+
+ pub fn update_shaders(&mut self) {
+ self.shadow.update_shaders();
+ }
+
pub fn update_render_elements(&mut self, size: Size<f64, Logical>, scale: Scale<f64>) {
// Round to physical pixels.
let size = size.to_physical_precise_round(scale).to_logical(scale);
self.block_out_buffer.resize(size);
+
+ let radius = self.rules.geometry_corner_radius.unwrap_or_default();
+ // FIXME: is_active based on keyboard focus?
+ self.shadow
+ .update_render_elements(size, true, radius, scale.x);
}
pub fn surface(&self) -> &LayerSurface {
@@ -81,6 +111,7 @@ impl MappedLayer {
// Round to physical pixels.
let location = location.to_physical_precise_round(scale).to_logical(scale);
+ // FIXME: take geometry-corner-radius into account.
let elem = SolidColorRenderElement::from_buffer(
&self.block_out_buffer,
location,
@@ -117,6 +148,10 @@ impl MappedLayer {
);
}
+ let location = location.to_physical_precise_round(scale).to_logical(scale);
+ rv.normal
+ .extend(self.shadow.render(renderer, location).map(Into::into));
+
rv
}
}
diff --git a/src/layer/mod.rs b/src/layer/mod.rs
index 72e804d5..36e7ee67 100644
--- a/src/layer/mod.rs
+++ b/src/layer/mod.rs
@@ -1,5 +1,5 @@
use niri_config::layer_rule::{LayerRule, Match};
-use niri_config::BlockOutFrom;
+use niri_config::{BlockOutFrom, CornerRadius, ShadowRule};
use smithay::desktop::LayerSurface;
pub mod mapped;
@@ -13,6 +13,12 @@ pub struct ResolvedLayerRules {
/// Whether to block out this layer surface from certain render targets.
pub block_out_from: Option<BlockOutFrom>,
+
+ /// Shadow overrides.
+ pub shadow: ShadowRule,
+
+ /// Corner radius to assume this layer surface has.
+ pub geometry_corner_radius: Option<CornerRadius>,
}
impl ResolvedLayerRules {
@@ -20,6 +26,17 @@ impl ResolvedLayerRules {
Self {
opacity: None,
block_out_from: None,
+ shadow: ShadowRule {
+ off: false,
+ on: false,
+ offset: None,
+ softness: None,
+ spread: None,
+ draw_behind_window: None,
+ color: None,
+ inactive_color: None,
+ },
+ geometry_corner_radius: None,
}
}
@@ -53,6 +70,11 @@ impl ResolvedLayerRules {
if let Some(x) = rule.block_out_from {
resolved.block_out_from = Some(x);
}
+ if let Some(x) = rule.geometry_corner_radius {
+ resolved.geometry_corner_radius = Some(x);
+ }
+
+ resolved.shadow.merge_with(&rule.shadow);
}
resolved