Restrict multiple hovered regions to a single stacking context

Nathan Sobo created

We won't hover regions from stacking contexts that are below the one being hovered.

Change summary

crates/gpui/src/presenter.rs              | 14 +++++++++-----
crates/gpui/src/scene.rs                  | 15 ++++++++++-----
crates/project_panel/src/project_panel.rs |  4 +---
3 files changed, 20 insertions(+), 13 deletions(-)

Detailed changes

crates/gpui/src/presenter.rs 🔗

@@ -28,7 +28,7 @@ pub struct Presenter {
     pub(crate) rendered_views: HashMap<usize, ElementBox>,
     parents: HashMap<usize, usize>,
     cursor_regions: Vec<CursorRegion>,
-    mouse_regions: Vec<MouseRegion>,
+    mouse_regions: Vec<(MouseRegion, usize)>,
     font_cache: Arc<FontCache>,
     text_layout_cache: TextLayoutCache,
     asset_cache: Arc<AssetCache>,
@@ -230,7 +230,7 @@ impl Presenter {
 
             match event {
                 Event::LeftMouseDown { position, .. } => {
-                    for region in self.mouse_regions.iter().rev() {
+                    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));
@@ -254,7 +254,7 @@ impl Presenter {
                     }
                 }
                 Event::RightMouseDown { position, .. } => {
-                    for region in self.mouse_regions.iter().rev() {
+                    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));
@@ -291,9 +291,13 @@ impl Presenter {
                         }
                         cx.platform().set_cursor_style(style_to_assign);
 
-                        for region in self.mouse_regions.iter().rev() {
+                        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) {
+                            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());

crates/gpui/src/scene.rs 🔗

@@ -210,11 +210,16 @@ impl Scene {
             .collect()
     }
 
-    pub fn mouse_regions(&self) -> Vec<MouseRegion> {
-        self.layers()
-            .flat_map(|layer| &layer.mouse_regions)
-            .cloned()
-            .collect()
+    pub fn mouse_regions(&self) -> Vec<(MouseRegion, usize)> {
+        let mut regions = Vec::new();
+        for (stacking_depth, stacking_context) in self.stacking_contexts.iter().enumerate() {
+            for layer in &stacking_context.layers {
+                for mouse_region in &layer.mouse_regions {
+                    regions.push((mouse_region.clone(), stacking_depth));
+                }
+            }
+        }
+        regions
     }
 
     pub fn push_stacking_context(&mut self, clip_bounds: Option<RectF>) {

crates/project_panel/src/project_panel.rs 🔗

@@ -12,7 +12,7 @@ use gpui::{
     impl_internal_actions, keymap,
     platform::CursorStyle,
     AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MutableAppContext,
-    PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle,
+    PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle,
 };
 use menu::{Confirm, SelectNext, SelectPrev};
 use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
@@ -38,7 +38,6 @@ pub struct ProjectPanel {
     edit_state: Option<EditState>,
     filename_editor: ViewHandle<Editor>,
     context_menu: ViewHandle<ContextMenu>,
-    handle: WeakViewHandle<Self>,
 }
 
 #[derive(Copy, Clone)]
@@ -174,7 +173,6 @@ impl ProjectPanel {
                 edit_state: None,
                 filename_editor,
                 context_menu: cx.add_view(|_| ContextMenu::new()),
-                handle: cx.weak_handle(),
             };
             this.update_visible_entries(None, cx);
             this