Skip to content

Commit 1c034dd

Browse files
committed
commit
1 parent f30db16 commit 1c034dd

File tree

21 files changed

+1183
-14
lines changed

21 files changed

+1183
-14
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ tracy-client = { version = "0.18.4", default-features = false }
3232
# version = "0.4.1"
3333
git = "https://github.com/Smithay/smithay.git"
3434
# path = "../smithay"
35+
rev = "fbbcd475743f96f67fcfc4b4b6a5120e822fcfe2"
3536
default-features = false
3637

3738
[workspace.dependencies.smithay-drm-extras]
3839
# version = "0.1.0"
3940
git = "https://github.com/Smithay/smithay.git"
41+
rev = "fbbcd475743f96f67fcfc4b4b6a5120e822fcfe2"
4042
# path = "../smithay/smithay-drm-extras"
4143

4244
[package]

niri-config/src/appearance.rs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,101 @@ where
10061006
}
10071007
}
10081008

1009+
#[derive(Debug, Clone, Copy, PartialEq)]
1010+
pub struct Blur {
1011+
pub off: bool,
1012+
pub passes: u8,
1013+
pub offset: f64,
1014+
}
1015+
1016+
impl Default for Blur {
1017+
fn default() -> Self {
1018+
Self {
1019+
off: false,
1020+
// TODO: tune, reduce passes
1021+
passes: 3,
1022+
offset: 3.,
1023+
}
1024+
}
1025+
}
1026+
1027+
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)]
1028+
pub struct BlurPart {
1029+
#[knuffel(child)]
1030+
pub off: bool,
1031+
#[knuffel(child)]
1032+
pub on: bool,
1033+
#[knuffel(child, unwrap(argument))]
1034+
pub passes: Option<u8>,
1035+
#[knuffel(child, unwrap(argument))]
1036+
pub offset: Option<FloatOrInt<0, 100>>,
1037+
}
1038+
1039+
impl MergeWith<BlurPart> for Blur {
1040+
fn merge_with(&mut self, part: &BlurPart) {
1041+
self.off |= part.off;
1042+
if part.on {
1043+
self.off = false;
1044+
}
1045+
1046+
merge_clone!((self, part), passes);
1047+
merge!((self, part), offset);
1048+
}
1049+
}
1050+
1051+
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)]
1052+
pub struct BlurRule {
1053+
#[knuffel(child)]
1054+
pub off: bool,
1055+
#[knuffel(child)]
1056+
pub on: bool,
1057+
}
1058+
1059+
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq)]
1060+
pub struct BackgroundEffectRule {
1061+
#[knuffel(child, unwrap(argument))]
1062+
pub xray: Option<bool>,
1063+
#[knuffel(child, default)]
1064+
pub blur: BlurRule,
1065+
}
1066+
1067+
impl MergeWith<Self> for BackgroundEffectRule {
1068+
fn merge_with(&mut self, part: &Self) {
1069+
merge_clone_opt!((self, part), xray);
1070+
merge_on_off!((self.blur, part.blur));
1071+
}
1072+
}
1073+
1074+
/// Resolved background effect rule.
1075+
#[derive(Debug, Default, Clone, Copy, PartialEq)]
1076+
pub struct BackgroundEffect {
1077+
/// Whether to render with xray effect (see through).
1078+
pub xray: bool,
1079+
1080+
/// Whether to blur the background.
1081+
///
1082+
/// - `None`: blur when the window/layer requests it (e.g. through ext-background-effect
1083+
/// protocol)
1084+
/// - `Some(false)`: never blur
1085+
/// - `Some(true)`: always blur
1086+
pub blur: Option<bool>,
1087+
}
1088+
1089+
impl MergeWith<BackgroundEffectRule> for BackgroundEffect {
1090+
fn merge_with(&mut self, part: &BackgroundEffectRule) {
1091+
if let Some(x) = part.xray {
1092+
self.xray = x;
1093+
}
1094+
1095+
if part.blur.on {
1096+
self.blur = Some(true);
1097+
}
1098+
if part.blur.off {
1099+
self.blur = Some(false);
1100+
}
1101+
}
1102+
}
1103+
10091104
#[cfg(test)]
10101105
mod tests {
10111106
use insta::{assert_debug_snapshot, assert_snapshot};

niri-config/src/layer_rule.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::appearance::{BlockOutFrom, CornerRadius, ShadowRule};
1+
use crate::appearance::{BackgroundEffectRule, BlockOutFrom, CornerRadius, ShadowRule};
22
use crate::utils::RegexEq;
33

44
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]
@@ -20,6 +20,8 @@ pub struct LayerRule {
2020
pub place_within_backdrop: Option<bool>,
2121
#[knuffel(child, unwrap(argument))]
2222
pub baba_is_float: Option<bool>,
23+
#[knuffel(child, default)]
24+
pub background_effect: BackgroundEffectRule,
2325
}
2426

2527
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]

