diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index ee809746ae79adf586e0f51a61ddc516133d7bad..edeb5ccc692215fe6cc4bd9ec16b896b02f69866 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -18,11 +18,13 @@ pub struct MouseEventHandler { tag: TypeId, id: usize, cursor_style: Option, - mouse_down_handler: Option>, - click_handler: Option>, - right_mouse_down_handler: Option>, - right_click_handler: Option>, - drag_handler: Option>, + mouse_down: Option>, + click: Option>, + right_mouse_down: Option>, + right_click: Option>, + mouse_down_out: Option>, + right_mouse_down_out: Option>, + drag: Option>, padding: Padding, } @@ -38,11 +40,13 @@ impl MouseEventHandler { tag: TypeId::of::(), child: render_child(cx.mouse_state::(id), cx), cursor_style: None, - mouse_down_handler: None, - click_handler: None, - right_mouse_down_handler: None, - right_click_handler: None, - drag_handler: None, + mouse_down: None, + click: None, + right_mouse_down: None, + right_click: None, + mouse_down_out: None, + right_mouse_down_out: None, + drag: None, padding: Default::default(), } } @@ -56,7 +60,7 @@ impl MouseEventHandler { mut self, handler: impl Fn(Vector2F, &mut EventContext) + 'static, ) -> Self { - self.mouse_down_handler = Some(Rc::new(handler)); + self.mouse_down = Some(Rc::new(handler)); self } @@ -64,7 +68,7 @@ impl MouseEventHandler { mut self, handler: impl Fn(Vector2F, usize, &mut EventContext) + 'static, ) -> Self { - self.click_handler = Some(Rc::new(handler)); + self.click = Some(Rc::new(handler)); self } @@ -72,7 +76,7 @@ impl MouseEventHandler { mut self, handler: impl Fn(Vector2F, &mut EventContext) + 'static, ) -> Self { - self.right_mouse_down_handler = Some(Rc::new(handler)); + self.right_mouse_down = Some(Rc::new(handler)); self } @@ -80,12 +84,12 @@ impl MouseEventHandler { mut self, handler: impl Fn(Vector2F, usize, &mut EventContext) + 'static, ) -> Self { - self.right_click_handler = Some(Rc::new(handler)); + self.right_click = Some(Rc::new(handler)); self } pub fn on_drag(mut self, handler: impl Fn(Vector2F, &mut EventContext) + 'static) -> Self { - self.drag_handler = Some(Rc::new(handler)); + self.drag = Some(Rc::new(handler)); self } @@ -134,11 +138,13 @@ impl Element for MouseEventHandler { discriminant: Some((self.tag, self.id)), bounds: self.hit_bounds(bounds), hover: None, - click: self.click_handler.clone(), - mouse_down: self.mouse_down_handler.clone(), - right_click: self.right_click_handler.clone(), - right_mouse_down: self.right_mouse_down_handler.clone(), - drag: self.drag_handler.clone(), + click: self.click.clone(), + mouse_down: self.mouse_down.clone(), + right_click: self.right_click.clone(), + right_mouse_down: self.right_mouse_down.clone(), + mouse_down_out: self.mouse_down_out.clone(), + right_mouse_down_out: self.right_mouse_down_out.clone(), + drag: self.drag.clone(), }); self.child.paint(bounds.origin(), visible_bounds, cx); diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 6d2def4716b952195738e6223fea44c026f88829..3ff4334f616a4f753589d9ed0c4fea4fa2cc0d39 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -222,6 +222,7 @@ impl Presenter { let mut invalidated_views = Vec::new(); let mut hovered_regions = Vec::new(); let mut unhovered_regions = Vec::new(); + let mut mouse_down_out_handlers = Vec::new(); let mut mouse_down_region = None; let mut clicked_region = None; let mut right_mouse_down_region = None; @@ -230,13 +231,18 @@ impl Presenter { match event { Event::LeftMouseDown { position, .. } => { + let mut hit = false; for (region, _) in self.mouse_regions.iter().rev() { if region.bounds.contains_point(position) { - invalidated_views.push(region.view_id); - mouse_down_region = Some((region.clone(), position)); - self.clicked_region = Some(region.clone()); - self.prev_drag_position = Some(position); - break; + if !hit { + hit = true; + invalidated_views.push(region.view_id); + mouse_down_region = Some((region.clone(), position)); + self.clicked_region = Some(region.clone()); + self.prev_drag_position = Some(position); + } + } else if let Some(handler) = region.mouse_down_out.clone() { + mouse_down_out_handlers.push((handler, region.view_id, position)); } } } @@ -254,12 +260,17 @@ impl Presenter { } } Event::RightMouseDown { position, .. } => { + let mut hit = false; for (region, _) in self.mouse_regions.iter().rev() { if region.bounds.contains_point(position) { - invalidated_views.push(region.view_id); - right_mouse_down_region = Some((region.clone(), position)); - self.right_clicked_region = Some(region.clone()); - break; + if !hit { + hit = true; + invalidated_views.push(region.view_id); + right_mouse_down_region = Some((region.clone(), position)); + self.right_clicked_region = Some(region.clone()); + } + } else if let Some(handler) = region.right_mouse_down_out.clone() { + mouse_down_out_handlers.push((handler, region.view_id, position)); } } } @@ -355,6 +366,10 @@ impl Presenter { } } + for (handler, view_id, position) in mouse_down_out_handlers { + event_cx.with_current_view(view_id, |event_cx| handler(position, event_cx)) + } + if let Some((mouse_down_region, position)) = mouse_down_region { if let Some(mouse_down_callback) = mouse_down_region.mouse_down { handled = true; diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index 22762ea9dafc21589d1491ef7e3c4975c325104c..ee9bb8311ff576c1af42119af25e5dd2cfa35a44 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -54,6 +54,8 @@ pub struct MouseRegion { pub right_mouse_down: Option>, pub right_click: Option>, pub drag: Option>, + pub mouse_down_out: Option>, + pub right_mouse_down_out: Option>, } #[derive(Copy, Clone, Eq, PartialEq, Hash)]