Move workspace overlay elements into an actual overlay in order to get proper stacking context depths

K Simmons and Mikayla Maki created

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>

Change summary

crates/drag_and_drop/src/drag_and_drop.rs | 46 +++++++++++-------------
crates/gpui/src/elements/overlay.rs       | 13 +++---
crates/workspace/src/dock.rs              |  1 
crates/workspace/src/workspace.rs         | 31 +++++++++++-----
4 files changed, 50 insertions(+), 41 deletions(-)

Detailed changes

crates/drag_and_drop/src/drag_and_drop.rs 🔗

@@ -2,7 +2,7 @@ use std::{any::Any, rc::Rc};
 
 use collections::HashSet;
 use gpui::{
-    elements::{Container, MouseEventHandler},
+    elements::{Container, MouseEventHandler, Overlay},
     geometry::vector::Vector2F,
     scene::DragRegionEvent,
     CursorStyle, Element, ElementBox, EventContext, MouseButton, MutableAppContext, RenderContext,
@@ -116,29 +116,27 @@ impl<V: View> DragAndDrop<V> {
 
                 enum DraggedElementHandler {}
                 Some(
-                    MouseEventHandler::<DraggedElementHandler>::new(0, cx, |_, cx| {
-                        Container::new(render(payload, cx))
-                            .with_margin_left(position.x())
-                            .with_margin_top(position.y())
-                            .aligned()
-                            .top()
-                            .left()
-                            .boxed()
-                    })
-                    .with_cursor_style(CursorStyle::Arrow)
-                    .on_up(MouseButton::Left, |_, cx| {
-                        cx.defer(|cx| {
-                            cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
-                        });
-                        cx.propogate_event();
-                    })
-                    .on_up_out(MouseButton::Left, |_, cx| {
-                        cx.defer(|cx| {
-                            cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
-                        });
-                    })
-                    // Don't block hover events or invalidations
-                    .with_hoverable(false)
+                    Overlay::new(
+                        MouseEventHandler::<DraggedElementHandler>::new(0, cx, |_, cx| {
+                            render(payload, cx)
+                        })
+                        .with_cursor_style(CursorStyle::Arrow)
+                        .on_up(MouseButton::Left, |_, cx| {
+                            cx.defer(|cx| {
+                                cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
+                            });
+                            cx.propogate_event();
+                        })
+                        .on_up_out(MouseButton::Left, |_, cx| {
+                            cx.defer(|cx| {
+                                cx.update_global::<Self, _, _>(|this, cx| this.stop_dragging(cx));
+                            });
+                        })
+                        // Don't block hover events or invalidations
+                        .with_hoverable(false)
+                        .boxed(),
+                    )
+                    .with_anchor_position(position)
                     .boxed(),
                 )
             },

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

@@ -12,8 +12,8 @@ use serde_json::json;
 pub struct Overlay {
     child: ElementBox,
     anchor_position: Option<Vector2F>,
-    fit_mode: OverlayFitMode,
     anchor_corner: AnchorCorner,
+    fit_mode: OverlayFitMode,
     hoverable: bool,
 }
 
@@ -71,8 +71,8 @@ impl Overlay {
         Self {
             child,
             anchor_position: None,
-            fit_mode: OverlayFitMode::None,
             anchor_corner: AnchorCorner::TopLeft,
+            fit_mode: OverlayFitMode::None,
             hoverable: false,
         }
     }
@@ -183,14 +183,13 @@ impl Element for Overlay {
 
         if self.hoverable {
             enum OverlayHoverCapture {}
-            cx.scene.push_mouse_region(
-                MouseRegion::new::<OverlayHoverCapture>(
+            // Block hovers in lower stacking contexts
+            cx.scene
+                .push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
                     cx.current_view_id(),
                     cx.current_view_id(),
                     bounds,
-                )
-                .with_hoverable(true),
-            );
+                ));
         }
 
         self.child.paint(bounds.origin(), bounds, cx);

crates/workspace/src/dock.rs 🔗

@@ -150,6 +150,7 @@ impl Dock {
         cx: &mut RenderContext<Workspace>,
     ) -> Option<ElementBox> {
         let style = &theme.workspace.dock;
+
         self.position
             .visible()
             .filter(|current_anchor| *current_anchor == anchor)

crates/workspace/src/workspace.rs 🔗

@@ -2618,16 +2618,27 @@ impl View for Workspace {
                                     )
                                     .boxed()
                             })
-                            .with_children(self.dock.render(&theme, DockAnchor::Expanded, cx))
-                            .with_children(self.modal.as_ref().map(|m| {
-                                ChildView::new(m)
-                                    .contained()
-                                    .with_style(theme.workspace.modal)
-                                    .aligned()
-                                    .top()
-                                    .boxed()
-                            }))
-                            .with_children(self.render_notifications(&theme.workspace))
+                            .with_child(
+                                Overlay::new(
+                                    Stack::new()
+                                        .with_children(self.dock.render(
+                                            &theme,
+                                            DockAnchor::Expanded,
+                                            cx,
+                                        ))
+                                        .with_children(self.modal.as_ref().map(|m| {
+                                            ChildView::new(m)
+                                                .contained()
+                                                .with_style(theme.workspace.modal)
+                                                .aligned()
+                                                .top()
+                                                .boxed()
+                                        }))
+                                        .with_children(self.render_notifications(&theme.workspace))
+                                        .boxed(),
+                                )
+                                .boxed(),
+                            )
                             .flex(1.0, true)
                             .boxed(),
                     )