Commit 82c94edb8c50
tarball5 files changed+60-25
@@ -6,8 +6,7 @@ use monolith_config::{Animation, AnimationStyle};
66
use monolith_layout::{OutputId, Rect, WindowId};77
use monolith_motion::{CubicBezier, Edges, Position, Timeline, group_initial_slope};88
use monolith_planner::{Config as PlanConfig, Plan, Style};9
-use monolith_render_vk::{Effect, Transition, VulkanTexture};10
-use smithay::utils::{Logical, Rectangle, Transform};9
+use monolith_render_vk::{Effect, Transition};1110
use std::collections::HashMap;1211
1312
const VELOCITY_DT_NS: u64 = 1_000_000;@@ -21,16 +20,11 @@ pub struct Animator {
2120
}2221
2322
/// A closed tiled window that stays in its output's plan, shrinking to24
-/// `seed` with the last frame its client showed.23
+/// `seed`. `Wm::last_frames` holds what it shows.2524
pub struct Ghost {2625
pub id: WindowId,2726
pub output: OutputId,2827
pub seed: Rect,29
- pub texture: VulkanTexture,30
- pub scale: i32,31
- pub transform: Transform,32
- /// Window geometry inside the buffer.33
- pub geometry: Rectangle<i32, Logical>,3428
pub born: u64,3529
}3630
@@ -44,7 +44,12 @@ pub fn build(
4444
output: Option<&Output>,4545
unmanaged: &[X11Surface],4646
) -> Vec<Draw> {47
- let (layout, anim, windows) = wm.parts();47
+ let crate::wm::Parts {48
+ layout,49
+ anim,50
+ windows,51
+ last_frames,52
+ } = wm.parts();4853
let Some(area) = layout.output(o).map(|out| out.area) else {4954
return Vec::new();5055
};@@ -53,8 +58,8 @@ pub fn build(
5358
let mut tiled = Vec::new();5459
let mut above = Vec::new();5560
for g in anim.ghosts().iter().filter(|g| g.output == o) {56
- if let Some(r) = anim.tiled(o, g.id, now) {57
- ghosts.push((g, local(r)));61
+ if let (Some(r), Some(frame)) = (anim.tiled(o, g.id, now), last_frames.get(&g.id)) {62
+ ghosts.push((g, frame, local(r)));5863
}5964
}6065
let arr = layout.arrange(o);@@ -118,18 +123,18 @@ pub fn build(
118123
border_elements(&mut out, borders, r, deco.border as i32, color, alpha);119124
}120125
}121
- for (g, r) in ghosts.into_iter().rev() {126
+ for (g, frame, r) in ghosts.into_iter().rev() {122127
let Some((at, size)) = pixels(r) else {123128
continue;124129
};125130
let src = Rectangle::new(126
- g.geometry.loc.to_f64(),131
+ frame.geometry.loc.to_f64(),127132
(f64::from(size.0), f64::from(size.1)).into(),128133
);129134
out.push(Draw::Effect(EffectElement::new(130
- &g.texture,131
- g.scale,132
- g.transform,135
+ &frame.texture,136
+ frame.scale,137
+ frame.transform,133138
src,134139
at,135140
size,@@ -197,7 +197,7 @@ impl State {
197197
crate::backend::Backend::Nested(_) => crate::nested::render(self),198198
crate::backend::Backend::Starting => {}199199
}200
- self.wm.anim.prune(now_ns());200
+ self.wm.prune(now_ns());201201
self.confirm_lock();202202
self.complete_captures();203203
if std::mem::take(&mut self.dirty.snapshot) {@@ -1,6 +1,6 @@
11
use crate::anim::Ghost;22
use crate::state::{State, now_ns};3
-use crate::wm::{identity, root};3
+use crate::wm::{LastFrame, identity, root};44
use monolith_layout::{Rect, WindowId};55
use monolith_render_vk::VulkanTexture;66
use smithay::backend::renderer::Renderer;@@ -157,14 +157,19 @@ impl State {
157157
})158158
.flatten();159159
if let Some((texture, scale, transform)) = snapshot {160
+ self.wm.last_frames.insert(161
+ id,162
+ LastFrame {163
+ texture,164
+ scale,165
+ transform,166
+ geometry: window.geometry(),167
+ },168
+ );160169
self.wm.anim.add_ghost(Ghost {161170
id,162171
output: o,163172
seed: seed.rect,164
- texture,165
- scale,166
- transform,167
- geometry: window.geometry(),168173
born: now_ns(),169174
});170175
}@@ -4,12 +4,13 @@
44
use crate::anim::Animator;55
66
use monolith_layout::{Layout, OutputId, Rect, WindowId};7
+use monolith_render_vk::VulkanTexture;78
use slotmap::SecondaryMap;89
use smithay::backend::renderer::element::solid::SolidColorBuffer;910
use smithay::desktop::{PopupManager, Space, Window};1011
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::State as XdgState;1112
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;12
-use smithay::utils::Rectangle;13
+use smithay::utils::{Logical, Rectangle, Transform};1314
use smithay::wayland::compositor::with_states;1415
use smithay::wayland::foreign_toplevel_list::ForeignToplevelHandle;1516
use smithay::wayland::seat::WaylandFocus;@@ -28,6 +29,23 @@ pub struct Wm {
2829
pub anim: Animator,2930
/// A layer surface given the keyboard by a click, like a launcher.3031
pub layer_focus: Option<WlSurface>,32
+ /// What closed windows still show while their ghost animates.33
+ pub last_frames: HashMap<WindowId, LastFrame>,34
+}35
+36
+pub struct LastFrame {37
+ pub texture: VulkanTexture,38
+ pub scale: i32,39
+ pub transform: Transform,40
+ /// Window geometry inside the buffer.41
+ pub geometry: Rectangle<i32, Logical>,42
+}43
+44
+pub struct Parts<'a> {45
+ pub layout: &'a Layout,46
+ pub anim: &'a Animator,47
+ pub windows: &'a mut SecondaryMap<WindowId, WindowState>,48
+ pub last_frames: &'a HashMap<WindowId, LastFrame>,3149
}3250
3351
pub struct WindowState {@@ -74,6 +92,7 @@ impl Wm {
7492
popups: PopupManager::default(),7593
anim,7694
layer_focus: None,95
+ last_frames: HashMap::new(),7796
}7897
}7998
@@ -152,8 +171,20 @@ impl Wm {
152171
153172
/// The layout and animator to read alongside the records to write, which154173
/// a frame needs at once.155
- pub fn parts(&mut self) -> (&Layout, &Animator, &mut SecondaryMap<WindowId, WindowState>) {156
- (&self.layout, &self.anim, &mut self.windows)174
+ pub fn parts(&mut self) -> Parts<'_> {175
+ Parts {176
+ layout: &self.layout,177
+ anim: &self.anim,178
+ windows: &mut self.windows,179
+ last_frames: &self.last_frames,180
+ }181
+ }182
+183
+ pub fn prune(&mut self, now: u64) {184
+ self.anim.prune(now);185
+ let ghosts = self.anim.ghosts();186
+ self.last_frames187
+ .retain(|id, _| ghosts.iter().any(|g| g.id == *id));157188
}158189
159190
pub fn any_awaiting(&self) -> bool {