Checkpoint
This commit is contained in:
parent
15567493ba
commit
04d3ea9563
9 changed files with 313 additions and 166 deletions
|
@ -31,13 +31,13 @@ impl App {
|
||||||
let dispatcher = platform.dispatcher();
|
let dispatcher = platform.dispatcher();
|
||||||
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
||||||
let mut entities = SlotMap::with_key();
|
let mut entities = SlotMap::with_key();
|
||||||
let unit_entity_id = entities.insert(Some(Box::new(()) as Box<dyn Any + Send>));
|
let unit_entity = Handle::new(entities.insert(Some(Box::new(()) as Box<dyn Any + Send>)));
|
||||||
Self(Arc::new_cyclic(|this| {
|
Self(Arc::new_cyclic(|this| {
|
||||||
Mutex::new(AppContext {
|
Mutex::new(AppContext {
|
||||||
this: this.clone(),
|
this: this.clone(),
|
||||||
platform: MainThreadOnly::new(platform, dispatcher),
|
platform: MainThreadOnly::new(platform, dispatcher),
|
||||||
text_system,
|
text_system,
|
||||||
unit_entity_id,
|
unit_entity,
|
||||||
entities,
|
entities,
|
||||||
windows: SlotMap::with_key(),
|
windows: SlotMap::with_key(),
|
||||||
pending_updates: 0,
|
pending_updates: 0,
|
||||||
|
@ -67,7 +67,7 @@ pub struct AppContext {
|
||||||
this: Weak<Mutex<AppContext>>,
|
this: Weak<Mutex<AppContext>>,
|
||||||
platform: MainThreadOnly<dyn Platform>,
|
platform: MainThreadOnly<dyn Platform>,
|
||||||
text_system: Arc<TextSystem>,
|
text_system: Arc<TextSystem>,
|
||||||
pub(crate) unit_entity_id: EntityId,
|
pub(crate) unit_entity: Handle<()>,
|
||||||
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any + Send>>>,
|
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any + Send>>>,
|
||||||
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
||||||
pending_updates: usize,
|
pending_updates: usize,
|
||||||
|
@ -82,8 +82,12 @@ impl AppContext {
|
||||||
&self.text_system
|
&self.text_system
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_async(&self) -> AsyncContext {
|
||||||
|
AsyncContext(self.this.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn spawn_on_main<F, R>(
|
pub fn spawn_on_main<F, R>(
|
||||||
&mut self,
|
&self,
|
||||||
f: impl FnOnce(&dyn Platform, &mut Self) -> F + Send + 'static,
|
f: impl FnOnce(&dyn Platform, &mut Self) -> F + Send + 'static,
|
||||||
) -> impl Future<Output = R>
|
) -> impl Future<Output = R>
|
||||||
where
|
where
|
||||||
|
@ -97,7 +101,7 @@ impl AppContext {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_window<S: 'static + Send>(
|
pub fn open_window<S: 'static + Send + Sync>(
|
||||||
&mut self,
|
&mut self,
|
||||||
options: crate::WindowOptions,
|
options: crate::WindowOptions,
|
||||||
build_root_view: impl FnOnce(&mut WindowContext) -> RootView<S> + Send + 'static,
|
build_root_view: impl FnOnce(&mut WindowContext) -> RootView<S> + Send + 'static,
|
||||||
|
@ -105,9 +109,9 @@ impl AppContext {
|
||||||
let id = self.windows.insert(None);
|
let id = self.windows.insert(None);
|
||||||
let handle = WindowHandle::new(id);
|
let handle = WindowHandle::new(id);
|
||||||
self.spawn_on_main(move |platform, cx| {
|
self.spawn_on_main(move |platform, cx| {
|
||||||
let mut window = Window::new(handle.into(), options, platform);
|
let mut window = Window::new(handle.into(), options, platform, cx);
|
||||||
let root_view = build_root_view(&mut WindowContext::mutable(cx, &mut window));
|
let root_view = build_root_view(&mut WindowContext::mutable(cx, &mut window));
|
||||||
window.root_view.replace(Box::new(root_view));
|
window.root_view.replace(root_view.into_any());
|
||||||
cx.windows.get_mut(id).unwrap().replace(window);
|
cx.windows.get_mut(id).unwrap().replace(window);
|
||||||
future::ready(handle)
|
future::ready(handle)
|
||||||
})
|
})
|
||||||
|
@ -184,6 +188,7 @@ impl AppContext {
|
||||||
|
|
||||||
impl Context for AppContext {
|
impl Context for AppContext {
|
||||||
type EntityContext<'a, 'w, T: Send + Sync + 'static> = ModelContext<'a, T>;
|
type EntityContext<'a, 'w, T: Send + Sync + 'static> = ModelContext<'a, T>;
|
||||||
|
type Result<T> = T;
|
||||||
|
|
||||||
fn entity<T: Send + Sync + 'static>(
|
fn entity<T: Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -216,6 +221,54 @@ impl Context for AppContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AsyncContext(Weak<Mutex<AppContext>>);
|
||||||
|
|
||||||
|
impl Context for AsyncContext {
|
||||||
|
type EntityContext<'a, 'b, T: Send + Sync + 'static> = ModelContext<'a, T>;
|
||||||
|
type Result<T> = Result<T>;
|
||||||
|
|
||||||
|
fn entity<T: Send + Sync + 'static>(
|
||||||
|
&mut self,
|
||||||
|
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||||
|
) -> Result<Handle<T>> {
|
||||||
|
let app = self
|
||||||
|
.0
|
||||||
|
.upgrade()
|
||||||
|
.ok_or_else(|| anyhow!("app was released"))?;
|
||||||
|
let mut lock = app.lock();
|
||||||
|
Ok(lock.entity(build_entity))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_entity<T: Send + Sync + 'static, R>(
|
||||||
|
&mut self,
|
||||||
|
handle: &Handle<T>,
|
||||||
|
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||||
|
) -> Result<R> {
|
||||||
|
let app = self
|
||||||
|
.0
|
||||||
|
.upgrade()
|
||||||
|
.ok_or_else(|| anyhow!("app was released"))?;
|
||||||
|
let mut lock = app.lock();
|
||||||
|
Ok(lock.update_entity(handle, update))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsyncContext {
|
||||||
|
pub fn update_window<T>(
|
||||||
|
&self,
|
||||||
|
handle: AnyWindowHandle,
|
||||||
|
update: impl FnOnce(&mut WindowContext) -> T + Send + Sync,
|
||||||
|
) -> Result<T> {
|
||||||
|
let app = self
|
||||||
|
.0
|
||||||
|
.upgrade()
|
||||||
|
.ok_or_else(|| anyhow!("app was released"))?;
|
||||||
|
let mut app_context = app.lock();
|
||||||
|
app_context.update_window(handle.id, update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ModelContext<'a, T> {
|
pub struct ModelContext<'a, T> {
|
||||||
app: Reference<'a, AppContext>,
|
app: Reference<'a, AppContext>,
|
||||||
entity_type: PhantomData<T>,
|
entity_type: PhantomData<T>,
|
||||||
|
@ -293,6 +346,7 @@ impl<'a, T: Send + Sync + 'static> ModelContext<'a, T> {
|
||||||
|
|
||||||
impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
impl<'a, T: 'static> Context for ModelContext<'a, T> {
|
||||||
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
|
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ModelContext<'b, U>;
|
||||||
|
type Result<U> = U;
|
||||||
|
|
||||||
fn entity<U: Send + Sync + 'static>(
|
fn entity<U: Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -341,7 +395,7 @@ impl<T: Send + Sync + 'static> Handle<T> {
|
||||||
&self,
|
&self,
|
||||||
cx: &mut C,
|
cx: &mut C,
|
||||||
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
||||||
) -> R {
|
) -> C::Result<R> {
|
||||||
cx.update_entity(self, update)
|
cx.update_entity(self, update)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,12 +434,15 @@ impl<T: Send + Sync + 'static> WeakHandle<T> {
|
||||||
&self,
|
&self,
|
||||||
cx: &mut C,
|
cx: &mut C,
|
||||||
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
update: impl FnOnce(&mut T, &mut C::EntityContext<'_, '_, T>) -> R,
|
||||||
) -> Result<R> {
|
) -> Result<R>
|
||||||
if let Some(this) = self.upgrade(cx) {
|
where
|
||||||
Ok(cx.update_entity(&this, update))
|
Result<C::Result<R>>: crate::Flatten<R>,
|
||||||
} else {
|
{
|
||||||
Err(anyhow!("entity released"))
|
crate::Flatten::flatten(
|
||||||
}
|
self.upgrade(cx)
|
||||||
|
.ok_or_else(|| anyhow!("entity release"))
|
||||||
|
.map(|this| cx.update_entity(&this, update)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use crate::Element;
|
use crate::Element;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub struct Stateless<E: Element<State = ()>, S> {
|
pub struct Stateless<E: Element<State = ()>, S> {
|
||||||
element: E,
|
element: E,
|
||||||
|
|
|
@ -47,17 +47,34 @@ pub use window::*;
|
||||||
|
|
||||||
pub trait Context {
|
pub trait Context {
|
||||||
type EntityContext<'a, 'w, T: Send + Sync + 'static>;
|
type EntityContext<'a, 'w, T: Send + Sync + 'static>;
|
||||||
|
type Result<T>;
|
||||||
|
|
||||||
fn entity<T: Send + Sync + 'static>(
|
fn entity<T: Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
|
||||||
) -> Handle<T>;
|
) -> Self::Result<Handle<T>>;
|
||||||
|
|
||||||
fn update_entity<T: Send + Sync + 'static, R>(
|
fn update_entity<T: Send + Sync + 'static, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: &Handle<T>,
|
handle: &Handle<T>,
|
||||||
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
|
||||||
) -> R;
|
) -> Self::Result<R>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Flatten<T> {
|
||||||
|
fn flatten(self) -> Result<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Flatten<T> for Result<Result<T>> {
|
||||||
|
fn flatten(self) -> Result<T> {
|
||||||
|
self?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Flatten<T> for Result<T> {
|
||||||
|
fn flatten(self) -> Result<T> {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
|
|
|
@ -136,14 +136,14 @@ pub trait PlatformWindow {
|
||||||
fn minimize(&self);
|
fn minimize(&self);
|
||||||
fn zoom(&self);
|
fn zoom(&self);
|
||||||
fn toggle_full_screen(&self);
|
fn toggle_full_screen(&self);
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>);
|
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>);
|
||||||
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>);
|
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>);
|
||||||
fn on_resize(&mut self, callback: Box<dyn FnMut()>);
|
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>);
|
||||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>);
|
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>);
|
||||||
fn on_moved(&mut self, callback: Box<dyn FnMut()>);
|
fn on_moved(&self, callback: Box<dyn FnMut()>);
|
||||||
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>);
|
fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>);
|
||||||
fn on_close(&mut self, callback: Box<dyn FnOnce()>);
|
fn on_close(&self, callback: Box<dyn FnOnce()>);
|
||||||
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>);
|
fn on_appearance_changed(&self, callback: Box<dyn FnMut()>);
|
||||||
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool;
|
fn is_topmost_for_position(&self, position: Point<Pixels>) -> bool;
|
||||||
fn draw(&self, scene: Scene);
|
fn draw(&self, scene: Scene);
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,7 +286,7 @@ struct MacWindowState {
|
||||||
kind: WindowKind,
|
kind: WindowKind,
|
||||||
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
event_callback: Option<Box<dyn FnMut(Event) -> bool>>,
|
||||||
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
activate_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
resize_callback: Option<Box<dyn FnMut()>>,
|
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||||
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
fullscreen_callback: Option<Box<dyn FnMut(bool)>>,
|
||||||
moved_callback: Option<Box<dyn FnMut()>>,
|
moved_callback: Option<Box<dyn FnMut()>>,
|
||||||
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
|
should_close_callback: Option<Box<dyn FnMut() -> bool>>,
|
||||||
|
@ -821,35 +821,35 @@ impl PlatformWindow for MacWindow {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, callback: Box<dyn FnMut(Event) -> bool>) {
|
fn on_event(&self, callback: Box<dyn FnMut(Event) -> bool>) {
|
||||||
self.0.as_ref().lock().event_callback = Some(callback);
|
self.0.as_ref().lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_active_status_change(&mut self, callback: Box<dyn FnMut(bool)>) {
|
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
|
||||||
self.0.as_ref().lock().activate_callback = Some(callback);
|
self.0.as_ref().lock().activate_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_resize(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
|
||||||
self.0.as_ref().lock().resize_callback = Some(callback);
|
self.0.as_ref().lock().resize_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_fullscreen(&mut self, callback: Box<dyn FnMut(bool)>) {
|
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>) {
|
||||||
self.0.as_ref().lock().fullscreen_callback = Some(callback);
|
self.0.as_ref().lock().fullscreen_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_moved(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_moved(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.as_ref().lock().moved_callback = Some(callback);
|
self.0.as_ref().lock().moved_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_should_close(&mut self, callback: Box<dyn FnMut() -> bool>) {
|
fn on_should_close(&self, callback: Box<dyn FnMut() -> bool>) {
|
||||||
self.0.as_ref().lock().should_close_callback = Some(callback);
|
self.0.as_ref().lock().should_close_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_close(&mut self, callback: Box<dyn FnOnce()>) {
|
fn on_close(&self, callback: Box<dyn FnOnce()>) {
|
||||||
self.0.as_ref().lock().close_callback = Some(callback);
|
self.0.as_ref().lock().close_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_appearance_changed(&mut self, callback: Box<dyn FnMut()>) {
|
fn on_appearance_changed(&self, callback: Box<dyn FnMut()>) {
|
||||||
self.0.lock().appearance_changed_callback = Some(callback);
|
self.0.lock().appearance_changed_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,9 +935,9 @@ extern "C" fn handle_key_down(this: &Object, _: Sel, native_event: id) {
|
||||||
|
|
||||||
extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: bool) -> BOOL {
|
extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent: bool) -> BOOL {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
|
|
||||||
let window_height = window_state_borrow.content_size().height;
|
let window_height = lock.content_size().height;
|
||||||
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
if let Some(Event::KeyDown(event)) = event {
|
if let Some(Event::KeyDown(event)) = event {
|
||||||
|
@ -946,8 +946,8 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
// makes no distinction between these two types of events, so we need to ignore
|
// makes no distinction between these two types of events, so we need to ignore
|
||||||
// the "key down" event if we've already just processed its "key equivalent" version.
|
// the "key down" event if we've already just processed its "key equivalent" version.
|
||||||
if key_equivalent {
|
if key_equivalent {
|
||||||
window_state_borrow.last_key_equivalent = Some(event.clone());
|
lock.last_key_equivalent = Some(event.clone());
|
||||||
} else if window_state_borrow.last_key_equivalent.take().as_ref() == Some(&event) {
|
} else if lock.last_key_equivalent.take().as_ref() == Some(&event) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,14 +956,14 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
// Ignore events from held-down keys after some of the initially-pressed keys
|
// Ignore events from held-down keys after some of the initially-pressed keys
|
||||||
// were released.
|
// were released.
|
||||||
if event.is_held {
|
if event.is_held {
|
||||||
if window_state_borrow.last_fresh_keydown.as_ref() != Some(&keydown) {
|
if lock.last_fresh_keydown.as_ref() != Some(&keydown) {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window_state_borrow.last_fresh_keydown = Some(keydown);
|
lock.last_fresh_keydown = Some(keydown);
|
||||||
}
|
}
|
||||||
window_state_borrow.pending_key_down = Some((event, None));
|
lock.pending_key_down = Some((event, None));
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
|
|
||||||
// Send the event to the input context for IME handling, unless the `fn` modifier is
|
// Send the event to the input context for IME handling, unless the `fn` modifier is
|
||||||
// being pressed.
|
// being pressed.
|
||||||
|
@ -975,12 +975,12 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut handled = false;
|
let mut handled = false;
|
||||||
let mut window_state_borrow = window_state.lock();
|
let mut lock = window_state.lock();
|
||||||
let ime_text = window_state_borrow.ime_text.clone();
|
let ime_text = lock.ime_text.clone();
|
||||||
if let Some((event, insert_text)) = window_state_borrow.pending_key_down.take() {
|
if let Some((event, insert_text)) = lock.pending_key_down.take() {
|
||||||
let is_held = event.is_held;
|
let is_held = event.is_held;
|
||||||
if let Some(mut callback) = window_state_borrow.event_callback.take() {
|
if let Some(mut callback) = lock.event_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
|
|
||||||
let is_composing =
|
let is_composing =
|
||||||
with_input_handler(this, |input_handler| input_handler.marked_text_range())
|
with_input_handler(this, |input_handler| input_handler.marked_text_range())
|
||||||
|
@ -1056,10 +1056,10 @@ extern "C" fn handle_key_event(this: &Object, native_event: id, key_equivalent:
|
||||||
extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let weak_window_state = Arc::downgrade(&window_state);
|
let weak_window_state = Arc::downgrade(&window_state);
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
let is_active = unsafe { window_state_borrow.native_window.isKeyWindow() == YES };
|
let is_active = unsafe { lock.native_window.isKeyWindow() == YES };
|
||||||
|
|
||||||
let window_height = window_state_borrow.content_size().height;
|
let window_height = lock.content_size().height;
|
||||||
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
let event = unsafe { Event::from_native(native_event, Some(window_height)) };
|
||||||
|
|
||||||
if let Some(mut event) = event {
|
if let Some(mut event) = event {
|
||||||
|
@ -1095,7 +1095,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
modifiers: Modifiers { control: true, .. },
|
modifiers: Modifiers { control: true, .. },
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
window_state_borrow.synthetic_drag_counter += 1;
|
lock.synthetic_drag_counter += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,50 +1109,46 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
window_state_borrow.synthetic_drag_counter += 1;
|
lock.synthetic_drag_counter += 1;
|
||||||
let dispatcher = window_state_borrow.dispatcher.clone();
|
let dispatcher = lock.dispatcher.clone();
|
||||||
let _ = crate::spawn_on_main_local(
|
let _ = crate::spawn_on_main_local(
|
||||||
dispatcher,
|
dispatcher,
|
||||||
synthetic_drag(
|
synthetic_drag(
|
||||||
weak_window_state,
|
weak_window_state,
|
||||||
window_state_borrow.synthetic_drag_counter,
|
lock.synthetic_drag_counter,
|
||||||
event.clone(),
|
event.clone(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::MouseMoved(_)
|
Event::MouseMoved(_) if !(is_active || lock.kind == WindowKind::PopUp) => return,
|
||||||
if !(is_active || window_state_borrow.kind == WindowKind::PopUp) =>
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Event::MouseUp(MouseUpEvent {
|
Event::MouseUp(MouseUpEvent {
|
||||||
button: MouseButton::Left,
|
button: MouseButton::Left,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
window_state_borrow.synthetic_drag_counter += 1;
|
lock.synthetic_drag_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
Event::ModifiersChanged(ModifiersChangedEvent { modifiers }) => {
|
||||||
// Only raise modifiers changed event when they have actually changed
|
// Only raise modifiers changed event when they have actually changed
|
||||||
if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
|
if let Some(Event::ModifiersChanged(ModifiersChangedEvent {
|
||||||
modifiers: prev_modifiers,
|
modifiers: prev_modifiers,
|
||||||
})) = &window_state_borrow.previous_modifiers_changed_event
|
})) = &lock.previous_modifiers_changed_event
|
||||||
{
|
{
|
||||||
if prev_modifiers == modifiers {
|
if prev_modifiers == modifiers {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window_state_borrow.previous_modifiers_changed_event = Some(event.clone());
|
lock.previous_modifiers_changed_event = Some(event.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut callback) = window_state_borrow.event_callback.take() {
|
if let Some(mut callback) = lock.event_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback(event);
|
callback(event);
|
||||||
if let Some(event) = synthesized_second_event {
|
if let Some(event) = synthesized_second_event {
|
||||||
callback(event);
|
callback(event);
|
||||||
|
@ -1166,7 +1162,7 @@ extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
|
||||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
||||||
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
|
|
||||||
let keystroke = Keystroke {
|
let keystroke = Keystroke {
|
||||||
modifiers: Default::default(),
|
modifiers: Default::default(),
|
||||||
|
@ -1177,9 +1173,9 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||||
is_held: false,
|
is_held: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
window_state_borrow.last_fresh_keydown = Some(keystroke);
|
lock.last_fresh_keydown = Some(keystroke);
|
||||||
if let Some(mut callback) = window_state_borrow.event_callback.take() {
|
if let Some(mut callback) = lock.event_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback(event);
|
callback(event);
|
||||||
window_state.lock().event_callback = Some(callback);
|
window_state.lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
@ -1200,9 +1196,9 @@ extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||||
|
|
||||||
fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) {
|
fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
if let Some(mut callback) = window_state_borrow.fullscreen_callback.take() {
|
if let Some(mut callback) = lock.fullscreen_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback(is_fullscreen);
|
callback(is_fullscreen);
|
||||||
window_state.lock().fullscreen_callback = Some(callback);
|
window_state.lock().fullscreen_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
@ -1210,9 +1206,9 @@ fn window_fullscreen_changed(this: &Object, is_fullscreen: bool) {
|
||||||
|
|
||||||
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
if let Some(mut callback) = window_state_borrow.moved_callback.take() {
|
if let Some(mut callback) = lock.moved_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback();
|
callback();
|
||||||
window_state.lock().moved_callback = Some(callback);
|
window_state.lock().moved_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
@ -1220,8 +1216,8 @@ extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||||
|
|
||||||
extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) {
|
extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let window_state_borrow = window_state.lock();
|
let lock = window_state.lock();
|
||||||
let is_active = unsafe { window_state_borrow.native_window.isKeyWindow() == YES };
|
let is_active = unsafe { lock.native_window.isKeyWindow() == YES };
|
||||||
|
|
||||||
// When opening a pop-up while the application isn't active, Cocoa sends a spurious
|
// When opening a pop-up while the application isn't active, Cocoa sends a spurious
|
||||||
// `windowDidBecomeKey` message to the previous key window even though that window
|
// `windowDidBecomeKey` message to the previous key window even though that window
|
||||||
|
@ -1235,18 +1231,18 @@ extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id)
|
||||||
if selector == sel!(windowDidBecomeKey:) {
|
if selector == sel!(windowDidBecomeKey:) {
|
||||||
if !is_active {
|
if !is_active {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![window_state_borrow.native_window, resignKeyWindow];
|
let _: () = msg_send![lock.native_window, resignKeyWindow];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dispatcher = window_state_borrow.dispatcher.clone();
|
let dispatcher = lock.dispatcher.clone();
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
let _ = crate::spawn_on_main_local(dispatcher, async move {
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
if let Some(mut callback) = window_state_borrow.activate_callback.take() {
|
if let Some(mut callback) = lock.activate_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback(is_active);
|
callback(is_active);
|
||||||
window_state.lock().activate_callback = Some(callback);
|
window_state.lock().activate_callback = Some(callback);
|
||||||
};
|
};
|
||||||
|
@ -1255,9 +1251,9 @@ extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id)
|
||||||
|
|
||||||
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
if let Some(mut callback) = window_state_borrow.should_close_callback.take() {
|
if let Some(mut callback) = lock.should_close_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
let should_close = callback();
|
let should_close = callback();
|
||||||
window_state.lock().should_close_callback = Some(callback);
|
window_state.lock().should_close_callback = Some(callback);
|
||||||
should_close as BOOL
|
should_close as BOOL
|
||||||
|
@ -1292,38 +1288,40 @@ extern "C" fn make_backing_layer(this: &Object, _: Sel) -> id {
|
||||||
|
|
||||||
extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) {
|
extern "C" fn view_did_change_backing_properties(this: &Object, _: Sel) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let scale_factor = window_state_borrow.scale_factor() as f64;
|
let scale_factor = lock.scale_factor() as f64;
|
||||||
let size = window_state_borrow.content_size();
|
let size = lock.content_size();
|
||||||
let drawable_size: NSSize = NSSize {
|
let drawable_size: NSSize = NSSize {
|
||||||
width: f64::from(size.width) * scale_factor,
|
width: f64::from(size.width) * scale_factor,
|
||||||
height: f64::from(size.height) * scale_factor,
|
height: f64::from(size.height) * scale_factor,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _: () = msg_send![
|
let _: () = msg_send![
|
||||||
window_state_borrow.renderer.layer(),
|
lock.renderer.layer(),
|
||||||
setContentsScale: scale_factor
|
setContentsScale: scale_factor
|
||||||
];
|
];
|
||||||
let _: () = msg_send![
|
let _: () = msg_send![
|
||||||
window_state_borrow.renderer.layer(),
|
lock.renderer.layer(),
|
||||||
setDrawableSize: drawable_size
|
setDrawableSize: drawable_size
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut callback) = window_state_borrow.resize_callback.take() {
|
if let Some(mut callback) = lock.resize_callback.take() {
|
||||||
drop(window_state_borrow);
|
let content_size = lock.content_size();
|
||||||
callback();
|
let scale_factor = lock.scale_factor();
|
||||||
|
drop(lock);
|
||||||
|
callback(content_size, scale_factor);
|
||||||
window_state.as_ref().lock().resize_callback = Some(callback);
|
window_state.as_ref().lock().resize_callback = Some(callback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
||||||
let window_state = unsafe { get_window_state(this) };
|
let window_state = unsafe { get_window_state(this) };
|
||||||
let window_state_borrow = window_state.as_ref().lock();
|
let lock = window_state.as_ref().lock();
|
||||||
|
|
||||||
if window_state_borrow.content_size() == size.into() {
|
if lock.content_size() == size.into() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1331,7 +1329,7 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
||||||
let _: () = msg_send![super(this, class!(NSView)), setFrameSize: size];
|
let _: () = msg_send![super(this, class!(NSView)), setFrameSize: size];
|
||||||
}
|
}
|
||||||
|
|
||||||
let scale_factor = window_state_borrow.scale_factor() as f64;
|
let scale_factor = lock.scale_factor() as f64;
|
||||||
let drawable_size: NSSize = NSSize {
|
let drawable_size: NSSize = NSSize {
|
||||||
width: size.width * scale_factor,
|
width: size.width * scale_factor,
|
||||||
height: size.height * scale_factor,
|
height: size.height * scale_factor,
|
||||||
|
@ -1339,16 +1337,18 @@ extern "C" fn set_frame_size(this: &Object, _: Sel, size: NSSize) {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let _: () = msg_send![
|
let _: () = msg_send![
|
||||||
window_state_borrow.renderer.layer(),
|
lock.renderer.layer(),
|
||||||
setDrawableSize: drawable_size
|
setDrawableSize: drawable_size
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
let mut window_state_borrow = window_state.lock();
|
let mut lock = window_state.lock();
|
||||||
if let Some(mut callback) = window_state_borrow.resize_callback.take() {
|
if let Some(mut callback) = lock.resize_callback.take() {
|
||||||
drop(window_state_borrow);
|
let content_size = lock.content_size();
|
||||||
callback();
|
let scale_factor = lock.scale_factor();
|
||||||
|
drop(lock);
|
||||||
|
callback(content_size, scale_factor);
|
||||||
window_state.lock().resize_callback = Some(callback);
|
window_state.lock().resize_callback = Some(callback);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1416,9 +1416,9 @@ extern "C" fn first_rect_for_character_range(
|
||||||
extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NSRange) {
|
extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NSRange) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window_state = get_window_state(this);
|
let window_state = get_window_state(this);
|
||||||
let mut window_state_borrow = window_state.lock();
|
let mut lock = window_state.lock();
|
||||||
let pending_key_down = window_state_borrow.pending_key_down.take();
|
let pending_key_down = lock.pending_key_down.take();
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
|
|
||||||
let is_attributed_string: BOOL =
|
let is_attributed_string: BOOL =
|
||||||
msg_send![text, isKindOfClass: [class!(NSAttributedString)]];
|
msg_send![text, isKindOfClass: [class!(NSAttributedString)]];
|
||||||
|
@ -1534,9 +1534,9 @@ extern "C" fn do_command_by_selector(this: &Object, _: Sel, _: Sel) {
|
||||||
extern "C" fn view_did_change_effective_appearance(this: &Object, _: Sel) {
|
extern "C" fn view_did_change_effective_appearance(this: &Object, _: Sel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state = get_window_state(this);
|
let state = get_window_state(this);
|
||||||
let mut state_borrow = state.as_ref().lock();
|
let mut lock = state.as_ref().lock();
|
||||||
if let Some(mut callback) = state_borrow.appearance_changed_callback.take() {
|
if let Some(mut callback) = lock.appearance_changed_callback.take() {
|
||||||
drop(state_borrow);
|
drop(lock);
|
||||||
callback();
|
callback();
|
||||||
state.lock().appearance_changed_callback = Some(callback);
|
state.lock().appearance_changed_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
@ -1546,8 +1546,8 @@ extern "C" fn view_did_change_effective_appearance(this: &Object, _: Sel) {
|
||||||
extern "C" fn accepts_first_mouse(this: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn accepts_first_mouse(this: &Object, _: Sel, _: id) -> BOOL {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state = get_window_state(this);
|
let state = get_window_state(this);
|
||||||
let state_borrow = state.as_ref().lock();
|
let lock = state.as_ref().lock();
|
||||||
return if state_borrow.kind == WindowKind::PopUp {
|
return if lock.kind == WindowKind::PopUp {
|
||||||
YES
|
YES
|
||||||
} else {
|
} else {
|
||||||
NO
|
NO
|
||||||
|
@ -1563,10 +1563,10 @@ async fn synthetic_drag(
|
||||||
loop {
|
loop {
|
||||||
Timer::after(Duration::from_millis(16)).await;
|
Timer::after(Duration::from_millis(16)).await;
|
||||||
if let Some(window_state) = window_state.upgrade() {
|
if let Some(window_state) = window_state.upgrade() {
|
||||||
let mut window_state_borrow = window_state.lock();
|
let mut lock = window_state.lock();
|
||||||
if window_state_borrow.synthetic_drag_counter == drag_id {
|
if lock.synthetic_drag_counter == drag_id {
|
||||||
if let Some(mut callback) = window_state_borrow.event_callback.take() {
|
if let Some(mut callback) = lock.event_callback.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
callback(Event::MouseMoved(event.clone()));
|
callback(Event::MouseMoved(event.clone()));
|
||||||
window_state.lock().event_callback = Some(callback);
|
window_state.lock().event_callback = Some(callback);
|
||||||
}
|
}
|
||||||
|
@ -1582,9 +1582,9 @@ where
|
||||||
F: FnOnce(&mut dyn InputHandler) -> R,
|
F: FnOnce(&mut dyn InputHandler) -> R,
|
||||||
{
|
{
|
||||||
let window_state = unsafe { get_window_state(window) };
|
let window_state = unsafe { get_window_state(window) };
|
||||||
let mut window_state_borrow = window_state.as_ref().lock();
|
let mut lock = window_state.as_ref().lock();
|
||||||
if let Some(mut input_handler) = window_state_borrow.input_handler.take() {
|
if let Some(mut input_handler) = lock.input_handler.take() {
|
||||||
drop(window_state_borrow);
|
drop(lock);
|
||||||
let result = f(input_handler.as_mut());
|
let result = f(input_handler.as_mut());
|
||||||
window_state.lock().input_handler = Some(input_handler);
|
window_state.lock().input_handler = Some(input_handler);
|
||||||
Some(result)
|
Some(result)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use super::{Bounds, Hsla, Pixels, Point};
|
use super::{Bounds, Hsla, Pixels, Point};
|
||||||
use crate::{Corners, Edges};
|
use crate::{Corners, Edges};
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
|
@ -8,7 +10,7 @@ pub type PointF = Point<f32>;
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
layers: BTreeMap<u32, SceneLayer>,
|
layers: BTreeMap<u32, SceneLayer>,
|
||||||
scale_factor: f32,
|
pub(crate) scale_factor: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -24,6 +26,13 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn take(&mut self) -> Scene {
|
||||||
|
Scene {
|
||||||
|
layers: mem::take(&mut self.layers),
|
||||||
|
scale_factor: self.scale_factor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, primitive: impl Into<Primitive>) {
|
pub fn insert(&mut self, primitive: impl Into<Primitive>) {
|
||||||
let mut primitive = primitive.into();
|
let mut primitive = primitive.into();
|
||||||
primitive.scale(self.scale_factor);
|
primitive.scale(self.scale_factor);
|
||||||
|
|
|
@ -66,6 +66,16 @@ impl TaffyLayoutEngine {
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compute_layout(
|
||||||
|
&mut self,
|
||||||
|
id: LayoutId,
|
||||||
|
available_space: Size<AvailableSpace>,
|
||||||
|
) -> Result<()> {
|
||||||
|
self.taffy
|
||||||
|
.compute_layout(id.into(), available_space.into())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn layout(&mut self, id: LayoutId) -> Result<Layout> {
|
pub fn layout(&mut self, id: LayoutId) -> Result<Layout> {
|
||||||
if let Some(layout) = self.absolute_layouts.get(&id).cloned() {
|
if let Some(layout) = self.absolute_layouts.get(&id).cloned() {
|
||||||
return Ok(layout);
|
return Ok(layout);
|
||||||
|
@ -104,16 +114,6 @@ impl From<LayoutId> for NodeId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum AvailableSpace {
|
|
||||||
/// The amount of space available is the specified number of pixels
|
|
||||||
Definite(Pixels),
|
|
||||||
/// The amount of space available is indefinite and the node should be laid out under a min-content constraint
|
|
||||||
MinContent,
|
|
||||||
/// The amount of space available is indefinite and the node should be laid out under a max-content constraint
|
|
||||||
MaxContent,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Measureable<F>(F);
|
struct Measureable<F>(F);
|
||||||
|
|
||||||
impl<F> taffy::tree::Measurable for Measureable<F>
|
impl<F> taffy::tree::Measurable for Measureable<F>
|
||||||
|
@ -334,17 +334,28 @@ impl<T: Into<U> + Clone + Debug, U> From<Size<T>> for taffy::geometry::Size<U> {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// impl From<TaffySize<TaffyAvailableSpace>> for Size<AvailableSpace> {
|
#[derive(Copy, Clone, Debug)]
|
||||||
// fn from(taffy_size: TaffySize<TaffyAvailableSpace>) -> Self {
|
pub enum AvailableSpace {
|
||||||
// Size {
|
/// The amount of space available is the specified number of pixels
|
||||||
// width: From::from(taffy_size.width),
|
Definite(Pixels),
|
||||||
// height: From::from(taffy_size.height),
|
/// The amount of space available is indefinite and the node should be laid out under a min-content constraint
|
||||||
// }
|
MinContent,
|
||||||
// }
|
/// The amount of space available is indefinite and the node should be laid out under a max-content constraint
|
||||||
// }
|
MaxContent,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AvailableSpace> for TaffyAvailableSpace {
|
||||||
|
fn from(space: AvailableSpace) -> TaffyAvailableSpace {
|
||||||
|
match space {
|
||||||
|
AvailableSpace::Definite(Pixels(value)) => TaffyAvailableSpace::Definite(value),
|
||||||
|
AvailableSpace::MinContent => TaffyAvailableSpace::MinContent,
|
||||||
|
AvailableSpace::MaxContent => TaffyAvailableSpace::MaxContent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<TaffyAvailableSpace> for AvailableSpace {
|
impl From<TaffyAvailableSpace> for AvailableSpace {
|
||||||
fn from(space: TaffyAvailableSpace) -> Self {
|
fn from(space: TaffyAvailableSpace) -> AvailableSpace {
|
||||||
match space {
|
match space {
|
||||||
TaffyAvailableSpace::Definite(value) => AvailableSpace::Definite(Pixels(value)),
|
TaffyAvailableSpace::Definite(value) => AvailableSpace::Definite(Pixels(value)),
|
||||||
TaffyAvailableSpace::MinContent => AvailableSpace::MinContent,
|
TaffyAvailableSpace::MinContent => AvailableSpace::MinContent,
|
||||||
|
@ -353,6 +364,12 @@ impl From<TaffyAvailableSpace> for AvailableSpace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Pixels> for AvailableSpace {
|
||||||
|
fn from(pixels: Pixels) -> Self {
|
||||||
|
AvailableSpace::Definite(pixels)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&taffy::tree::Layout> for Layout {
|
impl From<&taffy::tree::Layout> for Layout {
|
||||||
fn from(layout: &taffy::tree::Layout) -> Self {
|
fn from(layout: &taffy::tree::Layout) -> Self {
|
||||||
Layout {
|
Layout {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyElement, Element, Handle, IntoAnyElement, Layout, LayoutId, Result, ViewContext,
|
AnyElement, Element, Handle, IntoAnyElement, Layout, LayoutId, Result, ViewContext,
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use std::{any::Any, cell::RefCell, marker::PhantomData, rc::Rc, sync::Arc};
|
use std::{any::Any, marker::PhantomData, sync::Arc};
|
||||||
|
|
||||||
pub struct View<S, P> {
|
pub struct View<S, P> {
|
||||||
state: Handle<S>,
|
state: Handle<S>,
|
||||||
|
@ -10,6 +12,15 @@ pub struct View<S, P> {
|
||||||
parent_state_type: PhantomData<P>,
|
parent_state_type: PhantomData<P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<S: 'static + Send + Sync, P: 'static + Send> View<S, P> {
|
||||||
|
pub fn into_any(self) -> AnyView<P> {
|
||||||
|
AnyView {
|
||||||
|
view: Arc::new(Mutex::new(self)),
|
||||||
|
parent_state_type: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S, P> Clone for View<S, P> {
|
impl<S, P> Clone for View<S, P> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -33,15 +44,6 @@ pub fn view<S: 'static, P: 'static, E: Element<State = S>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Send + Sync + 'static, P: 'static> View<S, P> {
|
|
||||||
pub fn into_any<ParentState>(self) -> AnyView<ParentState> {
|
|
||||||
AnyView {
|
|
||||||
view: Rc::new(RefCell::new(self)),
|
|
||||||
parent_state_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Send + Sync + 'static, P: Send + 'static> Element for View<S, P> {
|
impl<S: Send + Sync + 'static, P: Send + 'static> Element for View<S, P> {
|
||||||
type State = P;
|
type State = P;
|
||||||
type FrameState = AnyElement<S>;
|
type FrameState = AnyElement<S>;
|
||||||
|
@ -70,7 +72,7 @@ impl<S: Send + Sync + 'static, P: Send + 'static> Element for View<S, P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ViewObject {
|
trait ViewObject: Send + 'static {
|
||||||
fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)>;
|
fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)>;
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -80,7 +82,7 @@ trait ViewObject {
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Send + Sync + 'static, P> ViewObject for View<S, P> {
|
impl<S: Send + Sync + 'static, P: Send + 'static> ViewObject for View<S, P> {
|
||||||
fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
|
fn layout(&mut self, cx: &mut WindowContext) -> Result<(LayoutId, Box<dyn Any>)> {
|
||||||
self.state.update(cx, |state, cx| {
|
self.state.update(cx, |state, cx| {
|
||||||
let mut element = (self.render)(state, cx);
|
let mut element = (self.render)(state, cx);
|
||||||
|
@ -106,12 +108,12 @@ impl<S: Send + Sync + 'static, P> ViewObject for View<S, P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AnyView<S> {
|
pub struct AnyView<S> {
|
||||||
view: Rc<RefCell<dyn ViewObject>>,
|
view: Arc<Mutex<dyn ViewObject>>,
|
||||||
parent_state_type: PhantomData<S>,
|
parent_state_type: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: 'static> Element for AnyView<S> {
|
impl<S: 'static> Element for AnyView<S> {
|
||||||
type State = S;
|
type State = ();
|
||||||
type FrameState = Box<dyn Any>;
|
type FrameState = Box<dyn Any>;
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
@ -119,7 +121,7 @@ impl<S: 'static> Element for AnyView<S> {
|
||||||
_: &mut Self::State,
|
_: &mut Self::State,
|
||||||
cx: &mut ViewContext<Self::State>,
|
cx: &mut ViewContext<Self::State>,
|
||||||
) -> Result<(LayoutId, Self::FrameState)> {
|
) -> Result<(LayoutId, Self::FrameState)> {
|
||||||
self.view.borrow_mut().layout(cx)
|
self.view.lock().layout(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
|
@ -129,7 +131,7 @@ impl<S: 'static> Element for AnyView<S> {
|
||||||
element: &mut Self::FrameState,
|
element: &mut Self::FrameState,
|
||||||
cx: &mut ViewContext<Self::State>,
|
cx: &mut ViewContext<Self::State>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.view.borrow_mut().paint(layout, element, cx)
|
self.view.lock().paint(layout, element, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
px, AppContext, AvailableSpace, Bounds, Context, Effect, EntityId, Handle, LayoutId,
|
px, AnyView, AppContext, AvailableSpace, Bounds, Context, Effect, Element, EntityId, Handle,
|
||||||
MainThreadOnly, Pixels, Platform, PlatformWindow, Point, Reference, Size, Style,
|
LayoutId, MainThreadOnly, Pixels, Platform, PlatformWindow, Point, Reference, Scene, Size,
|
||||||
TaffyLayoutEngine, TextStyle, TextStyleRefinement, WeakHandle, WindowOptions,
|
Style, TaffyLayoutEngine, TextStyle, TextStyleRefinement, WeakHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use std::{
|
use std::{any::TypeId, future, marker::PhantomData, sync::Arc};
|
||||||
any::{Any, TypeId},
|
use util::ResultExt;
|
||||||
marker::PhantomData,
|
|
||||||
sync::Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct AnyWindow {}
|
pub struct AnyWindow {}
|
||||||
|
|
||||||
|
@ -18,26 +15,51 @@ pub struct Window {
|
||||||
handle: AnyWindowHandle,
|
handle: AnyWindowHandle,
|
||||||
platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
|
platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
|
||||||
rem_size: Pixels,
|
rem_size: Pixels,
|
||||||
|
content_size: Size<Pixels>,
|
||||||
layout_engine: TaffyLayoutEngine,
|
layout_engine: TaffyLayoutEngine,
|
||||||
text_style_stack: Vec<TextStyleRefinement>,
|
text_style_stack: Vec<TextStyleRefinement>,
|
||||||
pub(crate) root_view: Option<Box<dyn Any + Send>>,
|
pub(crate) root_view: Option<AnyView<()>>,
|
||||||
mouse_position: Point<Pixels>,
|
mouse_position: Point<Pixels>,
|
||||||
|
pub(crate) scene: Scene,
|
||||||
pub(crate) dirty: bool,
|
pub(crate) dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(handle: AnyWindowHandle, options: WindowOptions, platform: &dyn Platform) -> Self {
|
pub fn new(
|
||||||
|
handle: AnyWindowHandle,
|
||||||
|
options: WindowOptions,
|
||||||
|
platform: &dyn Platform,
|
||||||
|
cx: &mut AppContext,
|
||||||
|
) -> Self {
|
||||||
let platform_window = platform.open_window(handle, options);
|
let platform_window = platform.open_window(handle, options);
|
||||||
let mouse_position = platform_window.mouse_position();
|
let mouse_position = platform_window.mouse_position();
|
||||||
|
let content_size = platform_window.content_size();
|
||||||
|
let scale_factor = platform_window.scale_factor();
|
||||||
|
platform_window.on_resize(Box::new({
|
||||||
|
let handle = handle;
|
||||||
|
let cx = cx.to_async();
|
||||||
|
move |content_size, scale_factor| {
|
||||||
|
cx.update_window(handle, |cx| {
|
||||||
|
cx.window.scene = Scene::new(scale_factor);
|
||||||
|
cx.window.content_size = content_size;
|
||||||
|
cx.window.dirty = true;
|
||||||
|
})
|
||||||
|
.log_err();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
let platform_window = MainThreadOnly::new(Arc::new(platform_window), platform.dispatcher());
|
let platform_window = MainThreadOnly::new(Arc::new(platform_window), platform.dispatcher());
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
handle,
|
handle,
|
||||||
platform_window,
|
platform_window,
|
||||||
rem_size: px(16.),
|
rem_size: px(16.),
|
||||||
|
content_size,
|
||||||
layout_engine: TaffyLayoutEngine::new(),
|
layout_engine: TaffyLayoutEngine::new(),
|
||||||
text_style_stack: Vec::new(),
|
text_style_stack: Vec::new(),
|
||||||
root_view: None,
|
root_view: None,
|
||||||
mouse_position,
|
mouse_position,
|
||||||
|
scene: Scene::new(scale_factor),
|
||||||
dirty: true,
|
dirty: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +88,28 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn draw(&mut self) -> Result<()> {
|
||||||
|
let unit_entity = self.unit_entity.clone();
|
||||||
|
self.update_entity(&unit_entity, |_, cx| {
|
||||||
|
let mut root_view = cx.window.root_view.take().unwrap();
|
||||||
|
let (root_layout_id, mut frame_state) = root_view.layout(&mut (), cx)?;
|
||||||
|
let available_space = cx.window.content_size.map(Into::into);
|
||||||
|
cx.window
|
||||||
|
.layout_engine
|
||||||
|
.compute_layout(root_layout_id, available_space)?;
|
||||||
|
let layout = cx.window.layout_engine.layout(root_layout_id)?;
|
||||||
|
root_view.paint(layout, &mut (), &mut frame_state, cx)?;
|
||||||
|
cx.window.root_view = Some(root_view);
|
||||||
|
let scene = cx.window.scene.take();
|
||||||
|
let _ = cx.window.platform_window.read(|platform_window| {
|
||||||
|
platform_window.draw(scene);
|
||||||
|
future::ready(())
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_layout(
|
pub fn request_layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
style: Style,
|
style: Style,
|
||||||
|
@ -140,6 +184,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
||||||
|
|
||||||
impl Context for WindowContext<'_, '_> {
|
impl Context for WindowContext<'_, '_> {
|
||||||
type EntityContext<'a, 'w, T: Send + Sync + 'static> = ViewContext<'a, 'w, T>;
|
type EntityContext<'a, 'w, T: Send + Sync + 'static> = ViewContext<'a, 'w, T>;
|
||||||
|
type Result<T> = T;
|
||||||
|
|
||||||
fn entity<T: Send + Sync + 'static>(
|
fn entity<T: Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -229,11 +274,11 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
|
pub fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
|
||||||
let unit_entity_id = self.unit_entity_id;
|
let entity_id = self.unit_entity.id;
|
||||||
let mut cx = ViewContext::mutable(
|
let mut cx = ViewContext::mutable(
|
||||||
&mut *self.window_cx.app,
|
&mut *self.window_cx.app,
|
||||||
&mut *self.window_cx.window,
|
&mut *self.window_cx.window,
|
||||||
unit_entity_id,
|
entity_id,
|
||||||
);
|
);
|
||||||
f(&mut cx)
|
f(&mut cx)
|
||||||
}
|
}
|
||||||
|
@ -281,6 +326,7 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
|
||||||
|
|
||||||
impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
|
impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
|
||||||
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ViewContext<'b, 'c, U>;
|
type EntityContext<'b, 'c, U: Send + Sync + 'static> = ViewContext<'b, 'c, U>;
|
||||||
|
type Result<U> = U;
|
||||||
|
|
||||||
fn entity<T2: Send + Sync + 'static>(
|
fn entity<T2: Send + Sync + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue