This commit is contained in:
Antonio Scandurra
2023-10-22 16:27:23 +02:00
parent 5423012368
commit 6ffeb048b3
5 changed files with 132 additions and 152 deletions
+32 -16
View File
@@ -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,
+37 -25
View File
@@ -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
+8 -1
View File
@@ -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,