diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/layer_shell.rs | 17 | ||||
| -rw-r--r-- | src/layer/mapped.rs | 53 | ||||
| -rw-r--r-- | src/layer/mod.rs | 7 | ||||
| -rw-r--r-- | src/layout/tile.rs | 6 | ||||
| -rw-r--r-- | src/niri.rs | 35 | ||||
| -rw-r--r-- | src/utils/mod.rs | 7 |
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; |
