diff --git a/crates/gpui3/src/elements/div.rs b/crates/gpui3/src/elements/div.rs index 06192d82e43f2da1b2a26d80d1111dc5b258f813..4ae0ae72b6c9d889038fe652045c5b53899b8ebe 100644 --- a/crates/gpui3/src/elements/div.rs +++ b/crates/gpui3/src/elements/div.rs @@ -1,7 +1,7 @@ use crate::{ Active, Anonymous, AnyElement, AppContext, BorrowWindow, Bounds, Click, DispatchPhase, Element, - ElementFocusability, ElementId, ElementIdentity, EventListeners, Focus, FocusHandle, - FocusListeners, Focusable, GlobalElementId, Hover, Identified, Interactive, IntoAnyElement, + ElementFocusability, ElementId, ElementIdentity, Focus, FocusHandle, FocusListeners, Focusable, + GlobalElementId, Hover, Identified, Interactive, InteractiveState, IntoAnyElement, KeyDownEvent, KeyMatch, LayoutId, MouseClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent, NonFocusable, Overflow, ParentElement, Pixels, Point, ScrollWheelEvent, SharedString, Style, StyleRefinement, Styled, ViewContext, @@ -78,7 +78,7 @@ pub struct Div< focus_style: StyleRefinement, focus_in_style: StyleRefinement, in_focus_style: StyleRefinement, - listeners: EventListeners, + interactive_state: InteractiveState, } pub fn div() -> Div @@ -98,7 +98,7 @@ where focus_style: StyleRefinement::default(), focus_in_style: StyleRefinement::default(), in_focus_style: StyleRefinement::default(), - listeners: EventListeners::default(), + interactive_state: InteractiveState::default(), } } @@ -126,7 +126,7 @@ where focus_style: self.focus_style, focus_in_style: self.focus_in_style, in_focus_style: self.in_focus_style, - listeners: self.listeners, + interactive_state: self.interactive_state, } } } @@ -296,7 +296,7 @@ where pending_click: Arc>>, cx: &mut ViewContext, ) { - let click_listeners = mem::take(&mut self.listeners.mouse_click); + let click_listeners = mem::take(&mut self.interactive_state.mouse_click); let mouse_down = pending_click.lock().clone(); if let Some(mouse_down) = mouse_down { @@ -333,25 +333,25 @@ where }) } - for listener in mem::take(&mut self.listeners.mouse_down) { + for listener in mem::take(&mut self.interactive_state.mouse_down) { cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in mem::take(&mut self.listeners.mouse_up) { + for listener in mem::take(&mut self.interactive_state.mouse_up) { cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in mem::take(&mut self.listeners.mouse_move) { + for listener in mem::take(&mut self.interactive_state.mouse_move) { cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) } - for listener in mem::take(&mut self.listeners.scroll_wheel) { + for listener in mem::take(&mut self.interactive_state.scroll_wheel) { cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| { listener(state, event, &bounds, phase, cx); }) @@ -378,7 +378,7 @@ where focus_style: self.focus_style, focus_in_style: self.focus_in_style, in_focus_style: self.in_focus_style, - listeners: self.listeners, + interactive_state: self.interactive_state, } } } @@ -431,7 +431,7 @@ where self.with_element_id(cx, |this, global_id, cx| { let element_state = element_state.unwrap_or_default(); - let mut key_listeners = mem::take(&mut this.listeners.key); + let mut key_listeners = mem::take(&mut this.interactive_state.key); if let Some(global_id) = global_id { key_listeners.push(( TypeId::of::(), @@ -457,7 +457,7 @@ where } }); }); - this.listeners.key = key_listeners; + this.interactive_state.key = key_listeners; element_state }) @@ -584,8 +584,8 @@ where F: ElementFocusability, V: 'static + Send + Sync, { - fn listeners(&mut self) -> &mut EventListeners { - &mut self.listeners + fn interactive_state(&mut self) -> &mut InteractiveState { + &mut self.interactive_state } } diff --git a/crates/gpui3/src/elements/img.rs b/crates/gpui3/src/elements/img.rs index b0a8fe2fb037e8d388b2ccab107d0a2383a26f2e..d5db8032d725b2d9a52f25ac767fdf225649ca71 100644 --- a/crates/gpui3/src/elements/img.rs +++ b/crates/gpui3/src/elements/img.rs @@ -1,7 +1,7 @@ use crate::{ div, Active, Anonymous, AnyElement, BorrowWindow, Bounds, Click, Div, DivState, Element, - ElementFocusability, ElementId, ElementIdentity, EventListeners, Focus, FocusListeners, - Focusable, Hover, Identified, Interactive, IntoAnyElement, LayoutId, NonFocusable, Pixels, + ElementFocusability, ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover, + Identified, Interactive, InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, StyleRefinement, Styled, ViewContext, }; use futures::FutureExt; @@ -156,8 +156,8 @@ where I: ElementIdentity, F: ElementFocusability, { - fn listeners(&mut self) -> &mut EventListeners { - self.base.listeners() + fn interactive_state(&mut self) -> &mut InteractiveState { + self.base.interactive_state() } } diff --git a/crates/gpui3/src/elements/svg.rs b/crates/gpui3/src/elements/svg.rs index b8c02df1b6e379cb2a480e93134a1133d930cb9b..b3d8c66b19023dd593c4fdedd5c1f117dfe414d9 100644 --- a/crates/gpui3/src/elements/svg.rs +++ b/crates/gpui3/src/elements/svg.rs @@ -1,7 +1,7 @@ use crate::{ div, Active, Anonymous, AnyElement, Bounds, Click, Div, DivState, Element, ElementFocusability, - ElementId, ElementIdentity, EventListeners, Focus, FocusListeners, Focusable, Hover, - Identified, Interactive, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, + ElementId, ElementIdentity, Focus, FocusListeners, Focusable, Hover, Identified, Interactive, + InteractiveState, IntoAnyElement, LayoutId, NonFocusable, Pixels, SharedString, StyleRefinement, Styled, ViewContext, }; use util::ResultExt; @@ -130,8 +130,8 @@ where I: ElementIdentity, F: ElementFocusability, { - fn listeners(&mut self) -> &mut EventListeners { - self.base.listeners() + fn interactive_state(&mut self) -> &mut InteractiveState { + self.base.interactive_state() } } diff --git a/crates/gpui3/src/events.rs b/crates/gpui3/src/events.rs deleted file mode 100644 index 718ababf031f41c3dfadfe84d02fb24c3f9f110f..0000000000000000000000000000000000000000 --- a/crates/gpui3/src/events.rs +++ /dev/null @@ -1,291 +0,0 @@ -use crate::{ - point, Action, Bounds, DispatchContext, DispatchPhase, FocusHandle, Keystroke, Modifiers, - Pixels, Point, ViewContext, -}; -use smallvec::SmallVec; -use std::{ - any::{Any, TypeId}, - ops::Deref, - sync::Arc, -}; - -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct KeyDownEvent { - pub keystroke: Keystroke, - pub is_held: bool, -} - -#[derive(Clone, Debug)] -pub struct KeyUpEvent { - pub keystroke: Keystroke, -} - -#[derive(Clone, Debug, Default)] -pub struct ModifiersChangedEvent { - pub modifiers: Modifiers, -} - -impl Deref for ModifiersChangedEvent { - type Target = Modifiers; - - fn deref(&self) -> &Self::Target { - &self.modifiers - } -} - -/// The phase of a touch motion event. -/// Based on the winit enum of the same name. -#[derive(Clone, Copy, Debug)] -pub enum TouchPhase { - Started, - Moved, - Ended, -} - -#[derive(Clone, Debug, Default)] -pub struct MouseDownEvent { - pub button: MouseButton, - pub position: Point, - pub modifiers: Modifiers, - pub click_count: usize, -} - -#[derive(Clone, Debug, Default)] -pub struct MouseUpEvent { - pub button: MouseButton, - pub position: Point, - pub modifiers: Modifiers, - pub click_count: usize, -} - -#[derive(Clone, Debug, Default)] -pub struct MouseClickEvent { - pub down: MouseDownEvent, - pub up: MouseUpEvent, -} - -#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] -pub enum MouseButton { - Left, - Right, - Middle, - Navigate(NavigationDirection), -} - -impl MouseButton { - pub fn all() -> Vec { - vec![ - MouseButton::Left, - MouseButton::Right, - MouseButton::Middle, - MouseButton::Navigate(NavigationDirection::Back), - MouseButton::Navigate(NavigationDirection::Forward), - ] - } -} - -impl Default for MouseButton { - fn default() -> Self { - Self::Left - } -} - -#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] -pub enum NavigationDirection { - Back, - Forward, -} - -impl Default for NavigationDirection { - fn default() -> Self { - Self::Back - } -} - -#[derive(Clone, Debug, Default)] -pub struct MouseMoveEvent { - pub position: Point, - pub pressed_button: Option, - pub modifiers: Modifiers, -} - -#[derive(Clone, Debug)] -pub struct ScrollWheelEvent { - pub position: Point, - pub delta: ScrollDelta, - pub modifiers: Modifiers, - pub touch_phase: TouchPhase, -} - -impl Deref for ScrollWheelEvent { - type Target = Modifiers; - - fn deref(&self) -> &Self::Target { - &self.modifiers - } -} - -#[derive(Clone, Copy, Debug)] -pub enum ScrollDelta { - Pixels(Point), - Lines(Point), -} - -impl Default for ScrollDelta { - fn default() -> Self { - Self::Lines(Default::default()) - } -} - -impl ScrollDelta { - pub fn precise(&self) -> bool { - match self { - ScrollDelta::Pixels(_) => true, - ScrollDelta::Lines(_) => false, - } - } - - pub fn pixel_delta(&self, line_height: Pixels) -> Point { - match self { - ScrollDelta::Pixels(delta) => *delta, - ScrollDelta::Lines(delta) => point(line_height * delta.x, line_height * delta.y), - } - } -} - -#[derive(Clone, Debug, Default)] -pub struct MouseExitEvent { - pub position: Point, - pub pressed_button: Option, - pub modifiers: Modifiers, -} - -impl Deref for MouseExitEvent { - type Target = Modifiers; - - fn deref(&self) -> &Self::Target { - &self.modifiers - } -} - -#[derive(Clone, Debug)] -pub enum InputEvent { - KeyDown(KeyDownEvent), - KeyUp(KeyUpEvent), - ModifiersChanged(ModifiersChangedEvent), - MouseDown(MouseDownEvent), - MouseUp(MouseUpEvent), - MouseMoved(MouseMoveEvent), - MouseExited(MouseExitEvent), - ScrollWheel(ScrollWheelEvent), -} - -impl InputEvent { - pub fn position(&self) -> Option> { - match self { - InputEvent::KeyDown { .. } => None, - InputEvent::KeyUp { .. } => None, - InputEvent::ModifiersChanged { .. } => None, - InputEvent::MouseDown(event) => Some(event.position), - InputEvent::MouseUp(event) => Some(event.position), - InputEvent::MouseMoved(event) => Some(event.position), - InputEvent::MouseExited(event) => Some(event.position), - InputEvent::ScrollWheel(event) => Some(event.position), - } - } - - pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> { - match self { - InputEvent::KeyDown { .. } => None, - InputEvent::KeyUp { .. } => None, - InputEvent::ModifiersChanged { .. } => None, - InputEvent::MouseDown(event) => Some(event), - InputEvent::MouseUp(event) => Some(event), - InputEvent::MouseMoved(event) => Some(event), - InputEvent::MouseExited(event) => Some(event), - InputEvent::ScrollWheel(event) => Some(event), - } - } - - pub fn keyboard_event<'a>(&'a self) -> Option<&'a dyn Any> { - match self { - InputEvent::KeyDown(event) => Some(event), - InputEvent::KeyUp(event) => Some(event), - InputEvent::ModifiersChanged(event) => Some(event), - InputEvent::MouseDown(_) => None, - InputEvent::MouseUp(_) => None, - InputEvent::MouseMoved(_) => None, - InputEvent::MouseExited(_) => None, - InputEvent::ScrollWheel(_) => None, - } - } -} - -pub struct FocusEvent { - pub blurred: Option, - pub focused: Option, -} - -pub type MouseDownListener = Arc< - dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) - + Send - + Sync - + 'static, ->; -pub type MouseUpListener = Arc< - dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) - + Send - + Sync - + 'static, ->; -pub type MouseClickListener = - Arc) + Send + Sync + 'static>; - -pub type MouseMoveListener = Arc< - dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) - + Send - + Sync - + 'static, ->; - -pub type ScrollWheelListener = Arc< - dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) - + Send - + Sync - + 'static, ->; - -pub type KeyListener = Arc< - dyn Fn( - &mut V, - &dyn Any, - &[&DispatchContext], - DispatchPhase, - &mut ViewContext, - ) -> Option> - + Send - + Sync - + 'static, ->; - -pub struct EventListeners { - pub mouse_down: SmallVec<[MouseDownListener; 2]>, - pub mouse_up: SmallVec<[MouseUpListener; 2]>, - pub mouse_click: SmallVec<[MouseClickListener; 2]>, - pub mouse_move: SmallVec<[MouseMoveListener; 2]>, - pub scroll_wheel: SmallVec<[ScrollWheelListener; 2]>, - pub key: SmallVec<[(TypeId, KeyListener); 32]>, -} - -impl Default for EventListeners { - fn default() -> Self { - Self { - mouse_down: SmallVec::new(), - mouse_up: SmallVec::new(), - mouse_click: SmallVec::new(), - mouse_move: SmallVec::new(), - scroll_wheel: SmallVec::new(), - key: SmallVec::new(), - } - } -} diff --git a/crates/gpui3/src/gpui3.rs b/crates/gpui3/src/gpui3.rs index fbc9d8d0f2af3141d3b181828d2ed0b9ea5f8d4d..800593e4c189641f9a6bce65ceb982aa598ad08a 100644 --- a/crates/gpui3/src/gpui3.rs +++ b/crates/gpui3/src/gpui3.rs @@ -5,7 +5,6 @@ mod assets; mod color; mod element; mod elements; -mod events; mod executor; mod focus; mod geometry; @@ -33,7 +32,6 @@ pub use assets::*; pub use color::*; pub use element::*; pub use elements::*; -pub use events::*; pub use executor::*; pub use focus::*; pub use geometry::*; diff --git a/crates/gpui3/src/interactive.rs b/crates/gpui3/src/interactive.rs index 40e815ccb9f7d5585049ebc562e179c04afee966..d67a5d75787348cf6de01a8e6e0c105558affe53 100644 --- a/crates/gpui3/src/interactive.rs +++ b/crates/gpui3/src/interactive.rs @@ -1,12 +1,17 @@ -use std::{any::TypeId, sync::Arc}; +use smallvec::SmallVec; use crate::{ - DispatchPhase, Element, EventListeners, KeyDownEvent, KeyUpEvent, MouseButton, MouseClickEvent, - MouseDownEvent, MouseMoveEvent, MouseUpEvent, ScrollWheelEvent, ViewContext, + point, Action, Bounds, DispatchContext, DispatchPhase, Element, FocusHandle, Keystroke, + Modifiers, Pixels, Point, ViewContext, +}; +use std::{ + any::{Any, TypeId}, + ops::Deref, + sync::Arc, }; pub trait Interactive: Element { - fn listeners(&mut self) -> &mut EventListeners; + fn interactive_state(&mut self) -> &mut InteractiveState; fn on_mouse_down( mut self, @@ -19,16 +24,16 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() - .mouse_down - .push(Arc::new(move |view, event, bounds, phase, cx| { + self.interactive_state().mouse_down.push(Arc::new( + move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button && bounds.contains_point(&event.position) { handler(view, event, cx) } - })); + }, + )); self } @@ -43,7 +48,7 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() + self.interactive_state() .mouse_up .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble @@ -67,16 +72,16 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() - .mouse_down - .push(Arc::new(move |view, event, bounds, phase, cx| { + self.interactive_state().mouse_down.push(Arc::new( + move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture && event.button == button && !bounds.contains_point(&event.position) { handler(view, event, cx) } - })); + }, + )); self } @@ -91,7 +96,7 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() + self.interactive_state() .mouse_up .push(Arc::new(move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Capture @@ -114,13 +119,13 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() - .mouse_move - .push(Arc::new(move |view, event, bounds, phase, cx| { + self.interactive_state().mouse_move.push(Arc::new( + move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { handler(view, event, cx); } - })); + }, + )); self } @@ -134,13 +139,13 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners() - .scroll_wheel - .push(Arc::new(move |view, event, bounds, phase, cx| { + self.interactive_state().scroll_wheel.push(Arc::new( + move |view, event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { handler(view, event, cx); } - })); + }, + )); self } @@ -158,7 +163,7 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners().key.push(( + self.interactive_state().key.push(( TypeId::of::(), Arc::new(move |view, event, _, phase, cx| { let event = event.downcast_ref().unwrap(); @@ -179,7 +184,7 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners().key.push(( + self.interactive_state().key.push(( TypeId::of::(), Arc::new(move |view, event, _, phase, cx| { let event = event.downcast_ref().unwrap(); @@ -200,7 +205,7 @@ pub trait Interactive: Element { where Self: Sized, { - self.listeners().key.push(( + self.interactive_state().key.push(( TypeId::of::(), Arc::new(move |view, event, _, phase, cx| { let event = event.downcast_ref().unwrap(); @@ -223,9 +228,290 @@ pub trait Click: Interactive { where Self: Sized, { - self.listeners() + self.interactive_state() .mouse_click .push(Arc::new(move |view, event, cx| handler(view, event, cx))); self } } + +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct KeyDownEvent { + pub keystroke: Keystroke, + pub is_held: bool, +} + +#[derive(Clone, Debug)] +pub struct KeyUpEvent { + pub keystroke: Keystroke, +} + +#[derive(Clone, Debug, Default)] +pub struct ModifiersChangedEvent { + pub modifiers: Modifiers, +} + +impl Deref for ModifiersChangedEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +/// The phase of a touch motion event. +/// Based on the winit enum of the same name. +#[derive(Clone, Copy, Debug)] +pub enum TouchPhase { + Started, + Moved, + Ended, +} + +#[derive(Clone, Debug, Default)] +pub struct MouseDownEvent { + pub button: MouseButton, + pub position: Point, + pub modifiers: Modifiers, + pub click_count: usize, +} + +#[derive(Clone, Debug, Default)] +pub struct MouseUpEvent { + pub button: MouseButton, + pub position: Point, + pub modifiers: Modifiers, + pub click_count: usize, +} + +#[derive(Clone, Debug, Default)] +pub struct MouseClickEvent { + pub down: MouseDownEvent, + pub up: MouseUpEvent, +} + +#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] +pub enum MouseButton { + Left, + Right, + Middle, + Navigate(NavigationDirection), +} + +impl MouseButton { + pub fn all() -> Vec { + vec![ + MouseButton::Left, + MouseButton::Right, + MouseButton::Middle, + MouseButton::Navigate(NavigationDirection::Back), + MouseButton::Navigate(NavigationDirection::Forward), + ] + } +} + +impl Default for MouseButton { + fn default() -> Self { + Self::Left + } +} + +#[derive(Hash, PartialEq, Eq, Copy, Clone, Debug)] +pub enum NavigationDirection { + Back, + Forward, +} + +impl Default for NavigationDirection { + fn default() -> Self { + Self::Back + } +} + +#[derive(Clone, Debug, Default)] +pub struct MouseMoveEvent { + pub position: Point, + pub pressed_button: Option, + pub modifiers: Modifiers, +} + +#[derive(Clone, Debug)] +pub struct ScrollWheelEvent { + pub position: Point, + pub delta: ScrollDelta, + pub modifiers: Modifiers, + pub touch_phase: TouchPhase, +} + +impl Deref for ScrollWheelEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +#[derive(Clone, Copy, Debug)] +pub enum ScrollDelta { + Pixels(Point), + Lines(Point), +} + +impl Default for ScrollDelta { + fn default() -> Self { + Self::Lines(Default::default()) + } +} + +impl ScrollDelta { + pub fn precise(&self) -> bool { + match self { + ScrollDelta::Pixels(_) => true, + ScrollDelta::Lines(_) => false, + } + } + + pub fn pixel_delta(&self, line_height: Pixels) -> Point { + match self { + ScrollDelta::Pixels(delta) => *delta, + ScrollDelta::Lines(delta) => point(line_height * delta.x, line_height * delta.y), + } + } +} + +#[derive(Clone, Debug, Default)] +pub struct MouseExitEvent { + pub position: Point, + pub pressed_button: Option, + pub modifiers: Modifiers, +} + +impl Deref for MouseExitEvent { + type Target = Modifiers; + + fn deref(&self) -> &Self::Target { + &self.modifiers + } +} + +#[derive(Clone, Debug)] +pub enum InputEvent { + KeyDown(KeyDownEvent), + KeyUp(KeyUpEvent), + ModifiersChanged(ModifiersChangedEvent), + MouseDown(MouseDownEvent), + MouseUp(MouseUpEvent), + MouseMoved(MouseMoveEvent), + MouseExited(MouseExitEvent), + ScrollWheel(ScrollWheelEvent), +} + +impl InputEvent { + pub fn position(&self) -> Option> { + match self { + InputEvent::KeyDown { .. } => None, + InputEvent::KeyUp { .. } => None, + InputEvent::ModifiersChanged { .. } => None, + InputEvent::MouseDown(event) => Some(event.position), + InputEvent::MouseUp(event) => Some(event.position), + InputEvent::MouseMoved(event) => Some(event.position), + InputEvent::MouseExited(event) => Some(event.position), + InputEvent::ScrollWheel(event) => Some(event.position), + } + } + + pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> { + match self { + InputEvent::KeyDown { .. } => None, + InputEvent::KeyUp { .. } => None, + InputEvent::ModifiersChanged { .. } => None, + InputEvent::MouseDown(event) => Some(event), + InputEvent::MouseUp(event) => Some(event), + InputEvent::MouseMoved(event) => Some(event), + InputEvent::MouseExited(event) => Some(event), + InputEvent::ScrollWheel(event) => Some(event), + } + } + + pub fn keyboard_event<'a>(&'a self) -> Option<&'a dyn Any> { + match self { + InputEvent::KeyDown(event) => Some(event), + InputEvent::KeyUp(event) => Some(event), + InputEvent::ModifiersChanged(event) => Some(event), + InputEvent::MouseDown(_) => None, + InputEvent::MouseUp(_) => None, + InputEvent::MouseMoved(_) => None, + InputEvent::MouseExited(_) => None, + InputEvent::ScrollWheel(_) => None, + } + } +} + +pub struct FocusEvent { + pub blurred: Option, + pub focused: Option, +} + +pub type MouseDownListener = Arc< + dyn Fn(&mut V, &MouseDownEvent, &Bounds, DispatchPhase, &mut ViewContext) + + Send + + Sync + + 'static, +>; +pub type MouseUpListener = Arc< + dyn Fn(&mut V, &MouseUpEvent, &Bounds, DispatchPhase, &mut ViewContext) + + Send + + Sync + + 'static, +>; +pub type MouseClickListener = + Arc) + Send + Sync + 'static>; + +pub type MouseMoveListener = Arc< + dyn Fn(&mut V, &MouseMoveEvent, &Bounds, DispatchPhase, &mut ViewContext) + + Send + + Sync + + 'static, +>; + +pub type ScrollWheelListener = Arc< + dyn Fn(&mut V, &ScrollWheelEvent, &Bounds, DispatchPhase, &mut ViewContext) + + Send + + Sync + + 'static, +>; + +pub type KeyListener = Arc< + dyn Fn( + &mut V, + &dyn Any, + &[&DispatchContext], + DispatchPhase, + &mut ViewContext, + ) -> Option> + + Send + + Sync + + 'static, +>; + +pub struct InteractiveState { + pub mouse_down: SmallVec<[MouseDownListener; 2]>, + pub mouse_up: SmallVec<[MouseUpListener; 2]>, + pub mouse_click: SmallVec<[MouseClickListener; 2]>, + pub mouse_move: SmallVec<[MouseMoveListener; 2]>, + pub scroll_wheel: SmallVec<[ScrollWheelListener; 2]>, + pub key: SmallVec<[(TypeId, KeyListener); 32]>, +} + +impl Default for InteractiveState { + fn default() -> Self { + Self { + mouse_down: SmallVec::new(), + mouse_up: SmallVec::new(), + mouse_click: SmallVec::new(), + mouse_move: SmallVec::new(), + scroll_wheel: SmallVec::new(), + key: SmallVec::new(), + } + } +}