niri-config/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub struct Config {
7878
pub hotkey_overlay: HotkeyOverlay,
7979
pub config_notification: ConfigNotification,
8080
pub animations: Animations,
81+
pub blur: Blur,
8182
pub gestures: Gestures,
8283
pub overview: Overview,
8384
pub environment: Environment,
@@ -194,6 +195,7 @@ where
194195
"hotkey-overlay" => m_merge!(hotkey_overlay),
195196
"config-notification" => m_merge!(config_notification),
196197
"animations" => m_merge!(animations),
198+
"blur" => m_merge!(blur),
197199
"gestures" => m_merge!(gestures),
198200
"overview" => m_merge!(overview),
199201
"xwayland-satellite" => m_merge!(xwayland_satellite),
@@ -1616,6 +1618,11 @@ mod tests {
16161618
},
16171619
),
16181620
},
1621+
blur: Blur {
1622+
off: false,
1623+
passes: 3,
1624+
offset: 3.0,
1625+
},
16191626
gestures: Gestures {
16201627
dnd_edge_view_scroll: DndEdgeViewScroll {
16211628
trigger_width: 10.0,
@@ -1845,6 +1852,13 @@ mod tests {
18451852
),
18461853
scroll_factor: None,
18471854
tiled_state: None,
1855+
background_effect: BackgroundEffectRule {
1856+
xray: None,
1857+
blur: BlurRule {
1858+
off: false,
1859+
on: false,
1860+
},
1861+
},
18481862
},
18491863
],
18501864
layer_rules: [
@@ -1879,6 +1893,13 @@ mod tests {
18791893
geometry_corner_radius: None,
18801894
place_within_backdrop: None,
18811895
baba_is_float: None,
1896+
background_effect: BackgroundEffectRule {
1897+
xray: None,
1898+
blur: BlurRule {
1899+
off: false,
1900+
on: false,
1901+
},
1902+
},
18821903
},
18831904
],
18841905
binds: Binds(

niri-config/src/window_rule.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use niri_ipc::ColumnDisplay;
22

3-
use crate::appearance::{BlockOutFrom, BorderRule, CornerRadius, ShadowRule, TabIndicatorRule};
3+
use crate::appearance::{
4+
BackgroundEffectRule, BlockOutFrom, BorderRule, CornerRadius, ShadowRule, TabIndicatorRule,
5+
};
46
use crate::layout::DefaultPresetSize;
57
use crate::utils::RegexEq;
68
use crate::FloatOrInt;
@@ -72,6 +74,8 @@ pub struct WindowRule {
7274
pub scroll_factor: Option<FloatOrInt<0, 100>>,
7375
#[knuffel(child, unwrap(argument))]
7476
pub tiled_state: Option<bool>,
77+
#[knuffel(child, default)]
78+
pub background_effect: BackgroundEffectRule,
7579
}
7680

7781
#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq)]

src/layer/mapped.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use super::ResolvedLayerRules;
1010
use crate::animation::Clock;
1111
use crate::layout::shadow::Shadow;
1212
use crate::niri_render_elements;
13+
use crate::render_helpers::background_effect::{self, BackgroundEffect, BackgroundEffectElement};
1314
use crate::render_helpers::renderer::NiriRenderer;
1415
use crate::render_helpers::shadow::ShadowRenderElement;
1516
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
@@ -31,6 +32,9 @@ pub struct MappedLayer {
3132
/// The shadow around the surface.
3233
shadow: Shadow,
3334

35+
/// The background effect underneath the layer surface geometry.
36+
pub background_effect: BackgroundEffect,
37+
3438
/// The view size for the layer surface's output.
3539
view_size: Size<f64, Logical>,
3640

@@ -46,6 +50,7 @@ niri_render_elements! {
4650
Wayland = WaylandSurfaceRenderElement<R>,
4751
SolidColor = SolidColorRenderElement,
4852
Shadow = ShadowRenderElement,
53+
BackgroundEffect = BackgroundEffectElement,
4954
}
5055
}
5156

@@ -70,6 +75,7 @@ impl MappedLayer {
7075
view_size,
7176
scale,
7277
shadow: Shadow::new(shadow_config),
78+
background_effect: BackgroundEffect::new(),
7379
clock,
7480
}
7581
}
@@ -103,6 +109,16 @@ impl MappedLayer {
103109
// FIXME: is_active based on keyboard focus?
104110
self.shadow
105111
.update_render_elements(size, true, radius, self.scale, 1.);
112+
113+
let effect = self.rules.background_effect;
114+
self.background_effect
115+
.update_params(background_effect::Parameters {
116+
corner_radius: radius,
117+
xray: effect.xray,
118+
// TODO: ext-background-effect
119+
blur: effect.blur == Some(true),
120+
});
121+
self.background_effect.update_size(size);
106122
}
107123

