Checkpoint
This commit is contained in:
parent
457df8d3f3
commit
006f840570
6 changed files with 125 additions and 102 deletions
|
@ -9,9 +9,8 @@ use refineable::Refineable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor, LayoutId,
|
current_platform, image_cache::ImageCache, AssetSource, Context, DisplayId, Executor, LayoutId,
|
||||||
MainThread, MainThreadOnly, Platform, PlatformDisplayLinker, RootView, SubscriberSet,
|
MainThread, MainThreadOnly, Platform, RootView, SubscriberSet, SvgRenderer, Task, TextStyle,
|
||||||
SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, Window, WindowContext,
|
TextStyleRefinement, TextSystem, Window, WindowContext, WindowHandle, WindowId,
|
||||||
WindowHandle, WindowId,
|
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use collections::{HashMap, VecDeque};
|
use collections::{HashMap, VecDeque};
|
||||||
|
@ -55,7 +54,6 @@ impl App {
|
||||||
this: this.clone(),
|
this: this.clone(),
|
||||||
text_system: Arc::new(TextSystem::new(platform.text_system())),
|
text_system: Arc::new(TextSystem::new(platform.text_system())),
|
||||||
pending_updates: 0,
|
pending_updates: 0,
|
||||||
display_linker: platform.display_linker(),
|
|
||||||
next_frame_callbacks: Default::default(),
|
next_frame_callbacks: Default::default(),
|
||||||
platform: MainThreadOnly::new(platform, executor.clone()),
|
platform: MainThreadOnly::new(platform, executor.clone()),
|
||||||
executor,
|
executor,
|
||||||
|
@ -94,10 +92,9 @@ type FrameCallback = Box<dyn FnOnce(&mut WindowContext) + Send>;
|
||||||
|
|
||||||
pub struct AppContext {
|
pub struct AppContext {
|
||||||
this: Weak<Mutex<AppContext>>,
|
this: Weak<Mutex<AppContext>>,
|
||||||
platform: MainThreadOnly<dyn Platform>,
|
pub(crate) platform: MainThreadOnly<dyn Platform>,
|
||||||
text_system: Arc<TextSystem>,
|
text_system: Arc<TextSystem>,
|
||||||
pending_updates: usize,
|
pending_updates: usize,
|
||||||
pub(crate) display_linker: Arc<dyn PlatformDisplayLinker>,
|
|
||||||
pub(crate) next_frame_callbacks: HashMap<DisplayId, Vec<FrameCallback>>,
|
pub(crate) next_frame_callbacks: HashMap<DisplayId, Vec<FrameCallback>>,
|
||||||
pub(crate) executor: Executor,
|
pub(crate) executor: Executor,
|
||||||
pub(crate) svg_renderer: SvgRenderer,
|
pub(crate) svg_renderer: SvgRenderer,
|
||||||
|
|
|
@ -40,7 +40,6 @@ pub(crate) fn current_platform() -> Arc<dyn Platform> {
|
||||||
|
|
||||||
pub(crate) trait Platform: 'static {
|
pub(crate) trait Platform: 'static {
|
||||||
fn executor(&self) -> Executor;
|
fn executor(&self) -> Executor;
|
||||||
fn display_linker(&self) -> Arc<dyn PlatformDisplayLinker>;
|
|
||||||
fn text_system(&self) -> Arc<dyn PlatformTextSystem>;
|
fn text_system(&self) -> Arc<dyn PlatformTextSystem>;
|
||||||
|
|
||||||
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>);
|
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>);
|
||||||
|
@ -59,6 +58,14 @@ pub(crate) trait Platform: 'static {
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
options: WindowOptions,
|
options: WindowOptions,
|
||||||
) -> Box<dyn PlatformWindow>;
|
) -> Box<dyn PlatformWindow>;
|
||||||
|
|
||||||
|
fn set_display_link_output_callback(
|
||||||
|
&self,
|
||||||
|
display_id: DisplayId,
|
||||||
|
callback: Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>,
|
||||||
|
);
|
||||||
|
fn start_display_link(&self, display_id: DisplayId);
|
||||||
|
fn stop_display_link(&self, display_id: DisplayId);
|
||||||
// fn add_status_item(&self, _handle: AnyWindowHandle) -> Box<dyn PlatformWindow>;
|
// fn add_status_item(&self, _handle: AnyWindowHandle) -> Box<dyn PlatformWindow>;
|
||||||
|
|
||||||
fn open_url(&self, url: &str);
|
fn open_url(&self, url: &str);
|
||||||
|
@ -154,16 +161,6 @@ pub trait PlatformDispatcher: Send + Sync {
|
||||||
fn dispatch_on_main_thread(&self, task: Runnable);
|
fn dispatch_on_main_thread(&self, task: Runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlatformDisplayLinker: Send + Sync {
|
|
||||||
fn set_output_callback(
|
|
||||||
&self,
|
|
||||||
display_id: DisplayId,
|
|
||||||
callback: Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>,
|
|
||||||
);
|
|
||||||
fn start(&self, display_id: DisplayId);
|
|
||||||
fn stop(&self, display_id: DisplayId);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait PlatformTextSystem: Send + Sync {
|
pub trait PlatformTextSystem: Send + Sync {
|
||||||
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()>;
|
fn add_fonts(&self, fonts: &[Arc<Vec<u8>>]) -> Result<()>;
|
||||||
fn all_font_families(&self) -> Vec<String>;
|
fn all_font_families(&self) -> Vec<String>;
|
||||||
|
|
|
@ -4,27 +4,23 @@ use std::{
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{DisplayId, Executor, MainThreadOnly, PlatformDisplayLinker};
|
use crate::DisplayId;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
pub use sys::CVTimeStamp as VideoTimestamp;
|
pub use sys::CVTimeStamp as VideoTimestamp;
|
||||||
|
|
||||||
pub struct MacDisplayLinker {
|
pub(crate) struct MacDisplayLinker {
|
||||||
links: Mutex<HashMap<DisplayId, MacDisplayLink>>,
|
links: HashMap<DisplayId, MacDisplayLink>,
|
||||||
executor: Executor,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MacDisplayLink {
|
struct MacDisplayLink {
|
||||||
system_link: MainThreadOnly<sys::DisplayLink>,
|
system_link: sys::DisplayLink,
|
||||||
_output_callback: Arc<OutputCallback>,
|
_output_callback: Arc<OutputCallback>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for MacDisplayLink {}
|
|
||||||
|
|
||||||
impl MacDisplayLinker {
|
impl MacDisplayLinker {
|
||||||
pub fn new(executor: Executor) -> Self {
|
pub fn new() -> Self {
|
||||||
MacDisplayLinker {
|
MacDisplayLinker {
|
||||||
executor,
|
|
||||||
links: Default::default(),
|
links: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,9 +28,9 @@ impl MacDisplayLinker {
|
||||||
|
|
||||||
type OutputCallback = Mutex<Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>>;
|
type OutputCallback = Mutex<Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>>;
|
||||||
|
|
||||||
impl PlatformDisplayLinker for MacDisplayLinker {
|
impl MacDisplayLinker {
|
||||||
fn set_output_callback(
|
pub fn set_output_callback(
|
||||||
&self,
|
&mut self,
|
||||||
display_id: DisplayId,
|
display_id: DisplayId,
|
||||||
output_callback: Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>,
|
output_callback: Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>,
|
||||||
) {
|
) {
|
||||||
|
@ -43,11 +39,11 @@ impl PlatformDisplayLinker for MacDisplayLinker {
|
||||||
let weak_callback_ptr: *const OutputCallback = Arc::downgrade(&callback).into_raw();
|
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) }
|
unsafe { system_link.set_output_callback(trampoline, weak_callback_ptr as *mut c_void) }
|
||||||
|
|
||||||
self.links.lock().insert(
|
self.links.insert(
|
||||||
display_id,
|
display_id,
|
||||||
MacDisplayLink {
|
MacDisplayLink {
|
||||||
_output_callback: callback,
|
_output_callback: callback,
|
||||||
system_link: MainThreadOnly::new(Arc::new(system_link), self.executor.clone()),
|
system_link,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,26 +52,20 @@ impl PlatformDisplayLinker for MacDisplayLinker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn start(&self, display_id: DisplayId) {
|
pub fn start(&mut self, display_id: DisplayId) {
|
||||||
if let Some(link) = self.links.lock().get_mut(&display_id) {
|
if let Some(link) = self.links.get_mut(&display_id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let system_link = link.system_link.clone();
|
link.system_link.start();
|
||||||
self.executor
|
|
||||||
.run_on_main(move || system_link.borrow_on_main_thread().start())
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::warn!("No DisplayLink callback registered for {:?}", display_id)
|
log::warn!("No DisplayLink callback registered for {:?}", display_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&self, display_id: DisplayId) {
|
pub fn stop(&mut self, display_id: DisplayId) {
|
||||||
if let Some(link) = self.links.lock().get_mut(&display_id) {
|
if let Some(link) = self.links.get_mut(&display_id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let system_link = link.system_link.clone();
|
link.system_link.stop();
|
||||||
self.executor
|
|
||||||
.run_on_main(move || system_link.borrow_on_main_thread().stop())
|
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::warn!("No DisplayLink callback registered for {:?}", display_id)
|
log::warn!("No DisplayLink callback registered for {:?}", display_id)
|
||||||
|
@ -218,16 +208,16 @@ mod sys {
|
||||||
display_link_out: *mut *mut CVDisplayLink,
|
display_link_out: *mut *mut CVDisplayLink,
|
||||||
) -> i32;
|
) -> i32;
|
||||||
pub fn CVDisplayLinkSetOutputCallback(
|
pub fn CVDisplayLinkSetOutputCallback(
|
||||||
display_link: &DisplayLinkRef,
|
display_link: &mut DisplayLinkRef,
|
||||||
callback: CVDisplayLinkOutputCallback,
|
callback: CVDisplayLinkOutputCallback,
|
||||||
user_info: *mut c_void,
|
user_info: *mut c_void,
|
||||||
) -> i32;
|
) -> i32;
|
||||||
pub fn CVDisplayLinkSetCurrentCGDisplay(
|
pub fn CVDisplayLinkSetCurrentCGDisplay(
|
||||||
display_link: &DisplayLinkRef,
|
display_link: &mut DisplayLinkRef,
|
||||||
display_id: u32,
|
display_id: u32,
|
||||||
) -> i32;
|
) -> i32;
|
||||||
pub fn CVDisplayLinkStart(display_link: &DisplayLinkRef) -> i32;
|
pub fn CVDisplayLinkStart(display_link: &mut DisplayLinkRef) -> i32;
|
||||||
pub fn CVDisplayLinkStop(display_link: &DisplayLinkRef) -> i32;
|
pub fn CVDisplayLinkStop(display_link: &mut DisplayLinkRef) -> i32;
|
||||||
pub fn CVDisplayLinkRelease(display_link: *mut CVDisplayLink);
|
pub fn CVDisplayLinkRelease(display_link: *mut CVDisplayLink);
|
||||||
pub fn CVDisplayLinkRetain(display_link: *mut CVDisplayLink) -> *mut CVDisplayLink;
|
pub fn CVDisplayLinkRetain(display_link: *mut CVDisplayLink) -> *mut CVDisplayLink;
|
||||||
}
|
}
|
||||||
|
@ -272,12 +262,12 @@ mod sys {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apple docs: [CVDisplayLinkStart](https://developer.apple.com/documentation/corevideo/1457193-cvdisplaylinkstart?language=objc)
|
/// Apple docs: [CVDisplayLinkStart](https://developer.apple.com/documentation/corevideo/1457193-cvdisplaylinkstart?language=objc)
|
||||||
pub unsafe fn start(&self) {
|
pub unsafe fn start(&mut self) {
|
||||||
assert_eq!(CVDisplayLinkStart(self), 0);
|
assert_eq!(CVDisplayLinkStart(self), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apple docs: [CVDisplayLinkStop](https://developer.apple.com/documentation/corevideo/1457281-cvdisplaylinkstop?language=objc)
|
/// Apple docs: [CVDisplayLinkStop](https://developer.apple.com/documentation/corevideo/1457281-cvdisplaylinkstop?language=objc)
|
||||||
pub unsafe fn stop(&self) {
|
pub unsafe fn stop(&mut self) {
|
||||||
assert_eq!(CVDisplayLinkStop(self), 0);
|
assert_eq!(CVDisplayLinkStop(self), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use super::BoolExt;
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, ClipboardItem, CursorStyle, DisplayId, Event, Executor, MacDispatcher,
|
AnyWindowHandle, ClipboardItem, CursorStyle, DisplayId, Event, Executor, MacDispatcher,
|
||||||
MacDisplay, MacDisplayLinker, MacTextSystem, MacWindow, PathPromptOptions, Platform,
|
MacDisplay, MacDisplayLinker, MacTextSystem, MacWindow, PathPromptOptions, Platform,
|
||||||
PlatformDisplay, PlatformDisplayLinker, PlatformTextSystem, PlatformWindow, Result,
|
PlatformDisplay, PlatformTextSystem, PlatformWindow, Result, SemanticVersion, VideoTimestamp,
|
||||||
SemanticVersion, WindowOptions,
|
WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use block::ConcreteBlock;
|
use block::ConcreteBlock;
|
||||||
|
@ -145,6 +145,7 @@ pub struct MacPlatform(Mutex<MacPlatformState>);
|
||||||
pub struct MacPlatformState {
|
pub struct MacPlatformState {
|
||||||
executor: Executor,
|
executor: Executor,
|
||||||
text_system: Arc<MacTextSystem>,
|
text_system: Arc<MacTextSystem>,
|
||||||
|
display_linker: MacDisplayLinker,
|
||||||
pasteboard: id,
|
pasteboard: id,
|
||||||
text_hash_pasteboard_type: id,
|
text_hash_pasteboard_type: id,
|
||||||
metadata_pasteboard_type: id,
|
metadata_pasteboard_type: id,
|
||||||
|
@ -166,6 +167,7 @@ impl MacPlatform {
|
||||||
Self(Mutex::new(MacPlatformState {
|
Self(Mutex::new(MacPlatformState {
|
||||||
executor: Executor::new(Arc::new(MacDispatcher)),
|
executor: Executor::new(Arc::new(MacDispatcher)),
|
||||||
text_system: Arc::new(MacTextSystem::new()),
|
text_system: Arc::new(MacTextSystem::new()),
|
||||||
|
display_linker: MacDisplayLinker::new(),
|
||||||
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
pasteboard: unsafe { NSPasteboard::generalPasteboard(nil) },
|
||||||
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
text_hash_pasteboard_type: unsafe { ns_string("zed-text-hash") },
|
||||||
metadata_pasteboard_type: unsafe { ns_string("zed-metadata") },
|
metadata_pasteboard_type: unsafe { ns_string("zed-metadata") },
|
||||||
|
@ -348,10 +350,6 @@ impl Platform for MacPlatform {
|
||||||
self.0.lock().executor.clone()
|
self.0.lock().executor.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_linker(&self) -> Arc<dyn PlatformDisplayLinker> {
|
|
||||||
Arc::new(MacDisplayLinker::new(self.executor()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
|
fn text_system(&self) -> Arc<dyn PlatformTextSystem> {
|
||||||
self.0.lock().text_system.clone()
|
self.0.lock().text_system.clone()
|
||||||
}
|
}
|
||||||
|
@ -487,6 +485,25 @@ impl Platform for MacPlatform {
|
||||||
Box::new(MacWindow::open(handle, options, self.executor()))
|
Box::new(MacWindow::open(handle, options, self.executor()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_display_link_output_callback(
|
||||||
|
&self,
|
||||||
|
display_id: DisplayId,
|
||||||
|
callback: Box<dyn FnMut(&VideoTimestamp, &VideoTimestamp)>,
|
||||||
|
) {
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.display_linker
|
||||||
|
.set_output_callback(display_id, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_display_link(&self, display_id: DisplayId) {
|
||||||
|
self.0.lock().display_linker.start(display_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_display_link(&self, display_id: DisplayId) {
|
||||||
|
self.0.lock().display_linker.stop(display_id);
|
||||||
|
}
|
||||||
|
|
||||||
fn open_url(&self, url: &str) {
|
fn open_url(&self, url: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let url = NSURL::alloc(nil)
|
let url = NSURL::alloc(nil)
|
||||||
|
@ -675,6 +692,32 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
||||||
|
// self.0.lock().menu_command = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
|
||||||
|
// self.0.lock().will_open_menu = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
||||||
|
// self.0.lock().validate_menu_command = Some(callback);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn set_menus(&self, menus: Vec<Menu>, keystroke_matcher: &KeymapMatcher) {
|
||||||
|
// unsafe {
|
||||||
|
// let app: id = msg_send![APP_CLASS, sharedApplication];
|
||||||
|
// let mut state = self.0.lock();
|
||||||
|
// let actions = &mut state.menu_actions;
|
||||||
|
// app.setMainMenu_(self.create_menu_bar(
|
||||||
|
// menus,
|
||||||
|
// app.delegate(),
|
||||||
|
// actions,
|
||||||
|
// keystroke_matcher,
|
||||||
|
// ));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
fn set_cursor_style(&self, style: CursorStyle) {
|
fn set_cursor_style(&self, style: CursorStyle) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let new_cursor: id = match style {
|
let new_cursor: id = match style {
|
||||||
|
@ -741,32 +784,6 @@ impl Platform for MacPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn on_menu_command(&self, callback: Box<dyn FnMut(&dyn Action)>) {
|
|
||||||
// self.0.lock().menu_command = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn on_will_open_menu(&self, callback: Box<dyn FnMut()>) {
|
|
||||||
// self.0.lock().will_open_menu = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn on_validate_menu_command(&self, callback: Box<dyn FnMut(&dyn Action) -> bool>) {
|
|
||||||
// self.0.lock().validate_menu_command = Some(callback);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn set_menus(&self, menus: Vec<Menu>, keystroke_matcher: &KeymapMatcher) {
|
|
||||||
// unsafe {
|
|
||||||
// let app: id = msg_send![APP_CLASS, sharedApplication];
|
|
||||||
// let mut state = self.0.lock();
|
|
||||||
// let actions = &mut state.menu_actions;
|
|
||||||
// app.setMainMenu_(self.create_menu_bar(
|
|
||||||
// menus,
|
|
||||||
// app.delegate(),
|
|
||||||
// actions,
|
|
||||||
// keystroke_matcher,
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
fn read_from_clipboard(&self) -> Option<ClipboardItem> {
|
||||||
let state = self.0.lock();
|
let state = self.0.lock();
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -15,10 +15,6 @@ impl Platform for TestPlatform {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_linker(&self) -> std::sync::Arc<dyn crate::PlatformDisplayLinker> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn text_system(&self) -> std::sync::Arc<dyn crate::PlatformTextSystem> {
|
fn text_system(&self) -> std::sync::Arc<dyn crate::PlatformTextSystem> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -71,6 +67,22 @@ impl Platform for TestPlatform {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_display_link_output_callback(
|
||||||
|
&self,
|
||||||
|
_display_id: DisplayId,
|
||||||
|
_callback: Box<dyn FnMut(&crate::VideoTimestamp, &crate::VideoTimestamp)>,
|
||||||
|
) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_display_link(&self, _display_id: DisplayId) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_display_link(&self, _display_id: DisplayId) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn open_url(&self, _url: &str) {
|
fn open_url(&self, _url: &str) {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
px, size, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, BorrowAppContext,
|
px, size, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, BorrowAppContext,
|
||||||
Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId, Edges, Effect, Element, EntityId,
|
Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId, Edges, Effect, Element, EntityId,
|
||||||
Event, EventEmitter, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData, IsZero,
|
Event, EventEmitter, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData, IsZero,
|
||||||
LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels,
|
LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels, Platform,
|
||||||
PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
|
PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams,
|
||||||
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
|
RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size,
|
||||||
Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle,
|
Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle,
|
||||||
|
@ -190,17 +190,17 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
|
pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
|
||||||
let f = Box::new(f);
|
let f = Box::new(f);
|
||||||
let display_id = self.window.display_id;
|
let display_id = self.window.display_id;
|
||||||
let async_cx = self.to_async();
|
self.run_on_main(move |cx| {
|
||||||
let app_cx = self.app_mut();
|
if let Some(callbacks) = cx.next_frame_callbacks.get_mut(&display_id) {
|
||||||
match app_cx.next_frame_callbacks.entry(display_id) {
|
callbacks.push(f);
|
||||||
collections::hash_map::Entry::Occupied(mut entry) => {
|
// If there was already a callback, it means that we already scheduled a frame.
|
||||||
if entry.get().is_empty() {
|
if callbacks.len() > 1 {
|
||||||
app_cx.display_linker.start(display_id);
|
return;
|
||||||
}
|
}
|
||||||
entry.get_mut().push(f);
|
} else {
|
||||||
}
|
let async_cx = cx.to_async();
|
||||||
collections::hash_map::Entry::Vacant(entry) => {
|
cx.next_frame_callbacks.insert(display_id, vec![f]);
|
||||||
app_cx.display_linker.set_output_callback(
|
cx.platform().set_display_link_output_callback(
|
||||||
display_id,
|
display_id,
|
||||||
Box::new(move |_current_time, _output_time| {
|
Box::new(move |_current_time, _output_time| {
|
||||||
let _ = async_cx.update(|cx| {
|
let _ = async_cx.update(|cx| {
|
||||||
|
@ -214,16 +214,20 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
callback(cx);
|
callback(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {
|
cx.run_on_main(move |cx| {
|
||||||
cx.display_linker.stop(display_id);
|
if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {
|
||||||
}
|
cx.platform().stop_display_link(display_id);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
app_cx.display_linker.start(display_id);
|
|
||||||
entry.insert(vec![f]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
cx.platform().start_display_link(display_id);
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn<Fut, R>(
|
pub fn spawn<Fut, R>(
|
||||||
|
@ -709,6 +713,12 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'w> MainThread<WindowContext<'a, 'w>> {
|
||||||
|
fn platform(&self) -> &dyn Platform {
|
||||||
|
self.platform.borrow_on_main_thread()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Context for WindowContext<'_, '_> {
|
impl Context for WindowContext<'_, '_> {
|
||||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
|
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
|
||||||
type Result<T> = T;
|
type Result<T> = T;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue