diff --git a/crates/gpui3/src/app.rs b/crates/gpui3/src/app.rs index 9a58112e00..7a79f53a5a 100644 --- a/crates/gpui3/src/app.rs +++ b/crates/gpui3/src/app.rs @@ -8,9 +8,9 @@ pub use model_context::*; use refineable::Refineable; use crate::{ - current_platform, image_cache::ImageCache, AssetSource, Context, DisplayLinker, Executor, - LayoutId, MainThread, MainThreadOnly, Platform, RootView, SvgRenderer, Task, TextStyle, - TextStyleRefinement, TextSystem, Window, WindowContext, WindowHandle, WindowId, + current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor, LayoutId, + MainThread, MainThreadOnly, Platform, PlatformDisplayLinker, RootView, SvgRenderer, Task, + TextStyle, TextStyleRefinement, TextSystem, Window, WindowContext, WindowHandle, WindowId, }; use anyhow::{anyhow, Result}; use collections::{HashMap, VecDeque}; @@ -56,13 +56,14 @@ impl App { Self(Arc::new_cyclic(|this| { Mutex::new(AppContext { this: this.clone(), - display_linker: Arc::new(DisplayLinker::new(platform.display_linker())), text_system: Arc::new(TextSystem::new(platform.text_system())), + pending_updates: 0, + display_linker: platform.display_linker(), + next_frame_callbacks: Default::default(), platform: MainThreadOnly::new(platform, executor.clone()), executor, svg_renderer: SvgRenderer::new(asset_source), image_cache: ImageCache::new(http_client), - pending_updates: 0, text_style_stack: Vec::new(), state_stacks_by_type: HashMap::default(), unit_entity, @@ -90,14 +91,16 @@ impl App { } type Handlers = SmallVec<[Arc bool + Send + Sync + 'static>; 2]>; +type FrameCallback = Box; pub struct AppContext { this: Weak>, platform: MainThreadOnly, text_system: Arc, pending_updates: usize, + pub(crate) display_linker: Arc, + pub(crate) next_frame_callbacks: HashMap>, pub(crate) executor: Executor, - pub(crate) display_linker: Arc, pub(crate) svg_renderer: SvgRenderer, pub(crate) image_cache: ImageCache, pub(crate) text_style_stack: Vec, @@ -146,7 +149,6 @@ impl AppContext { } fn flush_effects(&mut self) { - dbg!("flush effects"); while let Some(effect) = self.pending_effects.pop_front() { match effect { Effect::Notify(entity_id) => self.apply_notify_effect(entity_id), diff --git a/crates/gpui3/src/display_linker.rs b/crates/gpui3/src/display_linker.rs deleted file mode 100644 index 54954b15b6..0000000000 --- a/crates/gpui3/src/display_linker.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::{DisplayId, PlatformDisplayLinker, VideoTimestamp}; -use collections::HashMap; -use parking_lot::Mutex; -use std::sync::Arc; - -type FrameCallback = Box; - -pub struct DisplayLinker { - platform_linker: Arc, - next_frame_callbacks: Arc>>>, -} - -impl DisplayLinker { - pub(crate) fn new(platform_linker: Arc) -> Self { - Self { - platform_linker, - next_frame_callbacks: Default::default(), - } - } - - pub(crate) fn on_next_frame( - &self, - display_id: DisplayId, - callback: impl FnOnce(&VideoTimestamp, &VideoTimestamp) + Send + 'static, - ) { - let next_frame_callbacks = self.next_frame_callbacks.clone(); - let callback = Box::new(callback); - match self.next_frame_callbacks.lock().entry(display_id) { - collections::hash_map::Entry::Occupied(mut entry) => { - if entry.get().is_empty() { - self.platform_linker.start(display_id); - } - entry.get_mut().push(callback) - } - collections::hash_map::Entry::Vacant(entry) => { - // let platform_linker = self.platform_linker.clone(); - self.platform_linker.set_output_callback( - display_id, - Box::new(move |current_time, output_time| { - for callback in next_frame_callbacks - .lock() - .get_mut(&display_id) - .unwrap() - .drain(..) - { - callback(current_time, output_time); - } - // platform_linker.stop(display_id); - }), - ); - self.platform_linker.start(display_id); - entry.insert(vec![callback]); - } - } - } -} diff --git a/crates/gpui3/src/elements/img.rs b/crates/gpui3/src/elements/img.rs index 29ddcc3702..49ed91fbde 100644 --- a/crates/gpui3/src/elements/img.rs +++ b/crates/gpui3/src/elements/img.rs @@ -77,9 +77,7 @@ impl Element for Img { } else { cx.spawn(|_, mut cx| async move { if image_future.await.log_err().is_some() { - cx.on_next_frame(|cx| { - cx.notify(); - }); + cx.on_next_frame(|cx| cx.notify()); } }) .detach() diff --git a/crates/gpui3/src/gpui3.rs b/crates/gpui3/src/gpui3.rs index e8276488e4..92a8043b7c 100644 --- a/crates/gpui3/src/gpui3.rs +++ b/crates/gpui3/src/gpui3.rs @@ -1,7 +1,6 @@ mod app; mod assets; mod color; -mod display_linker; mod element; mod elements; mod executor; @@ -23,7 +22,6 @@ pub use anyhow::Result; pub use app::*; pub use assets::*; pub use color::*; -pub use display_linker::*; pub use element::*; pub use elements::*; pub use executor::*; diff --git a/crates/gpui3/src/platform/mac/metal_renderer.rs b/crates/gpui3/src/platform/mac/metal_renderer.rs index 84a5fd5126..a018aad762 100644 --- a/crates/gpui3/src/platform/mac/metal_renderer.rs +++ b/crates/gpui3/src/platform/mac/metal_renderer.rs @@ -131,8 +131,6 @@ impl MetalRenderer { } pub fn draw(&mut self, scene: &mut Scene) { - dbg!("draw scene"); - let layer = self.layer.clone(); let viewport_size = layer.drawable_size(); let viewport_size: Size = size( diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index 7e3c5d3ce5..1b15cae691 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -144,11 +144,42 @@ impl<'a, 'w> WindowContext<'a, 'w> { } pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) { - let cx = self.to_async(); + let f = Box::new(f); let display_id = self.window.display_id; - self.display_linker.on_next_frame(display_id, move |_, _| { - cx.update(f).ok(); - }); + let async_cx = self.to_async(); + let app_cx = self.app_mut(); + match app_cx.next_frame_callbacks.entry(display_id) { + collections::hash_map::Entry::Occupied(mut entry) => { + if entry.get().is_empty() { + app_cx.display_linker.start(display_id); + } + entry.get_mut().push(f); + } + collections::hash_map::Entry::Vacant(entry) => { + app_cx.display_linker.set_output_callback( + display_id, + Box::new(move |_current_time, _output_time| { + let _ = async_cx.update(|cx| { + let callbacks = cx + .next_frame_callbacks + .get_mut(&display_id) + .unwrap() + .drain(..) + .collect::>(); + for callback in callbacks { + callback(cx); + } + + if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() { + cx.display_linker.stop(display_id); + } + }); + }), + ); + app_cx.display_linker.start(display_id); + entry.insert(vec![f]); + } + } } pub fn spawn( @@ -590,11 +621,9 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> { } pub fn on_next_frame(&mut self, f: impl FnOnce(&mut S, &mut ViewContext) + Send + 'static) { - let mut cx = self.to_async(); let entity = self.handle(); - let display_id = self.window.display_id; - self.display_linker.on_next_frame(display_id, move |_, _| { - entity.update(&mut cx, f).ok(); + self.window_cx.on_next_frame(move |cx| { + entity.update(cx, f).ok(); }); }