tiling: Refactor blocker code

This commit is contained in:
Victoria Brekenfeld 2025-01-15 19:57:04 +01:00 • committed by Victoria Brekenfeld
parent 560d234036
commit 75661c6ca7
2 changed files with 25 additions and 41 deletions

View file

@ -9,25 +9,18 @@ use smithay::{
}; };
use std::{ use std::{
collections::HashMap, collections::HashMap,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::{Duration, Instant}, time::{Duration, Instant},
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TilingBlocker { pub struct TilingBlocker {
pub necessary_acks: Vec<(CosmicSurface, Serial)>, pub necessary_acks: Vec<(CosmicSurface, Serial)>,
ready: Arc<AtomicBool>,
signaled: Arc<AtomicBool>,
start: Instant, start: Instant,
} }
impl Blocker for TilingBlocker { impl Blocker for TilingBlocker {
fn state(&self) -> BlockerState { fn state(&self) -> BlockerState {
self.signaled.store(true, Ordering::SeqCst); if self.is_ready() {
if self.ready.load(Ordering::SeqCst) {
BlockerState::Released BlockerState::Released
} else { } else {
BlockerState::Pending BlockerState::Pending
@ -39,8 +32,6 @@ impl TilingBlocker {
pub fn new(configures: impl IntoIterator<Item = (CosmicSurface, Serial)>) -> Self { pub fn new(configures: impl IntoIterator<Item = (CosmicSurface, Serial)>) -> Self {
TilingBlocker { TilingBlocker {
necessary_acks: configures.into_iter().collect(), necessary_acks: configures.into_iter().collect(),
ready: Arc::new(AtomicBool::new(false)),
signaled: Arc::new(AtomicBool::new(false)),
start: Instant::now(), start: Instant::now(),
} }
} }
@ -53,14 +44,15 @@ impl TilingBlocker {
.all(|(surf, serial)| !surf.alive() || surf.serial_acked(serial)) .all(|(surf, serial)| !surf.alive() || surf.serial_acked(serial))
} }
pub fn is_signaled(&self) -> bool { pub fn is_processed(&self) -> bool {
self.signaled.load(Ordering::SeqCst) Instant::now().duration_since(self.start) >= Duration::from_millis(500)
|| !self.necessary_acks.iter().any(|(surf, _)| surf.alive()) || self
.necessary_acks
.iter()
.all(|(surf, serial)| !surf.alive() || surf.serial_past(serial))
} }
#[must_use] pub fn clients(&self) -> HashMap<ClientId, Client> {
pub fn signal_ready(&self) -> HashMap<ClientId, Client> {
self.ready.swap(true, Ordering::SeqCst);
self.necessary_acks self.necessary_acks
.iter() .iter()
.flat_map(|(surface, _)| surface.wl_surface().and_then(|s| s.client())) .flat_map(|(surface, _)| surface.wl_surface().and_then(|s| s.client()))

View file

@ -130,7 +130,6 @@ impl TreeQueue {
pub struct TilingLayout { pub struct TilingLayout {
output: Output, output: Output,
queue: TreeQueue, queue: TreeQueue,
pending_blockers: Vec<TilingBlocker>,
placeholder_id: Id, placeholder_id: Id,
swapping_stack_surface_id: Id, swapping_stack_surface_id: Id,
last_overview_hover: Option<(Option<Instant>, TargetZone)>, last_overview_hover: Option<(Option<Instant>, TargetZone)>,
@ -353,7 +352,6 @@ impl TilingLayout {
animation_start: None, animation_start: None,
}, },
output: output.clone(), output: output.clone(),
pending_blockers: Vec::new(),
placeholder_id: Id::new(), placeholder_id: Id::new(),
swapping_stack_surface_id: Id::new(), swapping_stack_surface_id: Id::new(),
last_overview_hover: None, last_overview_hover: None,
@ -2345,8 +2343,20 @@ impl TilingLayout {
pub fn update_animation_state(&mut self) -> HashMap<ClientId, Client> { pub fn update_animation_state(&mut self) -> HashMap<ClientId, Client> {
let mut clients = HashMap::new(); let mut clients = HashMap::new();
for blocker in self.pending_blockers.drain(..) { let mut ready_trees = 0;
clients.extend(blocker.signal_ready()); for (_, _, blocker) in self.queue.trees.iter().skip(1) {
if let Some(blocker) = blocker.as_ref() {
if blocker.is_processed() {
ready_trees += 1;
}
if blocker.is_ready() {
clients.extend(blocker.clients());
continue;
}
break;
} else {
ready_trees += 1;
}
} }
if let Some(start) = self.queue.animation_start { if let Some(start) = self.queue.animation_start {
@ -2361,6 +2371,7 @@ impl TilingLayout {
{ {
let _ = self.queue.animation_start.take(); let _ = self.queue.animation_start.take();
let _ = self.queue.trees.pop_front(); let _ = self.queue.trees.pop_front();
ready_trees -= 1;
let front = self.queue.trees.front_mut().unwrap(); let front = self.queue.trees.front_mut().unwrap();
if let Some(root_id) = front.0.root_node_id() { if let Some(root_id) = front.0.root_node_id() {
for node in front for node in front
@ -2383,28 +2394,12 @@ impl TilingLayout {
} }
} }
let ready_trees = self
.queue
.trees
.iter()
.skip(1)
.take_while(|(_, _, blocker)| {
blocker
.as_ref()
.map(|blocker| blocker.is_ready() && blocker.is_signaled())
.unwrap_or(true)
})
.count();
// merge // merge
let other_duration = if ready_trees > 1 { let other_duration = if ready_trees > 1 {
self.queue self.queue
.trees .trees
.drain(1..ready_trees) .drain(1..ready_trees)
.fold(None, |res, (_, duration, blocker)| { .fold(None, |res, (_, duration, _)| {
if let Some(blocker) = blocker {
clients.extend(blocker.signal_ready());
}
Some( Some(
res.map(|old_duration: Duration| old_duration.max(duration)) res.map(|old_duration: Duration| old_duration.max(duration))
.unwrap_or(duration), .unwrap_or(duration),
@ -2416,13 +2411,10 @@ impl TilingLayout {
// start // start
if ready_trees > 0 { if ready_trees > 0 {
let (_, duration, blocker) = self.queue.trees.get_mut(1).unwrap(); let (_, duration, _) = self.queue.trees.get_mut(1).unwrap();
*duration = other_duration *duration = other_duration
.map(|other| other.max(*duration)) .map(|other| other.max(*duration))
.unwrap_or(*duration); .unwrap_or(*duration);
if let Some(blocker) = blocker {
clients.extend(blocker.signal_ready());
}
self.queue.animation_start = Some(Instant::now()); self.queue.animation_start = Some(Instant::now());
} }