From 77b9a7aa5a19eaf3a8856c2ac8f118381f8d607a Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 4 Oct 2023 23:59:21 -0600 Subject: [PATCH] Checkpoint --- crates/gpui3/src/app.rs | 6 --- crates/gpui3/src/display_linker.rs | 3 +- .../gpui3/src/platform/mac/display_linker.rs | 42 ++++++++++--------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/crates/gpui3/src/app.rs b/crates/gpui3/src/app.rs index ec212c7a68..805f7b24f0 100644 --- a/crates/gpui3/src/app.rs +++ b/crates/gpui3/src/app.rs @@ -146,7 +146,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), @@ -364,11 +363,6 @@ impl MainThread { let root_view = build_root_view(&mut WindowContext::mutable(cx, &mut window)); window.root_view.replace(root_view.into_any()); cx.windows.get_mut(id).unwrap().replace(window); - - cx.display_linker.on_next_frame(display_id, |_, _| { - dbg!("next frame"); - }); - handle }) } diff --git a/crates/gpui3/src/display_linker.rs b/crates/gpui3/src/display_linker.rs index 1be32a23e2..54954b15b6 100644 --- a/crates/gpui3/src/display_linker.rs +++ b/crates/gpui3/src/display_linker.rs @@ -28,7 +28,7 @@ impl DisplayLinker { 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) + self.platform_linker.start(display_id); } entry.get_mut().push(callback) } @@ -48,6 +48,7 @@ impl DisplayLinker { // platform_linker.stop(display_id); }), ); + self.platform_linker.start(display_id); entry.insert(vec![callback]); } } diff --git a/crates/gpui3/src/platform/mac/display_linker.rs b/crates/gpui3/src/platform/mac/display_linker.rs index 05381845b2..47c26f007c 100644 --- a/crates/gpui3/src/platform/mac/display_linker.rs +++ b/crates/gpui3/src/platform/mac/display_linker.rs @@ -1,4 +1,8 @@ -use std::ffi::c_void; +use std::{ + ffi::c_void, + mem, + sync::{Arc, Weak}, +}; use crate::{DisplayId, PlatformDisplayLinker}; use collections::HashMap; @@ -10,8 +14,8 @@ pub struct MacDisplayLinker { } struct MacDisplayLink { - output_callback: Box, system_link: sys::DisplayLink, + _output_callback: Arc, } unsafe impl Send for MacDisplayLink {} @@ -24,33 +28,29 @@ impl MacDisplayLinker { } } +type OutputCallback = Mutex>; + impl PlatformDisplayLinker for MacDisplayLinker { fn set_output_callback( &self, display_id: DisplayId, - mut output_callback: Box, + output_callback: Box, ) { if let Some(mut system_link) = unsafe { sys::DisplayLink::on_display(display_id.0) } { - unsafe { - system_link.set_output_callback( - trampoline, - output_callback.as_mut() as *mut dyn FnMut(_, _) as *mut c_void, - ) - } + let callback = Arc::new(Mutex::new(output_callback)); + let weak_callback_ptr: *const OutputCallback = Arc::downgrade(&callback).into_raw(); + unsafe { system_link.set_output_callback(trampoline, weak_callback_ptr as *mut c_void) } - let previous = self.links.lock().insert( + self.links.lock().insert( display_id, MacDisplayLink { - output_callback, + _output_callback: callback, system_link, }, ); - assert!( - previous.is_none(), - "You can currently only set an output callback once per display." - ) } else { - return log::warn!("DisplayLink could not be obtained for {:?}", display_id); + log::warn!("DisplayLink could not be obtained for {:?}", display_id); + return; } } @@ -81,11 +81,15 @@ unsafe extern "C" fn trampoline( output_time: *const sys::CVTimeStamp, _flags_in: i64, _flags_out: *mut i64, - context: *mut c_void, + user_data: *mut c_void, ) -> i32 { - let output_callback = &mut (*(context as *mut MacDisplayLink)).output_callback; if let Some((current_time, output_time)) = current_time.as_ref().zip(output_time.as_ref()) { - output_callback(¤t_time, &output_time); + let output_callback: Weak = + Weak::from_raw(user_data as *mut OutputCallback); + if let Some(output_callback) = output_callback.upgrade() { + (output_callback.lock())(current_time, output_time) + } + mem::forget(output_callback); } 0 }