Wire up events and fix synthetic dragging

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Nathan Sobo 2021-03-21 09:44:14 -06:00
parent 04665800c0
commit 0c59937a65
4 changed files with 74 additions and 43 deletions

View File

@ -467,14 +467,14 @@ impl MutableAppContext {
pub fn dispatch_action(
&mut self,
window_id: usize,
responder_chain: &[usize],
path: &[usize],
name: &str,
arg: &dyn Any,
) -> bool {
self.pending_flushes += 1;
let mut halted_dispatch = false;
for view_id in responder_chain.iter().rev() {
for view_id in path.iter().rev() {
if let Some(mut view) = self
.ctx
.windows
@ -635,6 +635,29 @@ impl MutableAppContext {
self,
)));
{
let mut app = self.upgrade();
let presenter = presenter.clone();
window.on_event(Box::new(move |event, window| {
log::info!("event {:?}", event);
app.update(|ctx| {
ctx.pending_flushes += 1;
let actions = presenter
.borrow_mut()
.dispatch_event(event, ctx.downgrade());
for action in actions {
ctx.dispatch_action(
window_id,
&action.path,
action.name,
action.arg.as_ref(),
);
}
ctx.flush_effects();
})
}));
}
{
let mut app = self.upgrade();
let presenter = presenter.clone();

View File

@ -17,6 +17,7 @@ pub enum Foreground {
Test(smol::LocalExecutor<'static>),
}
#[must_use]
#[pin_project(project = ForegroundTaskProject)]
pub enum ForegroundTask<T> {
Platform(#[pin] async_task::Task<T>),

View File

@ -31,8 +31,8 @@ use std::{
cell::RefCell,
ffi::c_void,
mem, ptr,
rc::Rc,
time::{Duration, Instant},
rc::{Rc, Weak},
time::Duration,
};
use super::{geometry::RectFExt, renderer::Renderer};
@ -330,24 +330,33 @@ extern "C" fn dealloc_view(this: &Object, _: Sel) {
extern "C" fn handle_view_event(this: &Object, _: Sel, native_event: id) {
let window_state = unsafe { get_window_state(this) };
let mut window_state_borrow = window_state.as_ref().borrow_mut();
let weak_window_state = Rc::downgrade(&window_state);
let mut window_state = window_state.as_ref().borrow_mut();
let event = unsafe { Event::from_native(native_event, Some(window_state_borrow.size().y())) };
let event = unsafe { Event::from_native(native_event, Some(window_state.size().y())) };
if let Some(event) = event {
match event {
Event::LeftMouseDragged { position } => {
schedule_synthetic_drag(&&window_state, position)
window_state.synthetic_drag_counter += 1;
window_state
.executor
.spawn(synthetic_drag(
weak_window_state,
window_state.synthetic_drag_counter,
position,
))
.detach();
}
Event::LeftMouseUp { .. } => {
post_inc(&mut window_state_borrow.synthetic_drag_counter);
window_state.synthetic_drag_counter += 1;
}
_ => {}
}
if let Some(mut callback) = window_state_borrow.event_callback.take() {
callback(event, &mut *window_state_borrow);
window_state_borrow.event_callback = Some(callback);
if let Some(mut callback) = window_state.event_callback.take() {
callback(event, &mut *window_state);
window_state.event_callback = Some(callback);
}
}
}
@ -450,30 +459,23 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
}
}
fn schedule_synthetic_drag(window_state: &Rc<RefCell<WindowState>>, position: Vector2F) {
let weak_window_state = Rc::downgrade(window_state);
let mut window_state = window_state.as_ref().borrow_mut();
let drag_id = post_inc(&mut window_state.synthetic_drag_counter);
let instant = Instant::now() + Duration::from_millis(16);
window_state
.executor
.spawn(async move {
Timer::at(instant).await;
if let Some(window_state) = weak_window_state.upgrade() {
let mut window_state_borrow = window_state.as_ref().borrow_mut();
if window_state_borrow.synthetic_drag_counter == drag_id {
if let Some(mut callback) = window_state_borrow.event_callback.take() {
schedule_synthetic_drag(&window_state, position);
callback(
Event::LeftMouseDragged { position },
&mut *window_state_borrow,
);
window_state_borrow.event_callback = Some(callback);
}
async fn synthetic_drag(
window_state: Weak<RefCell<WindowState>>,
drag_id: usize,
position: Vector2F,
) {
loop {
Timer::after(Duration::from_millis(16)).await;
if let Some(window_state) = window_state.upgrade() {
let mut window_state = window_state.borrow_mut();
if window_state.synthetic_drag_counter == drag_id {
if let Some(mut callback) = window_state.event_callback.take() {
callback(Event::LeftMouseDragged { position }, &mut *window_state);
window_state.event_callback = Some(callback);
}
} else {
break;
}
})
.detach();
}
}
}

View File

@ -109,11 +109,7 @@ impl Presenter {
})
}
pub fn dispatch_event(
&self,
event: Event,
app: &AppContext,
) -> Vec<(usize, &'static str, Box<dyn Any>)> {
pub fn dispatch_event(&self, event: Event, app: &AppContext) -> Vec<ActionToDispatch> {
let mut event_ctx = EventContext {
rendered_views: &self.rendered_views,
actions: Vec::new(),
@ -128,6 +124,12 @@ impl Presenter {
}
}
pub struct ActionToDispatch {
pub path: Vec<usize>,
pub name: &'static str,
pub arg: Box<dyn Any>,
}
pub struct LayoutContext<'a> {
rendered_views: &'a mut HashMap<usize, Box<dyn Element>>,
parents: &'a mut HashMap<usize, usize>,
@ -184,7 +186,7 @@ impl<'a> PaintContext<'a> {
pub struct EventContext<'a> {
rendered_views: &'a HashMap<usize, Box<dyn Element>>,
actions: Vec<(usize, &'static str, Box<dyn Any>)>,
actions: Vec<ActionToDispatch>,
pub font_cache: &'a FontCache,
pub text_layout_cache: &'a TextLayoutCache,
view_stack: Vec<usize>,
@ -208,8 +210,11 @@ impl<'a> EventContext<'a> {
}
pub fn dispatch_action<A: 'static + Any>(&mut self, name: &'static str, arg: A) {
self.actions
.push((*self.view_stack.last().unwrap(), name, Box::new(arg)));
self.actions.push(ActionToDispatch {
path: self.view_stack.clone(),
name,
arg: Box::new(arg),
});
}
}