use std::{
collections::HashMap,
sync::atomic::{AtomicU64, Ordering},
};
use gpui::{App, Bounds, Global, IntoElement, Pixels, Styled, Window, WindowId, canvas};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Mark(u64);
pub fn cover() -> impl IntoElement {
canvas(record, |_, _, _, _| {}).absolute().size_full()
}
pub fn record(bounds: Bounds<Pixels>, window: &mut Window, cx: &mut App) {
let bounds = bounds.intersect(&window.content_mask().bounds);
let mark = next();
let id = window.window_handle().window_id();
let covers = cx.default_global::<Covers>();
if let Some(frame) = covers.0.get_mut(&id) {
frame.push((mark, bounds));
return;
}
covers.0.insert(id, vec![(mark, bounds)]);
window.on_next_frame(move |_, cx| {
cx.default_global::<Covers>().0.remove(&id);
});
}
pub fn mark() -> Mark {
next()
}
pub fn covered(mark: Mark, bounds: Bounds<Pixels>, window: &Window, cx: &App) -> bool {
cx.try_global::<Covers>()
.and_then(|covers| covers.0.get(&window.window_handle().window_id()))
.is_some_and(|frame| {
frame
.iter()
.any(|(at, cover)| *at > mark && cover.intersects(&bounds))
})
}
fn next() -> Mark {
static NEXT: AtomicU64 = AtomicU64::new(1);
Mark(NEXT.fetch_add(1, Ordering::Relaxed))
}
#[derive(Default)]
struct Covers(HashMap<WindowId, Vec<(Mark, Bounds<Pixels>)>>);
impl Global for Covers {}