From 74aa9c13204775df0940f4e109c790f577957f0c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Sat, 4 Jun 2022 10:41:08 +0200 Subject: [PATCH] Capture mouse events when rendering disconnected overlay We do so by replacing `EventHandler::capture` with a new `::capture_all` method. After switching to mouse regions as part of zed-industries/zed#1081, overriding `dispatch_event` on `EventHandler` wasn't enough anymore because mouse interactions take place on a privileged code path that runs *before* dispatching any event. With this change, `EventHandler` will now push a mouse region that intercepts all mouse interactions, as well as pushing a cursor region that resets the cursor style to `Arrow`. One interesting change as part of this is that we've removed the ability to see which event we are capturing: we were not using this capability anyway and `capture_all` provides a simpler interface, so I went with that. In the future, we can opt into capturing specific events or mouse interactions if there's a code path that needs that. --- crates/gpui/src/elements/event_handler.rs | 48 +++++++++++++++-------- crates/workspace/src/workspace.rs | 2 +- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/crates/gpui/src/elements/event_handler.rs b/crates/gpui/src/elements/event_handler.rs index 340d892d22..76e9c7fc84 100644 --- a/crates/gpui/src/elements/event_handler.rs +++ b/crates/gpui/src/elements/event_handler.rs @@ -1,14 +1,14 @@ +use crate::{ + geometry::vector::Vector2F, CursorRegion, DebugContext, Element, ElementBox, Event, + EventContext, LayoutContext, MouseRegion, NavigationDirection, PaintContext, SizeConstraint, +}; use pathfinder_geometry::rect::RectF; use serde_json::json; - -use crate::{ - geometry::vector::Vector2F, DebugContext, Element, ElementBox, Event, EventContext, - LayoutContext, NavigationDirection, PaintContext, SizeConstraint, -}; +use std::{any::TypeId, rc::Rc}; pub struct EventHandler { child: ElementBox, - capture: Option bool>>, + capture_all: Option<(TypeId, usize)>, mouse_down: Option bool>>, right_mouse_down: Option bool>>, navigate_mouse_down: Option bool>>, @@ -18,7 +18,7 @@ impl EventHandler { pub fn new(child: ElementBox) -> Self { Self { child, - capture: None, + capture_all: None, mouse_down: None, right_mouse_down: None, navigate_mouse_down: None, @@ -49,11 +49,8 @@ impl EventHandler { self } - pub fn capture(mut self, callback: F) -> Self - where - F: 'static + FnMut(&Event, RectF, &mut EventContext) -> bool, - { - self.capture = Some(Box::new(callback)); + pub fn capture_all(mut self, id: usize) -> Self { + self.capture_all = Some((TypeId::of::(), id)); self } } @@ -78,6 +75,27 @@ impl Element for EventHandler { _: &mut Self::LayoutState, cx: &mut PaintContext, ) -> Self::PaintState { + if let Some(discriminant) = self.capture_all { + cx.scene.push_stacking_context(None); + cx.scene.push_cursor_region(CursorRegion { + bounds, + style: Default::default(), + }); + cx.scene.push_mouse_region(MouseRegion { + view_id: cx.current_view_id(), + discriminant: Some(discriminant), + bounds, + hover: Some(Rc::new(|_, _, _| {})), + mouse_down: Some(Rc::new(|_, _| {})), + click: Some(Rc::new(|_, _, _| {})), + right_mouse_down: Some(Rc::new(|_, _| {})), + right_click: Some(Rc::new(|_, _, _| {})), + drag: Some(Rc::new(|_, _| {})), + mouse_down_out: Some(Rc::new(|_, _| {})), + right_mouse_down_out: Some(Rc::new(|_, _| {})), + }); + cx.scene.pop_stacking_context(); + } self.child.paint(bounds.origin(), visible_bounds, cx); } @@ -90,10 +108,8 @@ impl Element for EventHandler { _: &mut Self::PaintState, cx: &mut EventContext, ) -> bool { - if let Some(capture) = self.capture.as_mut() { - if capture(event, visible_bounds, cx) { - return true; - } + if self.capture_all.is_some() { + return true; } if self.child.dispatch_event(event, cx) { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 20edeac20e..7d4f451771 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1878,7 +1878,7 @@ impl Workspace { .with_style(theme.workspace.disconnected_overlay.container) .boxed(), ) - .capture(|_, _, _| true) + .capture_all::(0) .boxed(), ) } else {