Block hovering behind overlays

Nathan Sobo created

Change summary

crates/gpui/src/app.rs                          |  3 -
crates/gpui/src/elements/mouse_event_handler.rs |  3 -
crates/gpui/src/elements/overlay.rs             |  9 ++++-
crates/gpui/src/presenter.rs                    | 33 ++++++++++--------
crates/gpui/src/scene.rs                        | 17 ++++-----
5 files changed, 34 insertions(+), 31 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -3484,8 +3484,7 @@ impl<'a, V: View> RenderContext<'a, V> {
     pub fn mouse_state<Tag: 'static>(&self, region_id: usize) -> MouseState {
         let region_id = MouseRegionId {
             view_id: self.view_id,
-            tag: TypeId::of::<Tag>(),
-            region_id,
+            discriminant: (TypeId::of::<Tag>(), region_id),
         };
         MouseState {
             hovered: self.hovered_region_ids.contains(&region_id),

crates/gpui/src/elements/mouse_event_handler.rs 🔗

@@ -131,8 +131,7 @@ impl Element for MouseEventHandler {
 
         cx.scene.push_mouse_region(MouseRegion {
             view_id: cx.current_view_id(),
-            tag: self.tag,
-            region_id: self.id,
+            discriminant: Some((self.tag, self.id)),
             bounds: self.hit_bounds(bounds),
             hover: None,
             click: self.click_handler.clone(),

crates/gpui/src/elements/overlay.rs 🔗

@@ -3,8 +3,8 @@ use serde_json::json;
 use crate::{
     geometry::{rect::RectF, vector::Vector2F},
     json::ToJson,
-    DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
-    SizeConstraint,
+    DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MouseRegion,
+    PaintContext, SizeConstraint,
 };
 
 pub struct Overlay {
@@ -54,6 +54,11 @@ impl Element for Overlay {
         let origin = self.abs_position.unwrap_or(bounds.origin());
         let visible_bounds = RectF::new(origin, *size);
         cx.scene.push_stacking_context(None);
+        cx.scene.push_mouse_region(MouseRegion {
+            view_id: cx.current_view_id(),
+            bounds: visible_bounds,
+            ..Default::default()
+        });
         self.child.paint(origin, visible_bounds, cx);
         cx.scene.pop_stacking_context();
     }

crates/gpui/src/presenter.rs 🔗

@@ -103,11 +103,11 @@ 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().map(MouseRegion::id),
+                    clicked_region_id: self.clicked_region.as_ref().and_then(MouseRegion::id),
                     right_clicked_region_id: self
                         .right_clicked_region
                         .as_ref()
-                        .map(MouseRegion::id),
+                        .and_then(MouseRegion::id),
                     refreshing: false,
                 })
                 .unwrap(),
@@ -125,11 +125,11 @@ 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().map(MouseRegion::id),
+                        clicked_region_id: self.clicked_region.as_ref().and_then(MouseRegion::id),
                         right_clicked_region_id: self
                             .right_clicked_region
                             .as_ref()
-                            .map(MouseRegion::id),
+                            .and_then(MouseRegion::id),
                         refreshing: true,
                     })
                     .unwrap();
@@ -194,8 +194,8 @@ impl Presenter {
             view_stack: Vec::new(),
             refreshing,
             hovered_region_ids: self.hovered_region_ids.clone(),
-            clicked_region_id: self.clicked_region.as_ref().map(MouseRegion::id),
-            right_clicked_region_id: self.right_clicked_region.as_ref().map(MouseRegion::id),
+            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),
             titlebar_height: self.titlebar_height,
             window_size,
             app: cx,
@@ -293,21 +293,24 @@ impl Presenter {
 
                         let mut hover_depth = None;
                         for (region, depth) in self.mouse_regions.iter().rev() {
-                            let region_id = region.id();
                             if region.bounds.contains_point(position)
                                 && hover_depth.map_or(true, |hover_depth| hover_depth == *depth)
                             {
                                 hover_depth = Some(*depth);
-                                if !self.hovered_region_ids.contains(&region_id) {
-                                    invalidated_views.push(region.view_id);
-                                    hovered_regions.push(region.clone());
-                                    self.hovered_region_ids.insert(region_id);
+                                if let Some(region_id) = region.id() {
+                                    if !self.hovered_region_ids.contains(&region_id) {
+                                        invalidated_views.push(region.view_id);
+                                        hovered_regions.push(region.clone());
+                                        self.hovered_region_ids.insert(region_id);
+                                    }
                                 }
                             } else {
-                                if self.hovered_region_ids.contains(&region_id) {
-                                    invalidated_views.push(region.view_id);
-                                    unhovered_regions.push(region.clone());
-                                    self.hovered_region_ids.remove(&region_id);
+                                if let Some(region_id) = region.id() {
+                                    if self.hovered_region_ids.contains(&region_id) {
+                                        invalidated_views.push(region.view_id);
+                                        unhovered_regions.push(region.clone());
+                                        self.hovered_region_ids.remove(&region_id);
+                                    }
                                 }
                             }
                         }

crates/gpui/src/scene.rs 🔗

@@ -43,11 +43,10 @@ pub struct CursorRegion {
     pub style: CursorStyle,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Default)]
 pub struct MouseRegion {
     pub view_id: usize,
-    pub tag: TypeId,
-    pub region_id: usize,
+    pub discriminant: Option<(TypeId, usize)>,
     pub bounds: RectF,
     pub hover: Option<Rc<dyn Fn(bool, &mut EventContext)>>,
     pub mouse_down: Option<Rc<dyn Fn(Vector2F, &mut EventContext)>>,
@@ -60,8 +59,7 @@ pub struct MouseRegion {
 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub struct MouseRegionId {
     pub view_id: usize,
-    pub tag: TypeId,
-    pub region_id: usize,
+    pub discriminant: (TypeId, usize),
 }
 
 #[derive(Default, Debug)]
@@ -544,12 +542,11 @@ impl ToJson for Border {
 }
 
 impl MouseRegion {
-    pub fn id(&self) -> MouseRegionId {
-        MouseRegionId {
+    pub fn id(&self) -> Option<MouseRegionId> {
+        self.discriminant.map(|discriminant| MouseRegionId {
             view_id: self.view_id,
-            tag: self.tag,
-            region_id: self.region_id,
-        }
+            discriminant,
+        })
     }
 }