From 3fb4e6356c49796ac285a1a2b3b39fed78d2f025 Mon Sep 17 00:00:00 2001 From: K Simmons Date: Fri, 12 Aug 2022 19:00:48 -0700 Subject: [PATCH] Rework presenter dispatch_event to allow isolated propogation of individual MouseRegionEvent types Co-Authored-By: mikayla@zed.dev --- crates/gpui/src/app.rs | 33 +- .../gpui/src/elements/mouse_event_handler.rs | 14 +- crates/gpui/src/presenter.rs | 458 +++++++++--------- crates/gpui/src/scene/mouse_region.rs | 35 +- crates/gpui/src/scene/mouse_region_event.rs | 82 ++-- crates/workspace/src/sidebar.rs | 2 +- 6 files changed, 303 insertions(+), 321 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 9071f98dfe..c9748e08b4 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -9,7 +9,7 @@ use crate::{ platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions}, presenter::Presenter, util::post_inc, - AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseRegionId, + AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseButton, MouseRegionId, PathPromptOptions, TextLayoutCache, }; pub use action::*; @@ -483,6 +483,7 @@ impl TestAppContext { keystroke: keystroke.clone(), is_held, }), + false, cx, ) { return true; @@ -569,8 +570,7 @@ impl TestAppContext { view_type: PhantomData, titlebar_height: 0., hovered_region_ids: Default::default(), - clicked_region_id: None, - right_clicked_region_id: None, + clicked_region_ids: None, refreshing: false, }; f(view, &mut render_cx) @@ -1278,8 +1278,7 @@ impl MutableAppContext { view_id, titlebar_height, hovered_region_ids: Default::default(), - clicked_region_id: None, - right_clicked_region_id: None, + clicked_region_ids: None, refreshing: false, }) .unwrap(), @@ -1958,7 +1957,7 @@ impl MutableAppContext { } } - presenter.borrow_mut().dispatch_event(event, cx) + presenter.borrow_mut().dispatch_event(event, false, cx) } else { false } @@ -4013,8 +4012,7 @@ pub struct RenderParams { pub view_id: usize, pub titlebar_height: f32, pub hovered_region_ids: HashSet, - pub clicked_region_id: Option, - pub right_clicked_region_id: Option, + pub clicked_region_ids: Option<(Vec, MouseButton)>, pub refreshing: bool, } @@ -4023,8 +4021,7 @@ pub struct RenderContext<'a, T: View> { pub(crate) view_id: usize, pub(crate) view_type: PhantomData, pub(crate) hovered_region_ids: HashSet, - pub(crate) clicked_region_id: Option, - pub(crate) right_clicked_region_id: Option, + pub(crate) clicked_region_ids: Option<(Vec, MouseButton)>, pub app: &'a mut MutableAppContext, pub titlebar_height: f32, pub refreshing: bool, @@ -4033,8 +4030,7 @@ pub struct RenderContext<'a, T: View> { #[derive(Clone, Copy, Default)] pub struct MouseState { pub hovered: bool, - pub clicked: bool, - pub right_clicked: bool, + pub clicked: Option, } impl<'a, V: View> RenderContext<'a, V> { @@ -4046,8 +4042,7 @@ impl<'a, V: View> RenderContext<'a, V> { view_type: PhantomData, titlebar_height: params.titlebar_height, hovered_region_ids: params.hovered_region_ids.clone(), - clicked_region_id: params.clicked_region_id, - right_clicked_region_id: params.right_clicked_region_id, + clicked_region_ids: params.clicked_region_ids.clone(), refreshing: params.refreshing, } } @@ -4071,8 +4066,13 @@ impl<'a, V: View> RenderContext<'a, V> { }; MouseState { hovered: self.hovered_region_ids.contains(®ion_id), - clicked: self.clicked_region_id == Some(region_id), - right_clicked: self.right_clicked_region_id == Some(region_id), + clicked: self.clicked_region_ids.as_ref().and_then(|(ids, button)| { + if ids.contains(®ion_id) { + Some(*button) + } else { + None + } + }), } } @@ -6025,6 +6025,7 @@ mod tests { cmd: false, click_count: 1, }), + false, cx, ); assert_eq!(mouse_down_count.load(SeqCst), 1); diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 570ec1b1a6..52e701b051 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -6,9 +6,8 @@ use crate::{ }, platform::CursorStyle, scene::{ - ClickRegionEvent, CursorRegion, DownOutRegionEvent, DownRegionEvent, DragOverRegionEvent, - DragRegionEvent, HandlerSet, HoverRegionEvent, MoveRegionEvent, UpOutRegionEvent, - UpRegionEvent, + ClickRegionEvent, CursorRegion, DownOutRegionEvent, DownRegionEvent, DragRegionEvent, + HandlerSet, HoverRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent, }, DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MeasurementContext, MouseButton, MouseRegion, MouseState, PaintContext, RenderContext, SizeConstraint, View, @@ -107,15 +106,6 @@ impl MouseEventHandler { self } - pub fn on_drag_over( - mut self, - button: MouseButton, - handler: impl Fn(DragOverRegionEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers = self.handlers.on_drag_over(button, handler); - self - } - pub fn on_hover( mut self, handler: impl Fn(HoverRegionEvent, &mut EventContext) + 'static, diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index f279b470da..d5ac91bed2 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -7,15 +7,14 @@ use crate::{ keymap::Keystroke, platform::{CursorStyle, Event}, scene::{ - ClickRegionEvent, CursorRegion, DownOutRegionEvent, DownRegionEvent, DragOverRegionEvent, - DragRegionEvent, HoverRegionEvent, MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, - UpRegionEvent, + ClickRegionEvent, CursorRegion, DownOutRegionEvent, DownRegionEvent, DragRegionEvent, + HoverRegionEvent, MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent, }, text_layout::TextLayoutCache, Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity, - FontSystem, ModelHandle, MouseButtonEvent, MouseMovedEvent, MouseRegion, MouseRegionId, - ParentId, ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, - UpgradeViewHandle, View, ViewHandle, WeakModelHandle, WeakViewHandle, + FontSystem, ModelHandle, MouseButton, MouseMovedEvent, MouseRegion, MouseRegionId, ParentId, + ReadModel, ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, + View, ViewHandle, WeakModelHandle, WeakViewHandle, }; use collections::{HashMap, HashSet}; use pathfinder_geometry::vector::{vec2f, Vector2F}; @@ -37,9 +36,9 @@ pub struct Presenter { asset_cache: Arc, last_mouse_moved_event: Option, hovered_region_ids: HashSet, - clicked_region: Option, - right_clicked_region: Option, - prev_drag_position: Option, + clicked_regions: Vec, + clicked_button: Option, + mouse_position: Vector2F, titlebar_height: f32, } @@ -62,9 +61,9 @@ impl Presenter { asset_cache, last_mouse_moved_event: None, hovered_region_ids: Default::default(), - clicked_region: None, - right_clicked_region: None, - prev_drag_position: None, + clicked_regions: Vec::new(), + clicked_button: None, + mouse_position: vec2f(0., 0.), titlebar_height, } } @@ -87,11 +86,15 @@ impl Presenter { view_id: *view_id, titlebar_height: self.titlebar_height, hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_id: self.clicked_region.as_ref().and_then(MouseRegion::id), - right_clicked_region_id: self - .right_clicked_region - .as_ref() - .and_then(MouseRegion::id), + clicked_region_ids: self.clicked_button.map(|button| { + ( + self.clicked_regions + .iter() + .filter_map(MouseRegion::id) + .collect(), + button, + ) + }), refreshing: false, }) .unwrap(), @@ -109,11 +112,15 @@ impl Presenter { view_id: *view_id, titlebar_height: self.titlebar_height, hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_id: self.clicked_region.as_ref().and_then(MouseRegion::id), - right_clicked_region_id: self - .right_clicked_region - .as_ref() - .and_then(MouseRegion::id), + clicked_region_ids: self.clicked_button.map(|button| { + ( + self.clicked_regions + .iter() + .filter_map(MouseRegion::id) + .collect(), + button, + ) + }), refreshing: true, }) .unwrap(); @@ -144,11 +151,7 @@ impl Presenter { if cx.window_is_active(self.window_id) { if let Some(event) = self.last_mouse_moved_event.clone() { - let invalidated_views = self.handle_hover_events(&event, cx).invalidated_views; - - for view_id in invalidated_views { - cx.notify_view(self.window_id, view_id); - } + self.dispatch_event(event, true, cx); } } } else { @@ -181,8 +184,15 @@ impl Presenter { view_stack: Vec::new(), refreshing, hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_id: self.clicked_region.as_ref().and_then(MouseRegion::id), - right_clicked_region_id: self.right_clicked_region.as_ref().and_then(MouseRegion::id), + clicked_region_ids: self.clicked_button.map(|button| { + ( + self.clicked_regions + .iter() + .filter_map(MouseRegion::id) + .collect(), + button, + ) + }), titlebar_height: self.titlebar_height, window_size, app: cx, @@ -217,197 +227,230 @@ impl Presenter { }) } - pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) -> bool { + pub fn dispatch_event( + &mut self, + event: Event, + event_reused: bool, + cx: &mut MutableAppContext, + ) -> bool { if let Some(root_view_id) = cx.root_view_id(self.window_id) { let mut events_to_send = Vec::new(); + + //1. Allocate the correct set of GPUI events generated from the platform events + // -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?] + // -> Also moves around mouse related state match &event { - Event::MouseDown(e @ MouseButtonEvent { position, .. }) => { - for (region, _) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(*position) { - self.clicked_region = Some(region.clone()); - self.prev_drag_position = Some(*position); - events_to_send.push(( - region.clone(), - MouseRegionEvent::Down(DownRegionEvent { - region: region.bounds, - platform_event: e.clone(), - }), - )); - } else { - events_to_send.push(( - region.clone(), - MouseRegionEvent::DownOut(DownOutRegionEvent { - region: region.bounds, - platform_event: e.clone(), - }), - )); - } - } - } - Event::MouseUp(e @ MouseButtonEvent { position, .. }) => { - for (region, _) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(*position) { - events_to_send.push(( - region.clone(), - MouseRegionEvent::Up(UpRegionEvent { - region: region.bounds, - platform_event: e.clone(), - }), - )); - } else { - events_to_send.push(( - region.clone(), - MouseRegionEvent::UpOut(UpOutRegionEvent { - region: region.bounds, - platform_event: e.clone(), - }), - )); - } - } - self.prev_drag_position.take(); - if let Some(region) = self.clicked_region.take() { - if region.bounds.contains_point(*position) { - let bounds = region.bounds.clone(); - events_to_send.push(( - region, - MouseRegionEvent::Click(ClickRegionEvent { - region: bounds, - platform_event: e.clone(), - }), - )); - } - } - } - Event::MouseMoved(e @ MouseMovedEvent { position, .. }) => { - if let Some(clicked_region) = self.clicked_region.as_ref() { - if let Some(prev_drag_position) = self.prev_drag_position { - events_to_send.push(( - clicked_region.clone(), - MouseRegionEvent::Drag(DragRegionEvent { - region: clicked_region.bounds, - prev_drag_position, - platform_event: e.clone(), - }), - )); - } + Event::MouseDown(e) => { + //Click events are weird because they can be fired after a drag event. + //MDN says that browsers handle this by starting from 'the most + //specific ancestor element that contained both [positions]' + //So we need to store the overlapping regions on mouse down. + self.clicked_regions = self + .mouse_regions + .iter() + .filter_map(|(region, _)| { + region + .bounds + .contains_point(e.position) + .then(|| region.clone()) + }) + .collect(); + self.clicked_button = Some(e.button); - self.prev_drag_position = Some(*position) + events_to_send.push(MouseRegionEvent::Down(DownRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + events_to_send.push(MouseRegionEvent::DownOut(DownOutRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + } + Event::MouseUp(e) => { + //NOTE: The order of event pushes is important! MouseUp events MUST be fired + //before click events, and so the UpRegionEvent events need to be pushed before + //ClickRegionEvents + events_to_send.push(MouseRegionEvent::Up(UpRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + events_to_send.push(MouseRegionEvent::UpOut(UpOutRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + events_to_send.push(MouseRegionEvent::Click(ClickRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + } + Event::MouseMoved( + e @ MouseMovedEvent { + position, + pressed_button, + .. + }, + ) => { + let mut style_to_assign = CursorStyle::Arrow; + for region in self.cursor_regions.iter().rev() { + if region.bounds.contains_point(*position) { + style_to_assign = region.style; + break; + } + } + cx.platform().set_cursor_style(style_to_assign); + + if pressed_button.is_some() { + events_to_send.push(MouseRegionEvent::Drag(DragRegionEvent { + region: Default::default(), + prev_mouse_position: self.mouse_position, + platform_event: e.clone(), + })); } - for (region, _) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(*position) { - events_to_send.push(( - region.clone(), - MouseRegionEvent::Move(MoveRegionEvent { - region: region.bounds, - platform_event: e.clone(), - }), - )); - } - } + events_to_send.push(MouseRegionEvent::Move(MoveRegionEvent { + region: Default::default(), + platform_event: e.clone(), + })); + + events_to_send.push(MouseRegionEvent::Hover(HoverRegionEvent { + region: Default::default(), + platform_event: e.clone(), + started: true, + })); + + events_to_send.push(MouseRegionEvent::Hover(HoverRegionEvent { + region: Default::default(), + platform_event: e.clone(), + started: false, + })); self.last_mouse_moved_event = Some(event.clone()); } _ => {} } - let (invalidated_views, handled) = { - let mut event_cx = self.handle_hover_events(&event, cx); - event_cx.process_region_events(events_to_send); + if let Some(position) = event.position() { + self.mouse_position = position; + } - if !event_cx.handled { - event_cx.handled = event_cx.dispatch_event(root_view_id, &event); + let mut invalidated_views: HashSet = Default::default(); + let mut any_event_handled = false; + //2. Process the raw mouse events into region events + for mut region_event in events_to_send { + let mut valid_regions = Vec::new(); + + //GPUI elements are arranged by depth but sibling elements can register overlapping + //mouse regions. As such, hover events are only fired on overlapping elements which + //are at the same depth as the deepest element which overlaps with the mouse. + if let MouseRegionEvent::Hover(_) = region_event { + let mut top_most_depth = None; + let mouse_position = self.mouse_position.clone(); + for (region, depth) in self.mouse_regions.iter().rev() { + let contains_mouse = region.bounds.contains_point(mouse_position); + + if contains_mouse && top_most_depth.is_none() { + top_most_depth = Some(depth); + } + + if let Some(region_id) = region.id() { + //This unwrap relies on short circuiting boolean expressions + //The right side of the && is only executed when contains_mouse + //is true, and we know above that when contains_mouse is true + //top_most_depth is set + if contains_mouse && depth == top_most_depth.unwrap() { + //Ensure that hover entrance events aren't sent twice + if self.hovered_region_ids.insert(region_id) { + valid_regions.push(region.clone()); + } + } else { + //Ensure that hover exit events aren't sent twice + if self.hovered_region_ids.remove(®ion_id) { + valid_regions.push(region.clone()); + } + } + } + } + } else if let MouseRegionEvent::Click(e) = ®ion_event { + //Clear presenter state + let clicked_regions = std::mem::replace(&mut self.clicked_regions, Vec::new()); + self.clicked_button = None; + + //Find regions which still overlap with the mouse since the last MouseDown happened + for clicked_region in clicked_regions.into_iter().rev() { + if clicked_region.bounds.contains_point(e.position) { + valid_regions.push(clicked_region); + } + } + } else if region_event.is_local() { + for (mouse_region, _) in self.mouse_regions.iter().rev() { + //Contains + if mouse_region.bounds.contains_point(self.mouse_position) { + valid_regions.push(mouse_region.clone()); + } + } + } else { + for (mouse_region, _) in self.mouse_regions.iter().rev() { + //NOT contains + if !mouse_region.bounds.contains_point(self.mouse_position) { + valid_regions.push(mouse_region.clone()); + } + } } - (event_cx.invalidated_views, event_cx.handled) - }; + //3. Fire region events + let hovered_region_ids = self.hovered_region_ids.clone(); + let mut event_cx = self.build_event_context(cx); + for valid_region in valid_regions.into_iter() { + region_event.set_region(valid_region.bounds); + if let MouseRegionEvent::Hover(e) = &mut region_event { + e.started = valid_region + .id() + .map(|region_id| hovered_region_ids.contains(®ion_id)) + .unwrap_or(false) + } + + if let Some(callback) = valid_region.handlers.get(®ion_event.handler_key()) { + if event_reused { + invalidated_views.insert(valid_region.view_id); + } + + event_cx.handled = true; + let local = region_event.is_local(); + event_cx.with_current_view(valid_region.view_id, { + let region_event = region_event.clone(); + |cx| { + callback(region_event, cx); + } + }); + + // For bubbling events, if the event was handled, don't continue dispatching + // This only makes sense for local events. 'Out*' events are already + if event_cx.handled && local { + break; + } + } + } + + invalidated_views.extend(event_cx.invalidated_views); + any_event_handled = any_event_handled && event_cx.handled; + } + + if !any_event_handled { + let mut event_cx = self.build_event_context(cx); + any_event_handled = event_cx.dispatch_event(root_view_id, &event); + invalidated_views.extend(event_cx.invalidated_views); + } for view_id in invalidated_views { cx.notify_view(self.window_id, view_id); } - handled + any_event_handled } else { false } } - fn handle_hover_events<'a>( - &'a mut self, - event: &Event, - cx: &'a mut MutableAppContext, - ) -> EventContext<'a> { - let mut events_to_send = Vec::new(); - - if let Event::MouseMoved( - e @ MouseMovedEvent { - position, - pressed_button, - .. - }, - ) = event - { - let mut style_to_assign = CursorStyle::Arrow; - for region in self.cursor_regions.iter().rev() { - if region.bounds.contains_point(*position) { - style_to_assign = region.style; - break; - } - } - cx.platform().set_cursor_style(style_to_assign); - - let mut hover_depth = None; - for (region, depth) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(*position) - && hover_depth.map_or(true, |hover_depth| hover_depth == *depth) - { - hover_depth = Some(*depth); - if let Some(region_id) = region.id() { - if !self.hovered_region_ids.contains(®ion_id) { - let region_event = if pressed_button.is_some() { - MouseRegionEvent::DragOver(DragOverRegionEvent { - region: region.bounds, - started: true, - platform_event: e.clone(), - }) - } else { - MouseRegionEvent::Hover(HoverRegionEvent { - region: region.bounds, - started: true, - platform_event: e.clone(), - }) - }; - events_to_send.push((region.clone(), region_event)); - self.hovered_region_ids.insert(region_id); - } - } - } else if let Some(region_id) = region.id() { - if self.hovered_region_ids.contains(®ion_id) { - let region_event = if pressed_button.is_some() { - MouseRegionEvent::DragOver(DragOverRegionEvent { - region: region.bounds, - started: false, - platform_event: e.clone(), - }) - } else { - MouseRegionEvent::Hover(HoverRegionEvent { - region: region.bounds, - started: false, - platform_event: e.clone(), - }) - }; - events_to_send.push((region.clone(), region_event)); - self.hovered_region_ids.remove(®ion_id); - } - } - } - } - - let mut event_cx = self.build_event_context(cx); - event_cx.process_region_events(events_to_send); - event_cx - } - pub fn build_event_context<'a>( &'a mut self, cx: &'a mut MutableAppContext, @@ -454,8 +497,7 @@ pub struct LayoutContext<'a> { pub window_size: Vector2F, titlebar_height: f32, hovered_region_ids: HashSet, - clicked_region_id: Option, - right_clicked_region_id: Option, + clicked_region_ids: Option<(Vec, MouseButton)>, } impl<'a> LayoutContext<'a> { @@ -526,8 +568,7 @@ impl<'a> LayoutContext<'a> { view_type: PhantomData, titlebar_height: self.titlebar_height, hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_id: self.clicked_region_id, - right_clicked_region_id: self.right_clicked_region_id, + clicked_region_ids: self.clicked_region_ids.clone(), refreshing: self.refreshing, }; f(view, &mut render_cx) @@ -655,25 +696,6 @@ impl<'a> EventContext<'a> { } } - fn process_region_events(&mut self, events: Vec<(MouseRegion, MouseRegionEvent)>) { - for (region, event) in events { - if event.is_local() { - if self.handled { - continue; - } - - self.invalidated_views.insert(region.view_id); - } - - if let Some(callback) = region.handlers.get(&event.handler_key()) { - self.handled = true; - self.with_current_view(region.view_id, |event_cx| { - callback(event, event_cx); - }) - } - } - } - fn with_current_view(&mut self, view_id: usize, f: F) -> T where F: FnOnce(&mut Self) -> T, diff --git a/crates/gpui/src/scene/mouse_region.rs b/crates/gpui/src/scene/mouse_region.rs index 308722fced..639f52208b 100644 --- a/crates/gpui/src/scene/mouse_region.rs +++ b/crates/gpui/src/scene/mouse_region.rs @@ -6,8 +6,8 @@ use pathfinder_geometry::rect::RectF; use crate::{EventContext, MouseButton}; use super::mouse_region_event::{ - ClickRegionEvent, DownOutRegionEvent, DownRegionEvent, DragOverRegionEvent, DragRegionEvent, - HoverRegionEvent, MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent, + ClickRegionEvent, DownOutRegionEvent, DownRegionEvent, DragRegionEvent, HoverRegionEvent, + MouseRegionEvent, MoveRegionEvent, UpOutRegionEvent, UpRegionEvent, }; #[derive(Clone, Default)] @@ -104,15 +104,6 @@ impl MouseRegion { self } - pub fn on_drag_over( - mut self, - button: MouseButton, - handler: impl Fn(DragOverRegionEvent, &mut EventContext) + 'static, - ) -> Self { - self.handlers = self.handlers.on_drag_over(button, handler); - self - } - pub fn on_hover( mut self, handler: impl Fn(HoverRegionEvent, &mut EventContext) + 'static, @@ -152,10 +143,6 @@ impl HandlerSet { (MouseRegionEvent::drag_disc(), Some(button)), Rc::new(|_, _| {}), ); - set.insert( - (MouseRegionEvent::drag_over_disc(), Some(button)), - Rc::new(|_, _| {}), - ); set.insert( (MouseRegionEvent::down_disc(), Some(button)), Rc::new(|_, _| {}), @@ -317,24 +304,6 @@ impl HandlerSet { self } - pub fn on_drag_over( - mut self, - button: MouseButton, - handler: impl Fn(DragOverRegionEvent, &mut EventContext) + 'static, - ) -> Self { - self.set.insert((MouseRegionEvent::drag_over_disc(), Some(button)), - Rc::new(move |region_event, cx| { - if let MouseRegionEvent::DragOver(e) = region_event { - handler(e, cx); - } else { - panic!( - "Mouse Region Event incorrectly called with mismatched event type. Expected MouseRegionEvent::DragOver, found {:?}", - region_event); - } - })); - self - } - pub fn on_hover( mut self, handler: impl Fn(HoverRegionEvent, &mut EventContext) + 'static, diff --git a/crates/gpui/src/scene/mouse_region_event.rs b/crates/gpui/src/scene/mouse_region_event.rs index 6e33240e4b..6556f57fea 100644 --- a/crates/gpui/src/scene/mouse_region_event.rs +++ b/crates/gpui/src/scene/mouse_region_event.rs @@ -7,7 +7,7 @@ use pathfinder_geometry::{rect::RectF, vector::Vector2F}; use crate::{MouseButton, MouseButtonEvent, MouseMovedEvent, ScrollWheelEvent}; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct MoveRegionEvent { pub region: RectF, pub platform_event: MouseMovedEvent, @@ -21,10 +21,10 @@ impl Deref for MoveRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct DragRegionEvent { pub region: RectF, - pub prev_drag_position: Vector2F, + pub prev_mouse_position: Vector2F, pub platform_event: MouseMovedEvent, } @@ -36,22 +36,7 @@ impl Deref for DragRegionEvent { } } -#[derive(Debug, Default)] -pub struct DragOverRegionEvent { - pub region: RectF, - pub started: bool, - pub platform_event: MouseMovedEvent, -} - -impl Deref for DragOverRegionEvent { - type Target = MouseMovedEvent; - - fn deref(&self) -> &Self::Target { - &self.platform_event - } -} - -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct HoverRegionEvent { pub region: RectF, pub started: bool, @@ -66,7 +51,7 @@ impl Deref for HoverRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct DownRegionEvent { pub region: RectF, pub platform_event: MouseButtonEvent, @@ -80,7 +65,7 @@ impl Deref for DownRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct UpRegionEvent { pub region: RectF, pub platform_event: MouseButtonEvent, @@ -94,7 +79,7 @@ impl Deref for UpRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct ClickRegionEvent { pub region: RectF, pub platform_event: MouseButtonEvent, @@ -108,7 +93,7 @@ impl Deref for ClickRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct DownOutRegionEvent { pub region: RectF, pub platform_event: MouseButtonEvent, @@ -122,7 +107,7 @@ impl Deref for DownOutRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct UpOutRegionEvent { pub region: RectF, pub platform_event: MouseButtonEvent, @@ -136,7 +121,7 @@ impl Deref for UpOutRegionEvent { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct ScrollWheelRegionEvent { pub region: RectF, pub platform_event: ScrollWheelEvent, @@ -150,11 +135,10 @@ impl Deref for ScrollWheelRegionEvent { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum MouseRegionEvent { Move(MoveRegionEvent), Drag(DragRegionEvent), - DragOver(DragOverRegionEvent), Hover(HoverRegionEvent), Down(DownRegionEvent), Up(UpRegionEvent), @@ -164,6 +148,36 @@ pub enum MouseRegionEvent { ScrollWheel(ScrollWheelRegionEvent), } +impl MouseRegionEvent { + pub fn set_region(&mut self, region: RectF) { + match self { + MouseRegionEvent::Move(r) => r.region = region, + MouseRegionEvent::Drag(r) => r.region = region, + MouseRegionEvent::Hover(r) => r.region = region, + MouseRegionEvent::Down(r) => r.region = region, + MouseRegionEvent::Up(r) => r.region = region, + MouseRegionEvent::Click(r) => r.region = region, + MouseRegionEvent::DownOut(r) => r.region = region, + MouseRegionEvent::UpOut(r) => r.region = region, + MouseRegionEvent::ScrollWheel(r) => r.region = region, + } + } + + pub fn is_local(&self) -> bool { + match self { + MouseRegionEvent::Move(_) => true, + MouseRegionEvent::Drag(_) => true, + MouseRegionEvent::Hover(_) => true, + MouseRegionEvent::Down(_) => true, + MouseRegionEvent::Up(_) => true, + MouseRegionEvent::Click(_) => true, + MouseRegionEvent::DownOut(_) => false, + MouseRegionEvent::UpOut(_) => false, + MouseRegionEvent::ScrollWheel(_) => true, + } + } +} + impl MouseRegionEvent { pub fn move_disc() -> Discriminant { discriminant(&MouseRegionEvent::Move(Default::default())) @@ -173,10 +187,6 @@ impl MouseRegionEvent { discriminant(&MouseRegionEvent::Drag(Default::default())) } - pub fn drag_over_disc() -> Discriminant { - discriminant(&MouseRegionEvent::DragOver(Default::default())) - } - pub fn hover_disc() -> Discriminant { discriminant(&MouseRegionEvent::Hover(Default::default())) } @@ -205,20 +215,10 @@ impl MouseRegionEvent { discriminant(&MouseRegionEvent::ScrollWheel(Default::default())) } - pub fn is_local(&self) -> bool { - match self { - MouseRegionEvent::DownOut(_) - | MouseRegionEvent::UpOut(_) - | MouseRegionEvent::DragOver(_) => false, - _ => true, - } - } - pub fn handler_key(&self) -> (Discriminant, Option) { match self { MouseRegionEvent::Move(_) => (Self::move_disc(), None), MouseRegionEvent::Drag(e) => (Self::drag_disc(), e.pressed_button), - MouseRegionEvent::DragOver(e) => (Self::drag_over_disc(), e.pressed_button), MouseRegionEvent::Hover(_) => (Self::hover_disc(), None), MouseRegionEvent::Down(e) => (Self::down_disc(), Some(e.button)), MouseRegionEvent::Up(e) => (Self::up_disc(), Some(e.button)), diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index 819959eb75..c89057cb11 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -190,7 +190,7 @@ impl Sidebar { .with_cursor_style(CursorStyle::ResizeLeftRight) .on_down(MouseButton::Left, |_, _| {}) // This prevents the mouse down event from being propagated elsewhere .on_drag(MouseButton::Left, move |e, cx| { - let delta = e.prev_drag_position.x() - e.position.x(); + let delta = e.prev_mouse_position.x() - e.position.x(); let prev_width = *actual_width.borrow(); *custom_width.borrow_mut() = 0f32 .max(match side {