diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-03-01 09:45:57 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-03-10 07:59:14 +0300 |
| commit | 88614c08fe0a7833cbb749a6ecf3e703eb373c6e (patch) | |
| tree | f8dfa7b6b1802a355eb42fb7abc0f46a224928c1 /src/layout | |
| parent | 4f5c8e745bec6395105138c83468bccb4ab27ea9 (diff) | |
| download | niri-88614c08fe0a7833cbb749a6ecf3e703eb373c6e.tar.gz niri-88614c08fe0a7833cbb749a6ecf3e703eb373c6e.tar.bz2 niri-88614c08fe0a7833cbb749a6ecf3e703eb373c6e.zip | |
Make interactively moved window semitransparent
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/mod.rs | 65 | ||||
| -rw-r--r-- | src/layout/tile.rs | 20 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 5 |
3 files changed, 87 insertions, 3 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 43c1631d..ac83a0cf 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -93,6 +93,9 @@ pub const RESIZE_ANIMATION_THRESHOLD: f64 = 10.; /// Pointer needs to move this far to pull a window from the layout. const INTERACTIVE_MOVE_START_THRESHOLD: f64 = 256. * 256.; +/// Opacity of interactively moved tiles targeting the scrolling layout. +const INTERACTIVE_MOVE_ALPHA: f64 = 0.75; + /// Size-relative units. pub struct SizeFrac; @@ -2334,6 +2337,34 @@ impl<W: LayoutElement> Layout<W> { // Tile position must be rounded to physical pixels. assert_abs_diff_eq!(tile_pos.x, rounded_pos.x, epsilon = 1e-5); assert_abs_diff_eq!(tile_pos.y, rounded_pos.y, epsilon = 1e-5); + + if let Some(alpha) = &move_.tile.alpha_animation { + if move_.is_floating { + assert_eq!( + alpha.anim.to(), + 1., + "interactively moved floating tile can animate alpha only to 1" + ); + + assert!( + !alpha.hold_after_done, + "interactively moved floating tile \ + cannot have held alpha animation" + ); + } else { + assert_ne!( + alpha.anim.to(), + 1., + "interactively moved scrolling tile must animate alpha to not 1" + ); + + assert!( + alpha.hold_after_done, + "interactively moved scrolling tile \ + must have held alpha animation" + ); + } + } } } } @@ -3005,6 +3036,21 @@ impl<W: LayoutElement> Layout<W> { size.h = ensure_min_max_size_maybe_zero(size.h, min_size.h, max_size.h); win.request_size_once(size, true); + + // Animate the tile back to opaque. + move_.tile.animate_alpha( + INTERACTIVE_MOVE_ALPHA, + 1., + self.options.animations.window_movement.0, + ); + } else { + // Animate the tile back to semitransparent. + move_.tile.animate_alpha( + 1., + INTERACTIVE_MOVE_ALPHA, + self.options.animations.window_movement.0, + ); + move_.tile.hold_alpha_animation_after_done(); } return; @@ -3773,6 +3819,16 @@ impl<W: LayoutElement> Layout<W> { is_floating = unfullscreen_to_floating; } + // Animate to semitransparent. + if !is_floating { + tile.animate_alpha( + 1., + INTERACTIVE_MOVE_ALPHA, + self.options.animations.window_movement.0, + ); + tile.hold_alpha_animation_after_done(); + } + let mut data = InteractiveMoveData { tile, output, @@ -3869,7 +3925,7 @@ impl<W: LayoutElement> Layout<W> { return; } - let Some(InteractiveMoveState::Moving(move_)) = self.interactive_move.take() else { + let Some(InteractiveMoveState::Moving(mut move_)) = self.interactive_move.take() else { unreachable!() }; @@ -3878,6 +3934,13 @@ impl<W: LayoutElement> Layout<W> { for ws in self.workspaces_mut() { ws.dnd_scroll_gesture_end(); } + + // Also animate the tile back to opaque. + move_.tile.animate_alpha( + INTERACTIVE_MOVE_ALPHA, + 1., + self.options.animations.window_movement.0, + ); } match &mut self.monitor_set { diff --git a/src/layout/tile.rs b/src/layout/tile.rs index 71aa33a1..a93e4a6f 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -148,6 +148,12 @@ struct MoveAnimation { #[derive(Debug)] pub(super) struct AlphaAnimation { pub(super) anim: Animation, + /// Whether the animation should persist after it's done. + /// + /// This is used by things like interactive move which need to animate alpha to + /// semitransparent, then hold it at semitransparent for a while, until the operation + /// completes. + pub(super) hold_after_done: bool, offscreen: OffscreenBuffer, } @@ -319,7 +325,7 @@ impl<W: LayoutElement> Tile<W> { } if let Some(alpha) = &mut self.alpha_animation { - if alpha.anim.is_done() { + if !alpha.hold_after_done && alpha.anim.is_done() { self.alpha_animation = None; } } @@ -334,7 +340,10 @@ impl<W: LayoutElement> Tile<W> { || self.resize_animation.is_some() || self.move_x_animation.is_some() || self.move_y_animation.is_some() - || self.alpha_animation.is_some() + || self + .alpha_animation + .as_ref() + .is_some_and(|alpha| !alpha.anim.is_done()) } pub fn update_render_elements(&mut self, is_active: bool, view_rect: Rectangle<f64, Logical>) { @@ -491,6 +500,7 @@ impl<W: LayoutElement> Tile<W> { self.alpha_animation = Some(AlphaAnimation { anim: Animation::new(self.clock.clone(), current, to, 0., config), + hold_after_done: false, offscreen, }); } @@ -505,6 +515,12 @@ impl<W: LayoutElement> Tile<W> { } } + pub fn hold_alpha_animation_after_done(&mut self) { + if let Some(alpha) = &mut self.alpha_animation { + alpha.hold_after_done = true; + } + } + pub fn window(&self) -> &W { &self.window } diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 0e4c1af5..1cb55233 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -1757,6 +1757,11 @@ impl<W: LayoutElement> Workspace<W> { if visible { assert_eq!(anim.to(), 1., "visible tiles can animate alpha only to 1"); } + + assert!( + !alpha.hold_after_done, + "tiles in the layout cannot have held alpha animation" + ); } } } |
