WIP
This commit is contained in:
+32
-16
@@ -9,9 +9,9 @@ use refineable::Refineable;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{
|
||||
current_platform, image_cache::ImageCache, Action, AssetSource, Context, DispatchPhase,
|
||||
DisplayId, Executor, FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap, LayoutId,
|
||||
MainThread, MainThreadOnly, Platform, SemanticVersion, SharedString, SubscriberSet,
|
||||
current_platform, image_cache::ImageCache, Action, AppMetadata, AssetSource, Context,
|
||||
DispatchPhase, DisplayId, Executor, FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap,
|
||||
LayoutId, MainThread, MainThreadOnly, Platform, SemanticVersion, SharedString, SubscriberSet,
|
||||
SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, Window, WindowContext,
|
||||
WindowHandle, WindowId,
|
||||
};
|
||||
@@ -49,13 +49,25 @@ impl App {
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
) -> Self {
|
||||
let executor = platform.executor();
|
||||
assert!(
|
||||
executor.is_main_thread(),
|
||||
"must construct App on main thread"
|
||||
);
|
||||
|
||||
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
||||
let entities = EntityMap::new();
|
||||
let unit_entity = entities.insert(entities.reserve(), ());
|
||||
let app_metadata = AppMetadata {
|
||||
os_name: platform.os_name(),
|
||||
os_version: platform.os_version().unwrap_or_default(),
|
||||
app_version: platform.app_version().unwrap_or_default(),
|
||||
};
|
||||
Self(Arc::new_cyclic(|this| {
|
||||
Mutex::new(AppContext {
|
||||
this: this.clone(),
|
||||
text_system: Arc::new(TextSystem::new(platform.text_system())),
|
||||
text_system,
|
||||
platform: MainThreadOnly::new(platform, executor.clone()),
|
||||
app_metadata,
|
||||
flushing_effects: false,
|
||||
pending_updates: 0,
|
||||
next_frame_callbacks: Default::default(),
|
||||
@@ -128,16 +140,8 @@ impl App {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn app_version(&self) -> Result<SemanticVersion> {
|
||||
self.0.lock().platform.borrow_on_main_thread().app_version()
|
||||
}
|
||||
|
||||
pub fn os_name(&self) -> &'static str {
|
||||
self.0.lock().platform.borrow_on_main_thread().os_name()
|
||||
}
|
||||
|
||||
pub fn os_version(&self) -> Result<SemanticVersion> {
|
||||
self.0.lock().platform.borrow_on_main_thread().os_version()
|
||||
pub fn metadata(&self) -> AppMetadata {
|
||||
self.0.lock().app_metadata.clone()
|
||||
}
|
||||
|
||||
pub fn executor(&self) -> Executor {
|
||||
@@ -158,6 +162,7 @@ type ActionBuilder = fn(json: Option<serde_json::Value>) -> anyhow::Result<Box<d
|
||||
pub struct AppContext {
|
||||
this: Weak<Mutex<AppContext>>,
|
||||
pub(crate) platform: MainThreadOnly<dyn Platform>,
|
||||
app_metadata: AppMetadata,
|
||||
text_system: Arc<TextSystem>,
|
||||
flushing_effects: bool,
|
||||
pending_updates: usize,
|
||||
@@ -184,6 +189,10 @@ pub struct AppContext {
|
||||
}
|
||||
|
||||
impl AppContext {
|
||||
pub fn app_metadata(&self) -> AppMetadata {
|
||||
self.app_metadata.clone()
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
self.push_effect(Effect::Refresh);
|
||||
}
|
||||
@@ -379,7 +388,10 @@ impl AppContext {
|
||||
}
|
||||
|
||||
pub fn to_async(&self) -> AsyncAppContext {
|
||||
AsyncAppContext(unsafe { mem::transmute(self.this.clone()) })
|
||||
AsyncAppContext {
|
||||
app: unsafe { mem::transmute(self.this.clone()) },
|
||||
executor: self.executor.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn executor(&self) -> &Executor {
|
||||
@@ -639,7 +651,7 @@ impl MainThread<AppContext> {
|
||||
self.platform.borrow_on_main_thread()
|
||||
}
|
||||
|
||||
pub fn activate(&mut self, ignoring_other_apps: bool) {
|
||||
pub fn activate(&self, ignoring_other_apps: bool) {
|
||||
self.platform().activate(ignoring_other_apps);
|
||||
}
|
||||
|
||||
@@ -655,6 +667,10 @@ impl MainThread<AppContext> {
|
||||
self.platform().delete_credentials(url)
|
||||
}
|
||||
|
||||
pub fn open_url(&self, url: &str) {
|
||||
self.platform().open_url(url);
|
||||
}
|
||||
|
||||
pub fn open_window<S: 'static + Send + Sync>(
|
||||
&mut self,
|
||||
options: crate::WindowOptions,
|
||||
|
||||
@@ -8,7 +8,10 @@ use parking_lot::Mutex;
|
||||
use std::{future::Future, sync::Weak};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
|
||||
pub struct AsyncAppContext {
|
||||
pub(crate) app: Weak<Mutex<AppContext>>,
|
||||
pub(crate) executor: Executor,
|
||||
}
|
||||
|
||||
impl Context for AsyncAppContext {
|
||||
type EntityContext<'a, 'w, T: 'static + Send + Sync> = ModelContext<'a, T>;
|
||||
@@ -19,7 +22,7 @@ impl Context for AsyncAppContext {
|
||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||
) -> Self::Result<Handle<T>> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.lock(); // Need this to compile
|
||||
@@ -32,7 +35,7 @@ impl Context for AsyncAppContext {
|
||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||
) -> Self::Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.lock(); // Need this to compile
|
||||
@@ -43,7 +46,7 @@ impl Context for AsyncAppContext {
|
||||
impl AsyncAppContext {
|
||||
pub fn refresh(&mut self) -> Result<()> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.lock(); // Need this to compile
|
||||
@@ -51,13 +54,17 @@ impl AsyncAppContext {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn executor(&self) -> Result<Executor> {
|
||||
pub fn executor(&self) -> &Executor {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
pub fn update<R>(&self, f: impl FnOnce(&mut AppContext) -> R) -> Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let lock = app.lock(); // Need this to compile
|
||||
Ok(lock.executor().clone())
|
||||
let mut lock = app.lock();
|
||||
Ok(f(&mut *lock))
|
||||
}
|
||||
|
||||
pub fn read_window<R>(
|
||||
@@ -66,7 +73,7 @@ impl AsyncAppContext {
|
||||
update: impl FnOnce(&WindowContext) -> R,
|
||||
) -> Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut app_context = app.lock();
|
||||
@@ -79,27 +86,32 @@ impl AsyncAppContext {
|
||||
update: impl FnOnce(&mut WindowContext) -> R,
|
||||
) -> Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut app_context = app.lock();
|
||||
app_context.update_window(handle.id, update)
|
||||
}
|
||||
|
||||
pub fn spawn<Fut, R>(
|
||||
&self,
|
||||
f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static,
|
||||
) -> Result<Task<R>>
|
||||
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static) -> Task<R>
|
||||
where
|
||||
Fut: Future<Output = R> + Send + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let app = self
|
||||
.0
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let app_context = app.lock();
|
||||
Ok(app_context.spawn(f))
|
||||
let this = self.clone();
|
||||
self.executor.spawn(async move { f(this).await })
|
||||
}
|
||||
|
||||
pub fn spawn_on_main<Fut, R>(
|
||||
&self,
|
||||
f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static,
|
||||
) -> Task<R>
|
||||
where
|
||||
Fut: Future<Output = R> + 'static,
|
||||
R: Send + 'static,
|
||||
{
|
||||
let this = self.clone();
|
||||
self.executor.spawn_on_main(|| f(this))
|
||||
}
|
||||
|
||||
pub fn run_on_main<R>(
|
||||
@@ -110,7 +122,7 @@ impl AsyncAppContext {
|
||||
R: Send + 'static,
|
||||
{
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut app_context = app.lock();
|
||||
@@ -119,7 +131,7 @@ impl AsyncAppContext {
|
||||
|
||||
pub fn has_global<G: 'static + Send + Sync>(&self) -> Result<bool> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let lock = app.lock(); // Need this to compile
|
||||
@@ -131,7 +143,7 @@ impl AsyncAppContext {
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let lock = app.lock(); // Need this to compile
|
||||
@@ -142,7 +154,7 @@ impl AsyncAppContext {
|
||||
&self,
|
||||
read: impl FnOnce(&G, &AppContext) -> R,
|
||||
) -> Option<R> {
|
||||
let app = self.0.upgrade()?;
|
||||
let app = self.app.upgrade()?;
|
||||
let lock = app.lock(); // Need this to compile
|
||||
Some(read(lock.try_global()?, &lock))
|
||||
}
|
||||
@@ -152,7 +164,7 @@ impl AsyncAppContext {
|
||||
update: impl FnOnce(&mut G, &mut AppContext) -> R,
|
||||
) -> Result<R> {
|
||||
let app = self
|
||||
.0
|
||||
.app
|
||||
.upgrade()
|
||||
.ok_or_else(|| anyhow!("app was released"))?;
|
||||
let mut lock = app.lock(); // Need this to compile
|
||||
|
||||
@@ -181,6 +181,13 @@ pub trait PlatformTextSystem: Send + Sync {
|
||||
) -> Vec<usize>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AppMetadata {
|
||||
pub os_name: &'static str,
|
||||
pub os_version: SemanticVersion,
|
||||
pub app_version: SemanticVersion,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub enum AtlasKey {
|
||||
Glyph(RenderGlyphParams),
|
||||
@@ -404,7 +411,7 @@ impl Default for CursorStyle {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct SemanticVersion {
|
||||
major: usize,
|
||||
minor: usize,
|
||||
|
||||
Reference in New Issue
Block a user