From 0c59937a65eb5d83d353cfdbe2f04bdeefca6dff Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 21 Mar 2021 09:44:14 -0600 Subject: [PATCH] Wire up events and fix synthetic dragging Co-Authored-By: Antonio Scandurra --- gpui/src/app.rs | 27 ++++++++++++- gpui/src/executor.rs | 1 + gpui/src/platform/mac/window.rs | 68 +++++++++++++++++---------------- gpui/src/presenter.rs | 21 ++++++---- 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 14d4aa3c7c..ccf474b1b9 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -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(); diff --git a/gpui/src/executor.rs b/gpui/src/executor.rs index e9900ead11..618bbe059c 100644 --- a/gpui/src/executor.rs +++ b/gpui/src/executor.rs @@ -17,6 +17,7 @@ pub enum Foreground { Test(smol::LocalExecutor<'static>), } +#[must_use] #[pin_project(project = ForegroundTaskProject)] pub enum ForegroundTask { Platform(#[pin] async_task::Task), diff --git a/gpui/src/platform/mac/window.rs b/gpui/src/platform/mac/window.rs index 0aa74c990d..1277b747ac 100644 --- a/gpui/src/platform/mac/window.rs +++ b/gpui/src/platform/mac/window.rs @@ -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>, 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>, + 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(); + } + } } diff --git a/gpui/src/presenter.rs b/gpui/src/presenter.rs index 71fedbc1b8..0b8dd7f3b3 100644 --- a/gpui/src/presenter.rs +++ b/gpui/src/presenter.rs @@ -109,11 +109,7 @@ impl Presenter { }) } - pub fn dispatch_event( - &self, - event: Event, - app: &AppContext, - ) -> Vec<(usize, &'static str, Box)> { + pub fn dispatch_event(&self, event: Event, app: &AppContext) -> Vec { 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, + pub name: &'static str, + pub arg: Box, +} + pub struct LayoutContext<'a> { rendered_views: &'a mut HashMap>, parents: &'a mut HashMap, @@ -184,7 +186,7 @@ impl<'a> PaintContext<'a> { pub struct EventContext<'a> { rendered_views: &'a HashMap>, - actions: Vec<(usize, &'static str, Box)>, + actions: Vec, pub font_cache: &'a FontCache, pub text_layout_cache: &'a TextLayoutCache, view_stack: Vec, @@ -208,8 +210,11 @@ impl<'a> EventContext<'a> { } pub fn dispatch_action(&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), + }); } }