Commit bbe43ba0672c
tarball3 files changed+63-2
@@ -29,6 +29,9 @@ pub struct Ghost {
2929
/// Fades where it is for one phase instead of shrinking in the plan,3030
/// like a dismissed scratchpad.3131
pub fixed: Option<Rect>,32
+ /// Fades as it goes. A window sent to another output leaves one that33
+ /// slides off without fading, since the window lives on over there.34
+ pub closing: bool,3235
pub opacity: f32,3336
}3437
@@ -221,7 +224,11 @@ impl Animator {
221224
222225
pub fn ghost_effect(&self, g: &Ghost, now: u64) -> Effect {223226
Effect {224
- kind: Transition::Close,227
+ kind: if g.closing {228
+ Transition::Close229
+ } else {230
+ Transition::Move231
+ },225232
progress: self.progress(g.born, now).unwrap_or(1.0),226233
}227234
}@@ -72,6 +72,7 @@ impl State {
7272
seed: seed.rect,7373
born: now_ns(),7474
fixed: None,75
+ closing: true,7576
opacity,7677
});7778
}@@ -92,6 +93,28 @@ impl State {
9293
seed: rect,9394
born: now_ns(),9495
fixed: Some(rect),96
+ closing: true,97
+ opacity,98
+ });99
+ }100
+ }101
+102
+ /// Slides a tiled window sent to another output off the one it left,103
+ /// towards where it lands.104
+ pub(crate) fn slide_out(&mut self, id: WindowId, output: OutputId, to: Rect) {105
+ let Some(window) = self.wm.window(id).cloned() else {106
+ return;107
+ };108
+ let opacity = self.wm.get(id).and_then(|s| s.rule.opacity).unwrap_or(1.0);109
+ if let Some(frame) = self.last_frame(&window) {110
+ self.wm.last_frames.insert(id, frame);111
+ self.wm.anim.add_ghost(Ghost {112
+ id,113
+ output,114
+ seed: to,115
+ born: now_ns(),116
+ fixed: None,117
+ closing: false,95118
opacity,96119
});97120
}@@ -377,6 +377,28 @@ impl State {
377377
_ => {}378378
}379379
}380
+ let sent: Vec<(WindowId, OutputId, Rect, Rect)> = tracks381
+ .iter()382
+ .flat_map(|(o, targets)| targets.iter().map(move |&(id, to)| (*o, id, to)))383
+ .filter_map(|(o, id, to)| match self.wm.get(id)?.placed? {384
+ (Kind::Tiled, rect, was) if was != o => {385
+ let from = self.wm.anim.tiled(was, id, now).unwrap_or(rect);386
+ Some((id, was, from, to))387
+ }388
+ _ => None,389
+ })390
+ .collect();391
+ let empty = |o: OutputId| {392
+ tracks393
+ .iter()394
+ .filter(|t| t.0 == o)395
+ .flat_map(|t| &t.1)396
+ .all(|&(_, r)| r.w <= 0.0 || r.h <= 0.0)397
+ };398
+ let leaving: Vec<_> = sent.iter().filter(|s| empty(s.1)).copied().collect();399
+ for (id, was, _, to) in leaving {400
+ self.slide_out(id, was, to);401
+ }380402
let gap = self.wm.layout.gaps.inner;381403
for (o, targets) in tracks {382404
let new: Vec<WindowId> = targets@@ -395,8 +417,17 @@ impl State {
395417
.map(|p| (p.window, p.rect))396418
.collect()397419
};420
+ let alone = |id| {421
+ targets422
+ .iter()423
+ .all(|&(t, r)| t == id || r.w <= 0.0 || r.h <= 0.0)424
+ };398425
self.wm.anim.retarget(o, now, &targets, gap, |id| {399
- seeds.get(&id).copied().unwrap_or_default()426
+ sent.iter()427
+ .find(|s| s.0 == id && alone(id))428
+ .map(|s| s.2)429
+ .or_else(|| seeds.get(&id).copied())430
+ .unwrap_or_default()400431
});401432
}402433
for (id, from, to) in glides {