Ignore invisible layers for mouse events (#3651)

Fixes clicking in the top/bottom 100px of the editor


Release Notes:

- N/A
This commit is contained in:
Conrad Irwin 2023-12-14 12:01:45 -07:00 committed by GitHub
commit 2efd7cedbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 139 deletions

View file

@ -1094,16 +1094,24 @@ impl EditorElement {
cursor.paint(content_origin, cx); cursor.paint(content_origin, cx);
} }
}); });
},
)
}
cx.with_z_index(1, |cx| { fn paint_overlays(
&mut self,
text_bounds: Bounds<Pixels>,
layout: &mut LayoutState,
cx: &mut WindowContext,
) {
let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO);
let start_row = layout.visible_display_row_range.start;
if let Some((position, mut context_menu)) = layout.context_menu.take() { if let Some((position, mut context_menu)) = layout.context_menu.take() {
let available_space = let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
size(AvailableSpace::MinContent, AvailableSpace::MinContent);
let context_menu_size = context_menu.measure(available_space, cx); let context_menu_size = context_menu.measure(available_space, cx);
let cursor_row_layout = &layout.position_map.line_layouts let cursor_row_layout =
[(position.row() - start_row) as usize] &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
.line;
let x = cursor_row_layout.x_for_index(position.column() as usize) let x = cursor_row_layout.x_for_index(position.column() as usize)
- layout.position_map.scroll_position.x; - layout.position_map.scroll_position.x;
let y = (position.row() + 1) as f32 * layout.position_map.line_height let y = (position.row() + 1) as f32 * layout.position_map.line_height
@ -1115,34 +1123,29 @@ impl EditorElement {
// Snap the right edge of the list to the right edge of the window if // Snap the right edge of the list to the right edge of the window if
// its horizontal bounds overflow. // its horizontal bounds overflow.
if list_origin.x + list_width > cx.viewport_size().width { if list_origin.x + list_width > cx.viewport_size().width {
list_origin.x = list_origin.x = (cx.viewport_size().width - list_width).max(Pixels::ZERO);
(cx.viewport_size().width - list_width).max(Pixels::ZERO);
} }
if list_origin.y + list_height > text_bounds.lower_right().y { if list_origin.y + list_height > text_bounds.lower_right().y {
list_origin.y -= layout.position_map.line_height + list_height; list_origin.y -= layout.position_map.line_height + list_height;
} }
cx.break_content_mask(|cx| { cx.break_content_mask(|cx| context_menu.draw(list_origin, available_space, cx));
context_menu.draw(list_origin, available_space, cx)
});
} }
if let Some((position, mut hover_popovers)) = layout.hover_popovers.take() { if let Some((position, mut hover_popovers)) = layout.hover_popovers.take() {
let available_space = let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
size(AvailableSpace::MinContent, AvailableSpace::MinContent);
// This is safe because we check on layout whether the required row is available // This is safe because we check on layout whether the required row is available
let hovered_row_layout = &layout.position_map.line_layouts let hovered_row_layout =
[(position.row() - start_row) as usize] &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
.line;
// Minimum required size: Take the first popover, and add 1.5 times the minimum popover // Minimum required size: Take the first popover, and add 1.5 times the minimum popover
// height. This is the size we will use to decide whether to render popovers above or below // height. This is the size we will use to decide whether to render popovers above or below
// the hovered line. // the hovered line.
let first_size = hover_popovers[0].measure(available_space, cx); let first_size = hover_popovers[0].measure(available_space, cx);
let height_to_reserve = first_size.height let height_to_reserve =
+ 1.5 * MIN_POPOVER_LINE_HEIGHT * layout.position_map.line_height; first_size.height + 1.5 * MIN_POPOVER_LINE_HEIGHT * layout.position_map.line_height;
// Compute Hovered Point // Compute Hovered Point
let x = hovered_row_layout.x_for_index(position.column() as usize) let x = hovered_row_layout.x_for_index(position.column() as usize)
@ -1156,8 +1159,7 @@ impl EditorElement {
let mut current_y = hovered_point.y; let mut current_y = hovered_point.y;
for mut hover_popover in hover_popovers { for mut hover_popover in hover_popovers {
let size = hover_popover.measure(available_space, cx); let size = hover_popover.measure(available_space, cx);
let mut popover_origin = let mut popover_origin = point(hovered_point.x, current_y - size.height);
point(hovered_point.x, current_y - size.height);
let x_out_of_bounds = let x_out_of_bounds =
text_bounds.upper_right().x - (popover_origin.x + size.width); text_bounds.upper_right().x - (popover_origin.x + size.width);
@ -1191,9 +1193,7 @@ impl EditorElement {
} }
} }
if let Some(mouse_context_menu) = if let Some(mouse_context_menu) = self.editor.read(cx).mouse_context_menu.as_ref() {
self.editor.read(cx).mouse_context_menu.as_ref()
{
let element = overlay() let element = overlay()
.position(mouse_context_menu.position) .position(mouse_context_menu.position)
.child(mouse_context_menu.context_menu.clone()) .child(mouse_context_menu.context_menu.clone())
@ -1206,9 +1206,6 @@ impl EditorElement {
|_, _| {}, |_, _| {},
); );
} }
})
},
)
} }
fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels { fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels {
@ -2807,14 +2804,7 @@ impl Element for EditorElement {
self.register_actions(cx); self.register_actions(cx);
self.register_key_listeners(cx); self.register_key_listeners(cx);
// 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| { cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
// Paint mouse listeners at z-index 0 so any elements we paint on top of the editor
// take precedence.
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); let input_handler = ElementInputHandler::new(bounds, self.editor.clone(), cx);
cx.handle_input(&focus_handle, input_handler); cx.handle_input(&focus_handle, input_handler);
@ -2824,15 +2814,20 @@ impl Element for EditorElement {
} }
self.paint_text(text_bounds, &mut layout, cx); self.paint_text(text_bounds, &mut layout, cx);
cx.with_z_index(0, |cx| {
self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx);
if !layout.blocks.is_empty() { if !layout.blocks.is_empty() {
cx.with_z_index(1, |cx| {
cx.with_element_id(Some("editor_blocks"), |cx| { cx.with_element_id(Some("editor_blocks"), |cx| {
self.paint_blocks(bounds, &mut layout, cx); self.paint_blocks(bounds, &mut layout, cx);
}); });
})
} }
});
cx.with_z_index(2, |cx| self.paint_scrollbar(bounds, &mut layout, cx)); cx.with_z_index(1, |cx| self.paint_scrollbar(bounds, &mut layout, cx));
cx.with_z_index(2, |cx| {
self.paint_overlays(text_bounds, &mut layout, cx);
}); });
}); });
}) })

View file

@ -642,10 +642,6 @@ impl Element for Div {
&mut element_state.interactive_state, &mut element_state.interactive_state,
cx, cx,
|style, scroll_offset, cx| { |style, scroll_offset, cx| {
if style.visibility == Visibility::Hidden {
return;
}
let z_index = style.z_index.unwrap_or(0); let z_index = style.z_index.unwrap_or(0);
cx.with_z_index(z_index, |cx| { cx.with_z_index(z_index, |cx| {
@ -779,6 +775,10 @@ impl Interactivity {
) { ) {
let style = self.compute_style(Some(bounds), element_state, cx); let style = self.compute_style(Some(bounds), element_state, cx);
if style.visibility == Visibility::Hidden {
return;
}
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
if self.element_id.is_some() if self.element_id.is_some()
&& (style.debug || style.debug_below || cx.has_global::<crate::DebugBelow>()) && (style.debug || style.debug_below || cx.has_global::<crate::DebugBelow>())
@ -893,7 +893,7 @@ impl Interactivity {
if style if style
.background .background
.as_ref() .as_ref()
.is_some_and(|fill| fill.color().is_some()) .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)) cx.with_z_index(style.z_index.unwrap_or(0), |cx| cx.add_opaque_layer(bounds))
} }