108124
pub fn are_animations_ongoing(&self) -> bool {
@@ -197,6 +213,12 @@ impl MappedLayer {
197213
let location = location.to_physical_precise_round(scale).to_logical(scale);
198214
self.shadow
199215
.render(renderer, location, &mut |elem| push(elem.into()));
216+
217+
// TODO subsurfaces peeking out of the main surface? Ext background effect subsurfaces?
218+
if let Some(elem) = self.background_effect.render(renderer.as_gles_renderer()) {
219+
let location = location.to_physical_precise_round(scale).to_logical(scale);
220+
push(elem.with_location(location).into());
221+
}
200222
}
201223

202224
pub fn render_popups<R: NiriRenderer>(

src/layer/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use niri_config::layer_rule::{LayerRule, Match};
22
use niri_config::utils::MergeWith as _;
3-
use niri_config::{BlockOutFrom, CornerRadius, ShadowRule};
3+
use niri_config::{BackgroundEffect, BlockOutFrom, CornerRadius, ShadowRule};
44
use smithay::desktop::LayerSurface;
55

66
pub mod mapped;
@@ -26,6 +26,9 @@ pub struct ResolvedLayerRules {
2626

2727
/// Whether to bob this window up and down.
2828
pub baba_is_float: bool,
29+
30+
/// Background effect configuration.
31+
pub background_effect: BackgroundEffect,
2932
}
3033

3134
impl ResolvedLayerRules {
@@ -70,6 +73,10 @@ impl ResolvedLayerRules {
7073
}
7174

7275
resolved.shadow.merge_with(&rule.shadow);
76+
77+
resolved
78+
.background_effect
79+
.merge_with(&rule.background_effect);
7380
}
7481

7582
resolved

src/layout/tile.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::{
1818
use crate::animation::{Animation, Clock};
1919
use crate::layout::SizingMode;
2020
use crate::niri_render_elements;
21+
use crate::render_helpers::background_effect::{self, BackgroundEffect, BackgroundEffectElement};
2122
use crate::render_helpers::border::BorderRenderElement;
2223
use crate::render_helpers::clipped_surface::{ClippedSurfaceRenderElement, RoundedCornerDamage};
2324
use crate::render_helpers::damage::ExtraDamage;
@@ -57,6 +58,9 @@ pub struct Tile<W: LayoutElement> {
5758
/// The black backdrop for fullscreen windows.
5859
fullscreen_backdrop: SolidColorBuffer,
5960

61+
/// The background effect underneath the window geometry.
62+
pub background_effect: BackgroundEffect,
63+
6064
/// Whether the tile should float upon unfullscreening.
6165
pub(super) restore_to_floating: bool,
6266

@@ -130,6 +134,7 @@ niri_render_elements! {
130134
ClippedSurface = ClippedSurfaceRenderElement<R>,
131135
Offscreen = OffscreenRenderElement,
132136
ExtraDamage = ExtraDamage,
137+
BackgroundEffect = BackgroundEffectElement,
133138
}
134139
}
135140

@@ -192,6 +197,7 @@ impl<W: LayoutElement> Tile<W> {
192197
shadow: Shadow::new(shadow_config),
193198
sizing_mode,
194199
fullscreen_backdrop: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
200+
background_effect: BackgroundEffect::new(),
195201
restore_to_floating: false,
196202
floating_window_size: None,
197203
floating_pos: None,
@@ -455,6 +461,7 @@ impl<W: LayoutElement> Tile<W> {
455461
pub fn update_render_elements(&mut self, is_active: bool, view_rect: Rectangle<f64, Logical>) {
456462
let rules = self.window.rules();
457463
let animated_tile_size = self.animated_tile_size();
464+
let animated_window_size = self.animated_window_size();
458465
let expanded_progress = self.expanded_progress();
459466

460467
let draw_border_with_background = rules
@@ -505,6 +512,16 @@ impl<W: LayoutElement> Tile<W> {
505512
1. - expanded_progress as f32,
506513
);
507514

515+
let effect = rules.background_effect;
516+
self.background_effect
517+
.update_params(background_effect::Parameters {
518+
corner_radius: radius,
519+
xray: effect.xray,
520+
// TODO: ext-background-effect
521+
blur: effect.blur == Some(true),
522+
});
523+
self.background_effect.update_size(animated_window_size);
524+
508525
let draw_focus_ring_with_background = if self.border.is_off() {
509526
draw_border_with_background
510527
} else {
@@ -1283,6 +1300,11 @@ impl<W: LayoutElement> Tile<W> {
12831300
self.shadow
12841301
.render(renderer, location, &mut |elem| push(elem.into()));
12851302
}
1303+
1304+
// TODO subsurfaces peeking out of the main surface? Ext background effect subsurfaces?
1305+
if let Some(elem) = self.background_effect.render(renderer.as_gles_renderer()) {
1306+
push(elem.with_location(window_render_loc).into());
1307+
}
12861308
}
12871309

12881310
pub fn render<R: NiriRenderer>(

0 commit comments

Comments
 (0)