aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/handlers/layer_shell.rs17
-rw-r--r--src/layer/mapped.rs53
-rw-r--r--src/layer/mod.rs7
-rw-r--r--src/layout/tile.rs6
-rw-r--r--src/niri.rs35
-rw-r--r--src/utils/mod.rs7
6 files changed, 101 insertions, 24 deletions
diff --git a/src/handlers/layer_shell.rs b/src/handlers/layer_shell.rs
index 04366ab3..7678ccc1 100644
--- a/src/handlers/layer_shell.rs
+++ b/src/handlers/layer_shell.rs
@@ -12,7 +12,7 @@ use smithay::wayland::shell::xdg::PopupSurface;
use crate::layer::{MappedLayer, ResolvedLayerRules};
use crate::niri::State;
-use crate::utils::{is_mapped, send_scale_transform};
+use crate::utils::{is_mapped, output_size, send_scale_transform};
impl WlrLayerShellHandler for State {
fn shell_state(&mut self) -> &mut WlrLayerShellState {
@@ -125,10 +125,23 @@ impl State {
// Resolve rules for newly mapped layer surfaces.
if was_unmapped {
let config = self.niri.config.borrow();
+
let rules = &config.layer_rules;
let rules =
ResolvedLayerRules::compute(rules, layer, self.niri.is_at_startup);
- let mapped = MappedLayer::new(layer.clone(), rules, &config);
+
+ let output_size = output_size(&output);
+ let scale = output.current_scale().fractional_scale();
+
+ let mapped = MappedLayer::new(
+ layer.clone(),
+ rules,
+ output_size,
+ scale,
+ self.niri.clock.clone(),
+ &config,
+ );
+
let prev = self
.niri
.mapped_layer_surfaces
diff --git a/src/layer/mapped.rs b/src/layer/mapped.rs
index 78cfadbf..5eee37fb 100644
--- a/src/layer/mapped.rs
+++ b/src/layer/mapped.rs
@@ -9,12 +9,14 @@ use smithay::utils::{Logical, Point, Scale, Size};
use smithay::wayland::shell::wlr_layer::{ExclusiveZone, Layer};
use super::ResolvedLayerRules;
+use crate::animation::Clock;
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};
+use crate::utils::{baba_is_float_offset, round_logical_in_physical};
#[derive(Debug)]
pub struct MappedLayer {
@@ -29,6 +31,15 @@ pub struct MappedLayer {
/// The shadow around the surface.
shadow: Shadow,
+
+ /// The view size for the layer surface's output.
+ view_size: Size<f64, Logical>,
+
+ /// Scale of the output the layer surface is on (and rounds its sizes to).
+ scale: f64,
+
+ /// Clock for driving animations.
+ clock: Clock,
}
niri_render_elements! {
@@ -40,7 +51,14 @@ niri_render_elements! {
}
impl MappedLayer {
- pub fn new(surface: LayerSurface, rules: ResolvedLayerRules, config: &Config) -> Self {
+ pub fn new(
+ surface: LayerSurface,
+ rules: ResolvedLayerRules,
+ view_size: Size<f64, Logical>,
+ scale: f64,
+ clock: Clock,
+ config: &Config,
+ ) -> Self {
let mut shadow_config = config.layout.shadow;
// Shadows for layer surfaces need to be explicitly enabled.
shadow_config.on = false;
@@ -50,7 +68,10 @@ impl MappedLayer {
surface,
rules,
block_out_buffer: SolidColorBuffer::new((0., 0.), [0., 0., 0., 1.]),
+ view_size,
+ scale,
shadow: Shadow::new(shadow_config),
+ clock,
}
}
@@ -66,16 +87,27 @@ impl MappedLayer {
self.shadow.update_shaders();
}
- pub fn update_render_elements(&mut self, size: Size<f64, Logical>, scale: Scale<f64>) {
+ pub fn update_sizes(&mut self, view_size: Size<f64, Logical>, scale: f64) {
+ self.view_size = view_size;
+ self.scale = scale;
+ }
+
+ pub fn update_render_elements(&mut self, size: Size<f64, Logical>) {
// Round to physical pixels.
- let size = size.to_physical_precise_round(scale).to_logical(scale);
+ let size = size
+ .to_physical_precise_round(self.scale)
+ .to_logical(self.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, 1.);
+ .update_render_elements(size, true, radius, self.scale, 1.);
+ }
+
+ pub fn are_animations_ongoing(&self) -> bool {
+ self.rules.baba_is_float
}
pub fn surface(&self) -> &LayerSurface {
@@ -114,16 +146,27 @@ impl MappedLayer {
true
}
+ pub fn bob_offset(&self) -> Point<f64, Logical> {
+ if !self.rules.baba_is_float {
+ return Point::from((0., 0.));
+ }
+
+ let y = baba_is_float_offset(self.clock.now(), self.view_size.h);
+ let y = round_logical_in_physical(self.scale, y);
+ Point::from((0., y))
+ }
+
pub fn render<R: NiriRenderer>(
&self,
renderer: &mut R,
location: Point<f64, Logical>,
- scale: Scale<f64>,
target: RenderTarget,
) -> SplitElements<LayerSurfaceRenderElement<R>> {
let mut rv = SplitElements::default();
+ let scale = Scale::from(self.scale);
let alpha = self.rules.opacity.unwrap_or(1.).clamp(0., 1.);
+ let location = location + self.bob_offset();
if target.should_block_out(self.rules.block_out_from) {
// Round to physical pixels.
diff --git a/src/layer/mod.rs b/src/layer/mod.rs
index 3b27737c..2ff8b7ca 100644
--- a/src/layer/mod.rs
+++ b/src/layer/mod.rs
@@ -22,6 +22,9 @@ pub struct ResolvedLayerRules {
/// Whether to place this layer surface within the overview backdrop.
pub place_within_backdrop: bool,
+
+ /// Whether to bob this window up and down.
+ pub baba_is_float: bool,
}
impl ResolvedLayerRules {
@@ -41,6 +44,7 @@ impl ResolvedLayerRules {
},
geometry_corner_radius: None,
place_within_backdrop: false,
+ baba_is_float: false,
}
}
@@ -80,6 +84,9 @@ impl ResolvedLayerRules {
if let Some(x) = rule.place_within_backdrop {
resolved.place_within_backdrop = x;
}
+ if let Some(x) = rule.baba_is_float {
+ resolved.baba_is_float = x;
+ }
resolved.shadow.merge_with(&rule.shadow);
}
diff --git a/src/layout/tile.rs b/src/layout/tile.rs
index 454b109c..dea2a773 100644
--- a/src/layout/tile.rs
+++ b/src/layout/tile.rs
@@ -25,8 +25,8 @@ use crate::render_helpers::shadow::ShadowRenderElement;
use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
use crate::render_helpers::RenderTarget;
-use crate::utils::round_logical_in_physical;
use crate::utils::transaction::Transaction;
+use crate::utils::{baba_is_float_offset, round_logical_in_physical};
/// Toplevel window with decorations.
#[derive(Debug)]
@@ -800,9 +800,7 @@ impl<W: LayoutElement> Tile<W> {
return Point::from((0., 0.));
}
- let now = self.clock.now().as_secs_f64();
- let amplitude = self.view_size.h / 96.;
- let y = amplitude * ((f64::consts::TAU * now / 3.6).sin() - 1.);
+ let y = baba_is_float_offset(self.clock.now(), self.view_size.h);
let y = round_logical_in_physical(self.scale, y);
Point::from((0., y))
}
diff --git a/src/niri.rs b/src/niri.rs
index c203eb78..a65687be 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -2896,6 +2896,10 @@ impl Niri {
layer.with_surfaces(|surface, data| {
send_scale_transform(surface, data, scale, transform);
});
+
+ if let Some(mapped) = self.mapped_layer_surfaces.get_mut(layer) {
+ mapped.update_sizes(output_size, scale.fractional_scale());
+ }
}
layer_map.arrange();
}
@@ -2980,8 +2984,12 @@ impl Niri {
.layers_on(layer)
.rev()
.find_map(|layer| {
- let layer_pos_within_output =
+ let mapped = self.mapped_layer_surfaces.get(layer)?;
+
+ let mut layer_pos_within_output =
layers.layer_geometry(layer).unwrap().loc.to_f64();
+ layer_pos_within_output += mapped.bob_offset();
+
let surface_type = if popup {
WindowSurfaceType::POPUP
} else {
@@ -3042,6 +3050,7 @@ impl Niri {
let mut layer_pos_within_output =
layers.layer_geometry(layer_surface).unwrap().loc.to_f64();
+ layer_pos_within_output += mapped.bob_offset();
// Background and bottom layers move together with the workspaces.
let mon = self.layout.monitor_for_output(output)?;
@@ -3197,6 +3206,7 @@ impl Niri {
let mut layer_pos_within_output =
layers.layer_geometry(layer_surface).unwrap().loc.to_f64();
+ layer_pos_within_output += mapped.bob_offset();
// Background and bottom layers move together with the workspaces.
if matches!(layer, Layer::Background | Layer::Bottom) {
@@ -3924,7 +3934,7 @@ impl Niri {
continue;
};
- mapped.update_render_elements(geo.size.to_f64(), scale);
+ mapped.update_render_elements(geo.size.to_f64());
}
}
}
@@ -4077,15 +4087,7 @@ impl Niri {
let layer_map = layer_map_for_output(output);
let mut extend_from_layer =
|elements: &mut SplitElements<LayerSurfaceRenderElement<R>>, layer, for_backdrop| {
- self.render_layer(
- renderer,
- target,
- output_scale,
- &layer_map,
- layer,
- elements,
- for_backdrop,
- );
+ self.render_layer(renderer, target, &layer_map, layer, elements, for_backdrop);
};
// The overlay layer elements go next.
@@ -4205,7 +4207,6 @@ impl Niri {
&self,
renderer: &mut R,
target: RenderTarget,
- scale: Scale<f64>,
layer_map: &LayerMap,
layer: Layer,
elements: &mut SplitElements<LayerSurfaceRenderElement<R>>,
@@ -4223,7 +4224,7 @@ impl Niri {
Some((mapped, geo))
});
for (mapped, geo) in iter {
- elements.extend(mapped.render(renderer, geo.loc.to_f64(), scale, target));
+ elements.extend(mapped.render(renderer, geo.loc.to_f64(), target));
}
}
@@ -4258,6 +4259,14 @@ impl Niri {
.cursor_manager
.is_current_cursor_animated(output.current_scale().integer_scale());
+ // Also check layer surfaces.
+ if !state.unfinished_animations_remain {
+ state.unfinished_animations_remain |= layer_map_for_output(output)
+ .layers()
+ .filter_map(|surface| self.mapped_layer_surfaces.get(surface))
+ .any(|mapped| mapped.are_animations_ongoing());
+ }
+
// Render.
res = backend.render(self, output, target_presentation_time);
}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index c1e57b7b..2ac37721 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,4 +1,5 @@
use std::cmp::{max, min};
+use std::f64;
use std::ffi::{CString, OsStr};
use std::io::Write;
use std::os::unix::prelude::OsStrExt;
@@ -396,6 +397,12 @@ pub fn center_preferring_top_left_in_area(
area.loc + offset
}
+pub fn baba_is_float_offset(now: Duration, view_height: f64) -> f64 {
+ let now = now.as_secs_f64();
+ let amplitude = view_height / 96.;
+ amplitude * ((f64::consts::TAU * now / 3.6).sin() - 1.)
+}
+
#[cfg(feature = "dbus")]
pub fn show_screenshot_notification(image_path: Option<PathBuf>) -> anyhow::Result<()> {
use std::collections::HashMap;