From ffa3362e166fed44d49cc3418c997ccc7fd0994b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 19 Oct 2023 15:36:31 +0200 Subject: [PATCH] Checkpoint --- crates/gpui3/src/elements/div.rs | 13 ++-- crates/gpui3/src/events.rs | 31 ++++---- crates/gpui3/src/focus.rs | 26 +++++-- crates/gpui3/src/interactive.rs | 16 ++-- crates/gpui3/src/window.rs | 126 ++++++++++++------------------- 5 files changed, 102 insertions(+), 110 deletions(-) diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index ae81ec51ef94826a8fad9b5ee3eeb5c8aa217f63..938325ac89406786594638750c06564d8dcec4f6 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -423,18 +423,21 @@ where element_state: Option, cx: &mut ViewContext, ) -> Self::ElementState { + let key_listeners = mem::take(&mut self.listeners.key); + let focus_listeners = mem::take(&mut self.listeners.focus); cx.with_focus( self.focusability.focus_handle().cloned(), - mem::take(&mut self.listeners.key_down), - mem::take(&mut self.listeners.key_up), - mem::take(&mut self.listeners.focus), + &key_listeners, + &focus_listeners, |cx| { for child in &mut self.children { child.initialize(view_state, cx); } - element_state.unwrap_or_default() }, - ) + ); + self.listeners.key = key_listeners; + self.listeners.focus = focus_listeners; + element_state.unwrap_or_default() } fn layout( diff --git a/crates/gpui3/src/events.rs b/crates/gpui3/src/events.rs index 8adfba37ada3cd9038378a8f421e352433b001ce..58228b4175139d2da20b032e8acb8e24ec1a32d4 100644 --- a/crates/gpui3/src/events.rs +++ b/crates/gpui3/src/events.rs @@ -2,7 +2,11 @@ use crate::{ point, Bounds, DispatchPhase, FocusHandle, Keystroke, Modifiers, Pixels, Point, ViewContext, }; use smallvec::SmallVec; -use std::{any::Any, ops::Deref}; +use std::{ + any::{Any, TypeId}, + ops::Deref, + sync::Arc, +}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct KeyDownEvent { @@ -221,43 +225,40 @@ pub struct FocusEvent { pub focused: Option, } -pub type MouseDownListener = Box< +pub type MouseDownListener = Arc< dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) + Send + Sync + 'static, >; -pub type MouseUpListener = Box< +pub type MouseUpListener = Arc< dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) + Send + Sync + 'static, >; pub type MouseClickListener = - Box) + Send + Sync + 'static>; + Arc) + Send + Sync + 'static>; -pub type MouseMoveListener = Box< +pub type MouseMoveListener = Arc< dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) + Send + Sync + 'static, >; -pub type ScrollWheelListener = Box< +pub type ScrollWheelListener = Arc< dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) + Send + Sync + 'static, >; -pub type KeyDownListener = - Box) + Send + Sync + 'static>; - -pub type KeyUpListener = - Box) + Send + Sync + 'static>; +pub type KeyListener = + Arc) + Send + Sync + 'static>; pub type FocusListener = - Box) + Send + Sync + 'static>; + Arc) + Send + Sync + 'static>; pub struct EventListeners { pub mouse_down: SmallVec<[MouseDownListener; 2]>, @@ -265,8 +266,7 @@ pub struct EventListeners { pub mouse_click: SmallVec<[MouseClickListener; 2]>, pub mouse_move: SmallVec<[MouseMoveListener; 2]>, pub scroll_wheel: SmallVec<[ScrollWheelListener; 2]>, - pub key_down: SmallVec<[KeyDownListener; 2]>, - pub key_up: SmallVec<[KeyUpListener; 2]>, + pub key: SmallVec<[(TypeId, KeyListener); 32]>, pub focus: SmallVec<[FocusListener; 2]>, } @@ -278,8 +278,7 @@ impl Default for EventListeners { mouse_click: SmallVec::new(), mouse_move: SmallVec::new(), scroll_wheel: SmallVec::new(), - key_down: SmallVec::new(), - key_up: SmallVec::new(), + key: SmallVec::new(), focus: SmallVec::new(), } } diff --git a/crates/gpui3/src/focus.rs b/crates/gpui3/src/focus.rs index 12f0679655f5e7066d6b78ee47065b8edf2ad6e9..ecfda740f2296bc4e2aa24abe54210854793af18 100644 --- a/crates/gpui3/src/focus.rs +++ b/crates/gpui3/src/focus.rs @@ -1,3 +1,5 @@ +use std::{any::TypeId, sync::Arc}; + use crate::{ DispatchPhase, FocusEvent, FocusHandle, Interactive, KeyDownEvent, KeyUpEvent, StyleRefinement, ViewContext, @@ -46,7 +48,7 @@ pub trait Focus: Interactive { let handle = self.handle().clone(); self.listeners() .focus - .push(Box::new(move |view, event, cx| { + .push(Arc::new(move |view, event, cx| { if event.focused.as_ref() == Some(&handle) { listener(view, event, cx) } @@ -67,7 +69,7 @@ pub trait Focus: Interactive { let handle = self.handle().clone(); self.listeners() .focus - .push(Box::new(move |view, event, cx| { + .push(Arc::new(move |view, event, cx| { if event.blurred.as_ref() == Some(&handle) { listener(view, event, cx) } @@ -88,7 +90,7 @@ pub trait Focus: Interactive { let handle = self.handle().clone(); self.listeners() .focus - .push(Box::new(move |view, event, cx| { + .push(Arc::new(move |view, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -118,7 +120,7 @@ pub trait Focus: Interactive { let handle = self.handle().clone(); self.listeners() .focus - .push(Box::new(move |view, event, cx| { + .push(Arc::new(move |view, event, cx| { let descendant_blurred = event .blurred .as_ref() @@ -148,7 +150,13 @@ pub trait Focus: Interactive { where Self: Sized, { - self.listeners().key_down.push(Box::new(listener)); + self.listeners().key.push(( + TypeId::of::(), + Arc::new(move |view, event, phase, cx| { + let event = event.downcast_ref().unwrap(); + listener(view, event, phase, cx) + }), + )); self } @@ -162,7 +170,13 @@ pub trait Focus: Interactive { where Self: Sized, { - self.listeners().key_up.push(Box::new(listener)); + self.listeners().key.push(( + TypeId::of::(), + Arc::new(move |view, event, phase, cx| { + let event = event.downcast_ref().unwrap(); + listener(view, event, phase, cx) + }), + )); self } } diff --git a/crates/gpui3/src/interactive.rs b/crates/gpui3/src/interactive.rs index f328f22cc0606ccc7708a4ab785e479ff7392785..ac150652dd1e5d9bbd27c3b6c247c2737954ba8a 100644 --- a/crates/gpui3/src/interactive.rs +++ b/crates/gpui3/src/interactive.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::{ DispatchPhase, Element, EventListeners, MouseButton, MouseClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext, @@ -19,7 +21,7 @@ pub trait Interactive: Element { { self.listeners() .mouse_down - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button && bounds.contains_point(&event.position) @@ -43,7 +45,7 @@ pub trait Interactive: Element { { self.listeners() .mouse_up - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button && bounds.contains_point(&event.position) @@ -67,7 +69,7 @@ pub trait Interactive: Element { { self.listeners() .mouse_down - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture && event.button == button && !bounds.contains_point(&event.position) @@ -91,7 +93,7 @@ pub trait Interactive: Element { { self.listeners() .mouse_up - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture && event.button == button && !bounds.contains_point(&event.position) @@ -114,7 +116,7 @@ pub trait Interactive: Element { { self.listeners() .mouse_move - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { handler(view, event, cx); } @@ -134,7 +136,7 @@ pub trait Interactive: Element { { self.listeners() .scroll_wheel - .push(Box::new(move |view, event, bounds, phase, cx| { + .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { handler(view, event, cx); } @@ -156,7 +158,7 @@ pub trait Click: Interactive { { self.listeners() .mouse_click - .push(Box::new(move |view, event, cx| handler(view, event, cx))); + .push(Arc::new(move |view, event, cx| handler(view, event, cx))); self } } diff --git a/crates/gpui3/src/window.rs b/crates/gpui3/src/window.rs index e0edbac4489511bf5911877e6e75c25d5203cb92..ca3acc41ecf5c627f844037c07696be2911d2181 100644 --- a/crates/gpui3/src/window.rs +++ b/crates/gpui3/src/window.rs @@ -2,12 +2,11 @@ use crate::{ px, size, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, BorrowAppContext, Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId, Edges, Effect, Element, EntityId, EventEmitter, FocusEvent, FocusListener, FontId, GlobalElementId, GlyphId, Handle, Hsla, - ImageData, InputEvent, IsZero, KeyDownEvent, KeyDownListener, KeyUpEvent, KeyUpListener, - LayoutId, MainThread, MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels, Platform, - PlatformAtlas, PlatformWindow, Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, - RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, - Style, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle, - WindowOptions, SUBPIXEL_VARIANTS, + ImageData, InputEvent, IsZero, KeyListener, LayoutId, MainThread, MainThreadOnly, + MonochromeSprite, MouseMoveEvent, Path, Pixels, Platform, PlatformAtlas, PlatformWindow, Point, + PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams, RenderSvgParams, + ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, Subscription, TaffyLayoutEngine, + Task, Underline, UnderlineStyle, WeakHandle, WindowOptions, SUBPIXEL_VARIANTS, }; use anyhow::Result; use collections::HashMap; @@ -45,15 +44,8 @@ pub enum DispatchPhase { Capture, } -type AnyMouseEventListener = - Box; -type AnyKeyboardEventListener = - Box; -type AnyFocusListener = Box; -type AnyKeyDownListener = - Box; -type AnyKeyUpListener = - Box; +type AnyListener = Arc; +type AnyFocusListener = Arc; slotmap::new_key_type! { pub struct FocusId; } @@ -153,9 +145,10 @@ pub struct Window { element_states: HashMap, z_index_stack: StackingOrder, content_mask_stack: Vec>, - mouse_listeners: HashMap>, - keyboard_listeners: HashMap>, - focus_stack: Vec, + mouse_listeners: HashMap>, + key_listeners: HashMap>, + push_key_listeners: bool, + focus_stack: Vec, focus_parents_by_child: HashMap, pub(crate) focus_listeners: Vec, pub(crate) focus_handles: Arc>>, @@ -226,7 +219,8 @@ impl Window { z_index_stack: StackingOrder(SmallVec::new()), content_mask_stack: Vec::new(), mouse_listeners: HashMap::default(), - keyboard_listeners: HashMap::default(), + key_listeners: HashMap::default(), + push_key_listeners: true, focus_stack: Vec::new(), focus_parents_by_child: HashMap::default(), focus_listeners: Vec::new(), @@ -262,12 +256,6 @@ impl ContentMask { } } -struct FocusStackFrame { - handle: FocusHandle, - key_down_listeners: SmallVec<[AnyKeyDownListener; 2]>, - key_up_listeners: SmallVec<[AnyKeyUpListener; 2]>, -} - pub struct WindowContext<'a, 'w> { app: Reference<'a, AppContext>, pub(crate) window: Reference<'w, Window>, @@ -468,7 +456,7 @@ impl<'a, 'w> WindowContext<'a, 'w> { .or_default() .push(( order, - Box::new(move |event: &dyn Any, phase, cx| { + Arc::new(move |event: &dyn Any, phase, cx| { handler(event.downcast_ref().unwrap(), phase, cx) }), )) @@ -479,10 +467,10 @@ impl<'a, 'w> WindowContext<'a, 'w> { handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + Send + Sync + 'static, ) { self.window - .keyboard_listeners + .key_listeners .entry(TypeId::of::()) .or_default() - .push(Box::new(move |event: &dyn Any, phase, cx| { + .push(Arc::new(move |event: &dyn Any, phase, cx| { handler(event.downcast_ref().unwrap(), phase, cx) })) } @@ -833,8 +821,9 @@ impl<'a, 'w> WindowContext<'a, 'w> { // Clear focus state, because we determine what is focused when the new elements // in the upcoming frame are initialized. window.focus_listeners.clear(); - window.keyboard_listeners.values_mut().for_each(Vec::clear); + window.key_listeners.values_mut().for_each(Vec::clear); window.focus_parents_by_child.clear(); + window.push_key_listeners = true; } fn end_frame(&mut self) { @@ -893,7 +882,7 @@ impl<'a, 'w> WindowContext<'a, 'w> { } else if let Some(any_keyboard_event) = event.keyboard_event() { if let Some(mut handlers) = self .window - .keyboard_listeners + .key_listeners .remove(&any_keyboard_event.type_id()) { for handler in &handlers { @@ -914,13 +903,13 @@ impl<'a, 'w> WindowContext<'a, 'w> { handlers.extend( self.window - .keyboard_listeners + .key_listeners .get_mut(&any_keyboard_event.type_id()) .into_iter() .flat_map(|handlers| handlers.drain(..)), ); self.window - .keyboard_listeners + .key_listeners .insert(any_keyboard_event.type_id(), handlers); } } @@ -1221,9 +1210,8 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { pub fn with_focus( &mut self, focus_handle: Option, - key_down: impl IntoIterator>, - key_up: impl IntoIterator>, - focus: impl IntoIterator>, + key_listeners: &[(TypeId, KeyListener)], + focus_listeners: &[FocusListener], f: impl FnOnce(&mut Self) -> R, ) -> R { let Some(focus_handle) = focus_handle else { @@ -1233,63 +1221,49 @@ impl<'a, 'w, V: Send + Sync + 'static> ViewContext<'a, 'w, V> { let handle = self.handle(); let window = &mut *self.window; - for listener in focus { + for listener in focus_listeners.iter().cloned() { let handle = handle.clone(); - window.focus_listeners.push(Box::new(move |event, cx| { + window.focus_listeners.push(Arc::new(move |event, cx| { handle .update(cx, |view, cx| listener(view, event, cx)) .log_err(); })); } - let mut focus_stack = mem::take(&mut window.focus_stack); - if let Some(parent_frame) = focus_stack.last() { + if let Some(parent_focus_id) = window.focus_stack.last() { window .focus_parents_by_child - .insert(focus_handle.id, parent_frame.handle.id); - } - - let mut frame = FocusStackFrame { - handle: focus_handle.clone(), - key_down_listeners: SmallVec::new(), - key_up_listeners: SmallVec::new(), - }; - - for listener in key_down { - let handle = handle.clone(); - frame - .key_down_listeners - .push(Box::new(move |event, phase, cx| { - handle - .update(cx, |view, cx| listener(view, event, phase, cx)) - .log_err(); - })); + .insert(focus_handle.id, *parent_focus_id); } - for listener in key_up { - let handle = handle.clone(); - frame - .key_up_listeners - .push(Box::new(move |event, phase, cx| { - handle - .update(cx, |view, cx| listener(view, event, phase, cx)) - .log_err(); - })); + window.focus_stack.push(focus_handle.id); + + if window.push_key_listeners { + for (type_id, listener) in key_listeners { + let handle = handle.clone(); + let listener = listener.clone(); + window + .key_listeners + .entry(*type_id) + .or_default() + .push(Arc::new(move |event, phase, cx| { + handle + .update(cx, |view, cx| listener(view, event, phase, cx)) + .log_err(); + })); + } } - focus_stack.push(frame); if Some(focus_handle.id) == window.focus { - for focus_frame in &mut focus_stack { - for listener in focus_frame.key_down_listeners.drain(..) { - self.window_cx.on_keyboard_event(listener); - } - for listener in focus_frame.key_up_listeners.drain(..) { - self.window_cx.on_keyboard_event(listener); - } - } + window.push_key_listeners = false; } - self.window.focus_stack = focus_stack; let result = f(self); + + if self.window.push_key_listeners { + for (type_id, _) in key_listeners { + self.window.key_listeners.get_mut(type_id).unwrap().pop(); + } + } self.window.focus_stack.pop(); result }