diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 6a6afd5461b6abb1b2944635216b5fd8ff5270a2..74ca292ecf8b712588ab0f1713c2a93d9619d92d 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -22,10 +22,11 @@ use collections::{BTreeMap, HashMap}; use gpui::{ div, point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, DispatchPhase, Edges, Element, ElementId, - ElementInputHandler, Entity, EntityId, Hsla, InteractiveElement, IntoElement, LineLayout, - MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, RenderOnce, - ScrollWheelEvent, ShapedLine, SharedString, Size, StatefulInteractiveElement, Style, Styled, - TextRun, TextStyle, View, ViewContext, WeakView, WindowContext, WrappedLine, + ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement, + IntoElement, LineLayout, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, + ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, Size, + StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View, + ViewContext, WeakView, WindowContext, WrappedLine, }; use itertools::Itertools; use language::language_settings::ShowWhitespaceSetting; @@ -316,6 +317,7 @@ impl EditorElement { position_map: &PositionMap, text_bounds: Bounds, gutter_bounds: Bounds, + stacking_order: &StackingOrder, cx: &mut ViewContext, ) -> bool { let mut click_count = event.click_count; @@ -326,6 +328,9 @@ impl EditorElement { } else if !text_bounds.contains_point(&event.position) { return false; } + if !cx.was_top_layer(&event.position, stacking_order) { + return false; + } let point_for_position = position_map.point_for_position(text_bounds, event.position); let position = point_for_position.previous_valid; @@ -384,6 +389,7 @@ impl EditorElement { event: &MouseUpEvent, position_map: &PositionMap, text_bounds: Bounds, + stacking_order: &StackingOrder, cx: &mut ViewContext, ) -> bool { let end_selection = editor.has_pending_selection(); @@ -396,6 +402,7 @@ impl EditorElement { if !pending_nonempty_selections && event.modifiers.command && text_bounds.contains_point(&event.position) + && cx.was_top_layer(&event.position, stacking_order) { let point = position_map.point_for_position(text_bounds, event.position); let could_be_inlay = point.as_valid().is_none(); @@ -418,6 +425,7 @@ impl EditorElement { position_map: &PositionMap, text_bounds: Bounds, gutter_bounds: Bounds, + stacking_order: &StackingOrder, cx: &mut ViewContext, ) -> bool { let modifiers = event.modifiers; @@ -457,10 +465,12 @@ impl EditorElement { let text_hovered = text_bounds.contains_point(&event.position); let gutter_hovered = gutter_bounds.contains_point(&event.position); + let was_top = cx.was_top_layer(&event.position, stacking_order); + editor.set_gutter_hovered(gutter_hovered, cx); // Don't trigger hover popover if mouse is hovering over context menu - if text_hovered { + if text_hovered && was_top { let point_for_position = position_map.point_for_position(text_bounds, event.position); match point_for_position.as_valid() { @@ -490,7 +500,7 @@ impl EditorElement { } else { update_go_to_definition_link(editor, None, modifiers.command, modifiers.shift, cx); hover_at(editor, None, cx); - gutter_hovered + gutter_hovered && was_top } } @@ -498,10 +508,10 @@ impl EditorElement { editor: &mut Editor, event: &ScrollWheelEvent, position_map: &PositionMap, - bounds: Bounds, + bounds: &InteractiveBounds, cx: &mut ViewContext, ) -> bool { - if !bounds.contains_point(&event.position) { + if !bounds.visibly_contains(&event.position, cx) { return false; } @@ -2282,10 +2292,15 @@ impl EditorElement { cx: &mut WindowContext, ) { let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); + let interactive_bounds = InteractiveBounds { + bounds: bounds.intersect(&cx.content_mask().bounds), + stacking_order: cx.stacking_order().clone(), + }; cx.on_mouse_event({ let position_map = layout.position_map.clone(); let editor = self.editor.clone(); + let interactive_bounds = interactive_bounds.clone(); move |event: &ScrollWheelEvent, phase, cx| { if phase != DispatchPhase::Bubble { @@ -2293,7 +2308,7 @@ impl EditorElement { } let should_cancel = editor.update(cx, |editor, cx| { - Self::scroll(editor, event, &position_map, bounds, cx) + Self::scroll(editor, event, &position_map, &interactive_bounds, cx) }); if should_cancel { cx.stop_propagation(); @@ -2304,6 +2319,7 @@ impl EditorElement { cx.on_mouse_event({ let position_map = layout.position_map.clone(); let editor = self.editor.clone(); + let stacking_order = cx.stacking_order().clone(); move |event: &MouseDownEvent, phase, cx| { if phase != DispatchPhase::Bubble { @@ -2311,7 +2327,15 @@ impl EditorElement { } let should_cancel = editor.update(cx, |editor, cx| { - Self::mouse_down(editor, event, &position_map, text_bounds, gutter_bounds, cx) + Self::mouse_down( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) }); if should_cancel { @@ -2323,9 +2347,18 @@ impl EditorElement { cx.on_mouse_event({ let position_map = layout.position_map.clone(); let editor = self.editor.clone(); + let stacking_order = cx.stacking_order().clone(); + move |event: &MouseUpEvent, phase, cx| { let should_cancel = editor.update(cx, |editor, cx| { - Self::mouse_up(editor, event, &position_map, text_bounds, cx) + Self::mouse_up( + editor, + event, + &position_map, + text_bounds, + &stacking_order, + cx, + ) }); if should_cancel { @@ -2351,13 +2384,23 @@ impl EditorElement { cx.on_mouse_event({ let position_map = layout.position_map.clone(); let editor = self.editor.clone(); + let stacking_order = cx.stacking_order().clone(); + move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } let stop_propogating = editor.update(cx, |editor, cx| { - Self::mouse_moved(editor, event, &position_map, text_bounds, gutter_bounds, cx) + Self::mouse_moved( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) }); if stop_propogating { @@ -2617,9 +2660,11 @@ impl Element for EditorElement { // We call with_z_index to establish a new stacking context. cx.with_z_index(0, |cx| { cx.with_content_mask(Some(ContentMask { bounds }), |cx| { - // Paint mouse listeners first, so any elements we paint on top of the editor + // Paint mouse listeners at z-index 0 so any elements we paint on top of the editor // take precedence. - self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); + cx.with_z_index(0, |cx| { + self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); + }); let input_handler = ElementInputHandler::new(bounds, self.editor.clone(), cx); cx.handle_input(&focus_handle, input_handler); diff --git a/crates/editor2/src/hover_popover.rs b/crates/editor2/src/hover_popover.rs index 37c7df650b126c859c28339a09077a96f4844bf2..f80168ed250d3f3bdcbedb7ad1d61e9e173f15ef 100644 --- a/crates/editor2/src/hover_popover.rs +++ b/crates/editor2/src/hover_popover.rs @@ -483,9 +483,6 @@ impl InfoPopover { // Prevent a mouse move on the popover from being propagated to the editor, // because that would dismiss the popover. .on_mouse_move(|_, cx| cx.stop_propagation()) - // Prevent a mouse down on the popover from being propagated to the editor, - // because that would move the cursor. - .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation()) .child(crate::render_parsed_markdown( "content", &self.parsed_content, diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 406f2ea31179d265202b7bd381c3b8b782b813c9..635e8b634f0f6982fffa2d35ca46da5bfb736e90 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -3,7 +3,8 @@ use crate::{ BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle, IntoElement, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, - SharedString, Size, Style, StyleRefinement, Styled, Task, View, Visibility, WindowContext, + SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, + WindowContext, }; use collections::HashMap; use refineable::Refineable; @@ -84,7 +85,7 @@ pub trait InteractiveElement: Sized + Element { move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button - && bounds.contains_point(&event.position) + && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx) } @@ -99,7 +100,7 @@ pub trait InteractiveElement: Sized + Element { ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx) } }, @@ -117,7 +118,7 @@ pub trait InteractiveElement: Sized + Element { .push(Box::new(move |event, bounds, phase, cx| { if phase == DispatchPhase::Bubble && event.button == button - && bounds.contains_point(&event.position) + && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx) } @@ -132,7 +133,7 @@ pub trait InteractiveElement: Sized + Element { self.interactivity() .mouse_up_listeners .push(Box::new(move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx) } })); @@ -145,7 +146,8 @@ pub trait InteractiveElement: Sized + Element { ) -> Self { self.interactivity().mouse_down_listeners.push(Box::new( move |event, bounds, phase, cx| { - if phase == DispatchPhase::Capture && !bounds.contains_point(&event.position) { + if phase == DispatchPhase::Capture && !bounds.visibly_contains(&event.position, cx) + { (listener)(event, cx) } }, @@ -163,7 +165,7 @@ pub trait InteractiveElement: Sized + Element { .push(Box::new(move |event, bounds, phase, cx| { if phase == DispatchPhase::Capture && event.button == button - && !bounds.contains_point(&event.position) + && !bounds.visibly_contains(&event.position, cx) { (listener)(event, cx); } @@ -177,7 +179,7 @@ pub trait InteractiveElement: Sized + Element { ) -> Self { self.interactivity().mouse_move_listeners.push(Box::new( move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx); } }, @@ -191,7 +193,7 @@ pub trait InteractiveElement: Sized + Element { ) -> Self { self.interactivity().scroll_wheel_listeners.push(Box::new( move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { (listener)(event, cx); } }, @@ -526,15 +528,15 @@ pub type FocusListeners = SmallVec<[FocusListener; 2]>; pub type FocusListener = Box; pub type MouseDownListener = - Box, DispatchPhase, &mut WindowContext) + 'static>; + Box; pub type MouseUpListener = - Box, DispatchPhase, &mut WindowContext) + 'static>; + Box; pub type MouseMoveListener = - Box, DispatchPhase, &mut WindowContext) + 'static>; + Box; pub type ScrollWheelListener = - Box, DispatchPhase, &mut WindowContext) + 'static>; + Box; pub type ClickListener = Box; @@ -719,6 +721,18 @@ pub struct Interactivity { pub tooltip_builder: Option, } +#[derive(Clone)] +pub struct InteractiveBounds { + pub bounds: Bounds, + pub stacking_order: StackingOrder, +} + +impl InteractiveBounds { + pub fn visibly_contains(&self, point: &Point, cx: &WindowContext) -> bool { + self.bounds.contains_point(point) && cx.was_top_layer(&point, &self.stacking_order) + } +} + impl Interactivity { pub fn layout( &mut self, @@ -755,34 +769,52 @@ impl Interactivity { ) { let style = self.compute_style(Some(bounds), element_state, cx); + if style + .background + .as_ref() + .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) + { + cx.with_z_index(style.z_index.unwrap_or(0), |cx| cx.add_opaque_layer(bounds)) + } + + let interactive_bounds = Rc::new(InteractiveBounds { + bounds: bounds.intersect(&cx.content_mask().bounds), + stacking_order: cx.stacking_order().clone(), + }); + if let Some(mouse_cursor) = style.mouse_cursor { - let hovered = bounds.contains_point(&cx.mouse_position()); + let mouse_position = &cx.mouse_position(); + let hovered = interactive_bounds.visibly_contains(mouse_position, cx); if hovered { cx.set_cursor_style(mouse_cursor); } } for listener in self.mouse_down_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - listener(event, &bounds, phase, cx); + listener(event, &*interactive_bounds, phase, cx); }) } for listener in self.mouse_up_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - listener(event, &bounds, phase, cx); + listener(event, &*interactive_bounds, phase, cx); }) } for listener in self.mouse_move_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - listener(event, &bounds, phase, cx); + listener(event, &*interactive_bounds, phase, cx); }) } for listener in self.scroll_wheel_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - listener(event, &bounds, phase, cx); + listener(event, &*interactive_bounds, phase, cx); }) } @@ -792,6 +824,7 @@ impl Interactivity { .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); if let Some(group_bounds) = hover_group_bounds { + // todo!() needs cx.was_top_layer let hovered = group_bounds.contains_point(&cx.mouse_position()); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase == DispatchPhase::Capture { @@ -805,10 +838,11 @@ impl Interactivity { if self.hover_style.is_some() || (cx.active_drag.is_some() && !self.drag_over_styles.is_empty()) { - let hovered = bounds.contains_point(&cx.mouse_position()); + let interactive_bounds = interactive_bounds.clone(); + let hovered = interactive_bounds.visibly_contains(&cx.mouse_position(), cx); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase == DispatchPhase::Capture { - if bounds.contains_point(&event.position) != hovered { + if interactive_bounds.visibly_contains(&event.position, cx) != hovered { cx.notify(); } } @@ -817,8 +851,11 @@ impl Interactivity { if cx.active_drag.is_some() { let drop_listeners = mem::take(&mut self.drop_listeners); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, &cx) + { if let Some(drag_state_type) = cx.active_drag.as_ref().map(|drag| drag.view.entity_type()) { @@ -847,6 +884,7 @@ impl Interactivity { if let Some(mouse_down) = mouse_down { if let Some(drag_listener) = drag_listener { let active_state = element_state.clicked_state.clone(); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if cx.active_drag.is_some() { @@ -854,7 +892,7 @@ impl Interactivity { cx.notify(); } } else if phase == DispatchPhase::Bubble - && bounds.contains_point(&event.position) + && interactive_bounds.visibly_contains(&event.position, cx) && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD { *active_state.borrow_mut() = ElementClickedState::default(); @@ -867,8 +905,11 @@ impl Interactivity { }); } + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { let mouse_click = ClickEvent { down: mouse_down.clone(), up: event.clone(), @@ -881,8 +922,11 @@ impl Interactivity { cx.notify(); }); } else { + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { *pending_mouse_down.borrow_mut() = Some(event.clone()); cx.notify(); } @@ -893,13 +937,14 @@ impl Interactivity { if let Some(hover_listener) = self.hover_listener.take() { let was_hovered = element_state.hover_state.clone(); let has_mouse_down = element_state.pending_mouse_down.clone(); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } - let is_hovered = - bounds.contains_point(&event.position) && has_mouse_down.borrow().is_none(); + let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) + && has_mouse_down.borrow().is_none(); let mut was_hovered = was_hovered.borrow_mut(); if is_hovered != was_hovered.clone() { @@ -914,14 +959,15 @@ impl Interactivity { if let Some(tooltip_builder) = self.tooltip_builder.take() { let active_tooltip = element_state.active_tooltip.clone(); let pending_mouse_down = element_state.pending_mouse_down.clone(); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase != DispatchPhase::Bubble { return; } - let is_hovered = - bounds.contains_point(&event.position) && pending_mouse_down.borrow().is_none(); + let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) + && pending_mouse_down.borrow().is_none(); if !is_hovered { active_tooltip.borrow_mut().take(); return; @@ -979,11 +1025,12 @@ impl Interactivity { .group_active_style .as_ref() .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Bubble { let group = active_group_bounds .map_or(false, |bounds| bounds.contains_point(&down.position)); - let element = bounds.contains_point(&down.position); + let element = interactive_bounds.visibly_contains(&down.position, cx); if group || element { *active_state.borrow_mut() = ElementClickedState { group, element }; cx.notify(); @@ -1000,9 +1047,12 @@ impl Interactivity { .clone(); let line_height = cx.line_height(); let scroll_max = (content_size - bounds.size).max(&Size::default()); + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { let mut scroll_offset = scroll_offset.borrow_mut(); let old_scroll_offset = *scroll_offset; let delta = event.delta.pixel_delta(line_height); @@ -1098,19 +1148,21 @@ impl Interactivity { } } } - // if self.hover_style.is_some() { - if bounds.contains_point(&mouse_position) { - // eprintln!("div hovered {bounds:?} {mouse_position:?}"); - style.refine(&self.hover_style); - } else { - // eprintln!("div NOT hovered {bounds:?} {mouse_position:?}"); + if self.hover_style.is_some() { + if bounds + .intersect(&cx.content_mask().bounds) + .contains_point(&mouse_position) + && cx.was_top_layer(&mouse_position, cx.stacking_order()) + { + style.refine(&self.hover_style); + } } - // } if let Some(drag) = cx.active_drag.take() { for (state_type, group_drag_style) in &self.group_drag_over_styles { if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { if *state_type == drag.view.entity_type() + // todo!() needs to handle cx.content_mask() and cx.is_top() && group_bounds.contains_point(&mouse_position) { style.refine(&group_drag_style.style); @@ -1120,7 +1172,10 @@ impl Interactivity { for (state_type, drag_over_style) in &self.drag_over_styles { if *state_type == drag.view.entity_type() - && bounds.contains_point(&mouse_position) + && bounds + .intersect(&cx.content_mask().bounds) + .contains_point(&mouse_position) + && cx.was_top_layer(&mouse_position, cx.stacking_order()) { style.refine(drag_over_style); } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 20561c544368b6b9c41124194c07ada33145c968..6f342f70654653808d6b9797c898682ba4c532e8 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -39,8 +39,8 @@ use util::ResultExt; /// A global stacking order, which is created by stacking successive z-index values. /// Each z-index will always be interpreted in the context of its parent z-index. -#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Default)] -pub(crate) struct StackingOrder(pub(crate) SmallVec<[u32; 16]>); +#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Default, Debug)] +pub struct StackingOrder(pub(crate) SmallVec<[u32; 16]>); /// Represents the two different phases when dispatching events. #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] @@ -243,7 +243,8 @@ pub(crate) struct Frame { pub(crate) dispatch_tree: DispatchTree, pub(crate) focus_listeners: Vec, pub(crate) scene_builder: SceneBuilder, - z_index_stack: StackingOrder, + pub(crate) depth_map: Vec<(StackingOrder, Bounds)>, + pub(crate) z_index_stack: StackingOrder, content_mask_stack: Vec>, element_offset_stack: Vec>, } @@ -257,6 +258,7 @@ impl Frame { focus_listeners: Vec::new(), scene_builder: SceneBuilder::default(), z_index_stack: StackingOrder::default(), + depth_map: Default::default(), content_mask_stack: Vec::new(), element_offset_stack: Vec::new(), } @@ -806,6 +808,32 @@ impl<'a> WindowContext<'a> { result } + /// Called during painting to track which z-index is on top at each pixel position + pub fn add_opaque_layer(&mut self, bounds: Bounds) { + let stacking_order = self.window.current_frame.z_index_stack.clone(); + let depth_map = &mut self.window.current_frame.depth_map; + match depth_map.binary_search_by(|(level, _)| stacking_order.cmp(&level)) { + Ok(i) | Err(i) => depth_map.insert(i, (stacking_order, bounds)), + } + } + + /// Returns true if the top-most opaque layer painted over this point was part of the + /// same layer as the given stacking order. + pub fn was_top_layer(&self, point: &Point, level: &StackingOrder) -> bool { + for (stack, bounds) in self.window.previous_frame.depth_map.iter() { + if bounds.contains_point(point) { + return level.starts_with(stack) || stack.starts_with(level); + } + } + + false + } + + /// Called during painting to get the current stacking order. + pub fn stacking_order(&self) -> &StackingOrder { + &self.window.current_frame.z_index_stack + } + /// Paint one or more drop shadows into the scene for the current frame at the current z-index. pub fn paint_shadows( &mut self, @@ -1153,6 +1181,7 @@ impl<'a> WindowContext<'a> { frame.mouse_listeners.values_mut().for_each(Vec::clear); frame.focus_listeners.clear(); frame.dispatch_tree.clear(); + frame.depth_map.clear(); } /// Dispatch a mouse or keyboard event on the window. diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index ea31419201748ade52647504026d3d23e5ac27ea..8ab85a97eccecb83b0621b03a09cbc1409c4df39 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -114,7 +114,6 @@ impl Picker { } fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { - dbg!("canceling!"); self.delegate.dismissed(cx); } diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 6d28a6299b9f6cbef4231eda2f2bf5d087a3e9d4..a9b6189fdc313394061f21abb1449d6664f3daed 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -46,7 +46,6 @@ impl ModalLayer { previous_focus_handle: cx.focused(), focus_handle: cx.focus_handle(), }); - dbg!("focusing"); cx.focus_view(&new_modal); cx.notify(); } @@ -96,10 +95,6 @@ impl Render for ModalLayer { .track_focus(&active_modal.focus_handle) .child( h_stack() - // needed to prevent mouse events leaking to the - // UI below. // todo! for gpui3. - .on_any_mouse_down(|_, cx| cx.stop_propagation()) - .on_any_mouse_up(|_, cx| cx.stop_propagation()) .on_mouse_down_out(cx.listener(|this, _, cx| { this.hide_modal(cx); })) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 50f8611c4cc645c414ad68c030867ab4b8f07dab..6fa722f7757615ad01acdddfc8d527f457f94411 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2640,12 +2640,11 @@ impl Workspace { .flex_col() .justify_end() .gap_2() - .children(self.notifications.iter().map(|(_, _, notification)| { - div() - .on_any_mouse_down(|_, cx| cx.stop_propagation()) - .on_any_mouse_up(|_, cx| cx.stop_propagation()) - .child(notification.to_any()) - })), + .children( + self.notifications + .iter() + .map(|(_, _, notification)| notification.to_any()), + ), ) } }