Checkpoint
This commit is contained in:
parent
bc1801fb03
commit
f9646208e9
4 changed files with 117 additions and 33 deletions
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use collections::{HashMap, VecDeque};
|
use collections::{HashMap, VecDeque};
|
||||||
use futures::Future;
|
use futures::{channel::oneshot, Future};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -93,9 +93,9 @@ type Handlers = SmallVec<[Arc<dyn Fn(&mut AppContext) -> bool + Send + Sync + 's
|
||||||
pub struct AppContext {
|
pub struct AppContext {
|
||||||
this: Weak<Mutex<MainThread<AppContext>>>,
|
this: Weak<Mutex<MainThread<AppContext>>>,
|
||||||
platform: MainThreadOnly<dyn Platform>,
|
platform: MainThreadOnly<dyn Platform>,
|
||||||
dispatcher: Arc<dyn PlatformDispatcher>,
|
|
||||||
text_system: Arc<TextSystem>,
|
text_system: Arc<TextSystem>,
|
||||||
pending_updates: usize,
|
pending_updates: usize,
|
||||||
|
pub(crate) dispatcher: Arc<dyn PlatformDispatcher>,
|
||||||
pub(crate) svg_renderer: SvgRenderer,
|
pub(crate) svg_renderer: SvgRenderer,
|
||||||
pub(crate) image_cache: ImageCache,
|
pub(crate) image_cache: ImageCache,
|
||||||
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
|
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
|
||||||
|
@ -185,19 +185,29 @@ impl AppContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_on_main<R>(
|
pub fn run_on_main<R>(
|
||||||
&self,
|
&mut self,
|
||||||
f: impl FnOnce(&mut MainThread<AppContext>) -> R + Send + 'static,
|
f: impl FnOnce(&mut MainThread<AppContext>) -> R + Send + 'static,
|
||||||
) -> impl Future<Output = R>
|
) -> impl Future<Output = R>
|
||||||
where
|
where
|
||||||
R: Send + 'static,
|
R: Send + 'static,
|
||||||
{
|
{
|
||||||
let this = self.this.upgrade().unwrap();
|
let (tx, rx) = oneshot::channel();
|
||||||
run_on_main(self.dispatcher.clone(), move || {
|
if self.dispatcher.is_main_thread() {
|
||||||
let cx = &mut *this.lock();
|
let _ = tx.send(f(unsafe {
|
||||||
cx.update(|cx| {
|
mem::transmute::<&mut AppContext, &mut MainThread<AppContext>>(self)
|
||||||
f(unsafe { mem::transmute::<&mut AppContext, &mut MainThread<AppContext>>(cx) })
|
}));
|
||||||
})
|
} else {
|
||||||
})
|
let this = self.this.upgrade().unwrap();
|
||||||
|
let _ = run_on_main(self.dispatcher.clone(), move || {
|
||||||
|
let cx = &mut *this.lock();
|
||||||
|
cx.update(|cx| {
|
||||||
|
let _ = tx.send(f(unsafe {
|
||||||
|
mem::transmute::<&mut Self, &mut MainThread<Self>>(cx)
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_on_main<F, R>(
|
pub fn spawn_on_main<F, R>(
|
||||||
|
@ -307,7 +317,7 @@ impl MainThread<AppContext> {
|
||||||
pub(crate) fn update_window<R>(
|
pub(crate) fn update_window<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: WindowId,
|
id: WindowId,
|
||||||
update: impl FnOnce(&mut WindowContext) -> R,
|
update: impl FnOnce(&mut MainThread<WindowContext>) -> R,
|
||||||
) -> Result<R> {
|
) -> Result<R> {
|
||||||
self.0.update_window(id, |cx| {
|
self.0.update_window(id, |cx| {
|
||||||
update(unsafe {
|
update(unsafe {
|
||||||
|
|
|
@ -27,7 +27,15 @@ where
|
||||||
F: FnOnce() -> R + Send + 'static,
|
F: FnOnce() -> R + Send + 'static,
|
||||||
R: Send + 'static,
|
R: Send + 'static,
|
||||||
{
|
{
|
||||||
spawn_on_main(dispatcher, move || async move { func() })
|
let (tx, rx) = oneshot::channel();
|
||||||
|
if dispatcher.is_main_thread() {
|
||||||
|
let _ = tx.send(func());
|
||||||
|
} else {
|
||||||
|
let _ = spawn_on_main(dispatcher, move || async move {
|
||||||
|
let _ = tx.send(func());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enqueues the given closure to be run on the application's event loop. The
|
/// Enqueues the given closure to be run on the application's event loop. The
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub use serde_json;
|
||||||
pub use smallvec;
|
pub use smallvec;
|
||||||
pub use smol::Timer;
|
pub use smol::Timer;
|
||||||
use std::{
|
use std::{
|
||||||
|
mem,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
@ -89,6 +90,42 @@ impl<T> DerefMut for MainThread<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<C: Context> Context for MainThread<C> {
|
||||||
|
type EntityContext<'a, 'w, T: 'static + Send + Sync> = MainThread<C::EntityContext<'a, 'w, T>>;
|
||||||
|
type Result<T> = C::Result<T>;
|
||||||
|
|
||||||
|
fn entity<T: Send + Sync + 'static>(
|
||||||
|
&mut self,
|
||||||
|
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||||
|
) -> Self::Result<Handle<T>> {
|
||||||
|
self.0.entity(|cx| {
|
||||||
|
let cx = unsafe {
|
||||||
|
mem::transmute::<
|
||||||
|
&mut C::EntityContext<'_, '_, T>,
|
||||||
|
&mut MainThread<C::EntityContext<'_, '_, T>>,
|
||||||
|
>(cx)
|
||||||
|
};
|
||||||
|
build_entity(cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_entity<T: Send + Sync + 'static, R>(
|
||||||
|
&mut self,
|
||||||
|
handle: &Handle<T>,
|
||||||
|
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||||
|
) -> Self::Result<R> {
|
||||||
|
self.0.update_entity(handle, |entity, cx| {
|
||||||
|
let cx = unsafe {
|
||||||
|
mem::transmute::<
|
||||||
|
&mut C::EntityContext<'_, '_, T>,
|
||||||
|
&mut MainThread<C::EntityContext<'_, '_, T>>,
|
||||||
|
>(cx)
|
||||||
|
};
|
||||||
|
update(entity, cx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait BorrowAppContext {
|
pub trait BorrowAppContext {
|
||||||
fn app_mut(&mut self) -> &mut AppContext;
|
fn app_mut(&mut self) -> &mut AppContext;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
WindowOptions, SUBPIXEL_VARIANTS,
|
WindowOptions, SUBPIXEL_VARIANTS,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::Future;
|
use futures::{channel::oneshot, Future};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{any::TypeId, borrow::Cow, marker::PhantomData, mem, sync::Arc};
|
use std::{any::TypeId, borrow::Cow, marker::PhantomData, mem, sync::Arc};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
@ -112,6 +112,29 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
self.window.dirty = true;
|
self.window.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_on_main<R>(
|
||||||
|
&mut self,
|
||||||
|
f: impl FnOnce(&mut MainThread<WindowContext<'_, '_>>) -> R + Send + 'static,
|
||||||
|
) -> impl Future<Output = R>
|
||||||
|
where
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
if self.dispatcher.is_main_thread() {
|
||||||
|
let _ = tx.send(f(unsafe {
|
||||||
|
mem::transmute::<&mut Self, &mut MainThread<Self>>(self)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
let id = self.window.handle.id;
|
||||||
|
let _ = self.app.run_on_main(move |cx| {
|
||||||
|
cx.update_window(id, |cx| {
|
||||||
|
let _ = tx.send(f(cx));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_layout(
|
pub fn request_layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
style: Style,
|
style: Style,
|
||||||
|
@ -191,23 +214,6 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
self.window.current_layer_id.clone()
|
self.window.current_layer_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_on_main<R>(
|
|
||||||
&self,
|
|
||||||
f: impl FnOnce(&mut MainThread<WindowContext>) -> R + Send + 'static,
|
|
||||||
) -> impl Future<Output = Result<R>>
|
|
||||||
where
|
|
||||||
R: Send + 'static,
|
|
||||||
{
|
|
||||||
let id = self.window.handle.id;
|
|
||||||
self.app.run_on_main(move |cx| {
|
|
||||||
cx.update_window(id, |cx| {
|
|
||||||
f(unsafe {
|
|
||||||
mem::transmute::<&mut WindowContext, &mut MainThread<WindowContext>>(cx)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn paint_glyph(
|
pub fn paint_glyph(
|
||||||
&mut self,
|
&mut self,
|
||||||
origin: Point<Pixels>,
|
origin: Point<Pixels>,
|
||||||
|
@ -389,7 +395,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
|
|
||||||
pub(crate) fn draw(&mut self) -> Result<()> {
|
pub(crate) fn draw(&mut self) -> Result<()> {
|
||||||
let unit_entity = self.unit_entity.clone();
|
let unit_entity = self.unit_entity.clone();
|
||||||
self.update_entity(&unit_entity, |_, cx| {
|
self.update_entity(&unit_entity, |view, cx| {
|
||||||
let mut root_view = cx.window.root_view.take().unwrap();
|
let mut root_view = cx.window.root_view.take().unwrap();
|
||||||
let (root_layout_id, mut frame_state) = root_view.layout(&mut (), cx)?;
|
let (root_layout_id, mut frame_state) = root_view.layout(&mut (), cx)?;
|
||||||
let available_space = cx.window.content_size.map(Into::into);
|
let available_space = cx.window.content_size.map(Into::into);
|
||||||
|
@ -403,14 +409,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
cx.window.root_view = Some(root_view);
|
cx.window.root_view = Some(root_view);
|
||||||
let scene = cx.window.scene.take();
|
let scene = cx.window.scene.take();
|
||||||
|
|
||||||
let _ = cx.run_on_main(|cx| {
|
let _ = cx.run_on_main(view, |_, cx| {
|
||||||
cx.window
|
cx.window
|
||||||
.platform_window
|
.platform_window
|
||||||
.borrow_on_main_thread()
|
.borrow_on_main_thread()
|
||||||
.draw(scene);
|
.draw(scene);
|
||||||
|
cx.window.dirty = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
cx.window.dirty = false;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -596,6 +602,29 @@ impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
|
||||||
.push_back(Effect::Notify(self.entity_id));
|
.push_back(Effect::Notify(self.entity_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_on_main<R>(
|
||||||
|
&mut self,
|
||||||
|
view: &mut S,
|
||||||
|
f: impl FnOnce(&mut S, &mut MainThread<ViewContext<'_, '_, S>>) -> R + Send + 'static,
|
||||||
|
) -> impl Future<Output = R>
|
||||||
|
where
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let (tx, rx) = oneshot::channel();
|
||||||
|
if self.dispatcher.is_main_thread() {
|
||||||
|
let cx = unsafe { mem::transmute::<&mut Self, &mut MainThread<Self>>(self) };
|
||||||
|
let _ = tx.send(f(view, cx));
|
||||||
|
} else {
|
||||||
|
let handle = self.handle().upgrade(self).unwrap();
|
||||||
|
let _ = self.window_cx.run_on_main(move |cx| {
|
||||||
|
handle.update(cx, |view, cx| {
|
||||||
|
let _ = tx.send(f(view, cx));
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async move { rx.await.unwrap() }
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
|
pub(crate) fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
|
||||||
let entity_id = self.unit_entity.id;
|
let entity_id = self.unit_entity.id;
|
||||||
let mut cx = ViewContext::mutable(
|
let mut cx = ViewContext::mutable(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue