Merge remote-tracking branch 'origin/main' into zed2-workspace
This commit is contained in:
commit
269a72464d
128 changed files with 1718 additions and 1670 deletions
|
@ -13,7 +13,10 @@ use crate::{
|
|||
use anyhow::{anyhow, Result};
|
||||
use collections::HashMap;
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use futures::channel::oneshot;
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
StreamExt,
|
||||
};
|
||||
use parking_lot::RwLock;
|
||||
use slotmap::SlotMap;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -443,42 +446,55 @@ impl<'a> WindowContext<'a> {
|
|||
}
|
||||
|
||||
/// Schedule the given closure to be run directly after the current frame is rendered.
|
||||
pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
|
||||
let f = Box::new(f);
|
||||
pub fn on_next_frame(&mut self, callback: impl FnOnce(&mut WindowContext) + 'static) {
|
||||
let handle = self.window.handle;
|
||||
let display_id = self.window.display_id;
|
||||
|
||||
if let Some(callbacks) = self.next_frame_callbacks.get_mut(&display_id) {
|
||||
callbacks.push(f);
|
||||
// If there was already a callback, it means that we already scheduled a frame.
|
||||
if callbacks.len() > 1 {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let mut async_cx = self.to_async();
|
||||
self.next_frame_callbacks.insert(display_id, vec![f]);
|
||||
if !self.frame_consumers.contains_key(&display_id) {
|
||||
let (tx, mut rx) = mpsc::unbounded::<()>();
|
||||
self.platform.set_display_link_output_callback(
|
||||
display_id,
|
||||
Box::new(move |_current_time, _output_time| {
|
||||
let _ = async_cx.update(|_, cx| {
|
||||
let callbacks = cx
|
||||
Box::new(move |_current_time, _output_time| _ = tx.unbounded_send(())),
|
||||
);
|
||||
|
||||
let consumer_task = self.app.spawn(|cx| async move {
|
||||
while rx.next().await.is_some() {
|
||||
cx.update(|cx| {
|
||||
for callback in cx
|
||||
.next_frame_callbacks
|
||||
.get_mut(&display_id)
|
||||
.unwrap()
|
||||
.drain(..)
|
||||
.collect::<Vec<_>>();
|
||||
for callback in callbacks {
|
||||
.collect::<SmallVec<[_; 32]>>()
|
||||
{
|
||||
callback(cx);
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
|
||||
if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {
|
||||
// Flush effects, then stop the display link if no new next_frame_callbacks have been added.
|
||||
|
||||
cx.update(|cx| {
|
||||
if cx.next_frame_callbacks.is_empty() {
|
||||
cx.platform.stop_display_link(display_id);
|
||||
}
|
||||
});
|
||||
}),
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
});
|
||||
self.frame_consumers.insert(display_id, consumer_task);
|
||||
}
|
||||
|
||||
self.platform.start_display_link(display_id);
|
||||
if self.next_frame_callbacks.is_empty() {
|
||||
self.platform.start_display_link(display_id);
|
||||
}
|
||||
|
||||
self.next_frame_callbacks
|
||||
.entry(display_id)
|
||||
.or_default()
|
||||
.push(Box::new(move |cx: &mut AppContext| {
|
||||
cx.update_window(handle, |_root_view, cx| callback(cx)).ok();
|
||||
}));
|
||||
}
|
||||
|
||||
/// Spawn the future returned by the given closure on the application thread pool.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue