diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index daeb355b048d649d638a8830bdf3d367ea9cd40b..a6d9e593cc4b2d8d593f48a7887e6308ff0e63cb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -9893,7 +9893,14 @@ impl Editor { origin.x -= BORDER_WIDTH; - window.defer_draw(element, origin, 1); + window.with_content_mask( + Some(gpui::ContentMask { + bounds: *text_bounds, + }), + |window| { + window.defer_draw(element, origin, 1, Some(window.content_mask())); + }, + ); // Do not return an element, since it will already be drawn due to defer_draw. None diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 4779784ad75fbbe3740bf63572c2bd8cec06f1da..6fc2627533dde920c021b14d5d172cbef40d7a95 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -2863,7 +2863,7 @@ impl EditorElement { } }); - window.defer_draw(element, origin, 2); + window.defer_draw(element, origin, 2, None); } } @@ -5108,7 +5108,7 @@ impl EditorElement { current_position.y -= size.height; } let position = current_position; - window.defer_draw(element, current_position, 1); + window.defer_draw(element, current_position, 1, None); if !y_flipped { current_position.y += size.height + MENU_GAP; } else { @@ -5211,7 +5211,7 @@ impl EditorElement { // Skip drawing if it doesn't fit anywhere. if let Some((aside, position, size)) = positioned_aside { let aside_bounds = Bounds::new(position, size); - window.defer_draw(aside, position, 2); + window.defer_draw(aside, position, 2, None); return Some(aside_bounds); } @@ -5420,7 +5420,7 @@ impl EditorElement { .on_mouse_move(|_, _, cx| cx.stop_propagation()) .into_any_element(); occlusion.layout_as_root(size(width, HOVER_POPOVER_GAP).into(), window, cx); - window.defer_draw(occlusion, origin, 2); + window.defer_draw(occlusion, origin, 2, None); } fn place_popovers_above( @@ -5437,7 +5437,7 @@ impl EditorElement { current_y - size.height, ); - window.defer_draw(popover.element, popover_origin, 2); + window.defer_draw(popover.element, popover_origin, 2, None); if position != itertools::Position::Last { let origin = point(popover_origin.x, popover_origin.y - HOVER_POPOVER_GAP); draw_occluder(size.width, origin, window, cx); @@ -5459,7 +5459,7 @@ impl EditorElement { let size = popover.size; let popover_origin = point(hovered_point.x + popover.horizontal_offset, current_y); - window.defer_draw(popover.element, popover_origin, 2); + window.defer_draw(popover.element, popover_origin, 2, None); if position != itertools::Position::Last { let origin = point(popover_origin.x, popover_origin.y + size.height); draw_occluder(size.width, origin, window, cx); @@ -5561,7 +5561,7 @@ impl EditorElement { let size = popover.size; let popover_origin = point(origin.x, current_y); - window.defer_draw(popover.element, popover_origin, 2); + window.defer_draw(popover.element, popover_origin, 2, None); if position != itertools::Position::Last { let origin = point(popover_origin.x, popover_origin.y + size.height); draw_occluder(size.width, origin, window, cx); @@ -5893,7 +5893,7 @@ impl EditorElement { }) }; - window.defer_draw(element, final_origin, 2); + window.defer_draw(element, final_origin, 2, None); } fn paint_background(&self, layout: &EditorLayout, window: &mut Window, cx: &mut App) { diff --git a/crates/gpui/src/elements/deferred.rs b/crates/gpui/src/elements/deferred.rs index 9498734198dbe58798867ebe7f20138e5667777b..25245fa4b6ea70284658bf0b91b53ca395b750dd 100644 --- a/crates/gpui/src/elements/deferred.rs +++ b/crates/gpui/src/elements/deferred.rs @@ -62,7 +62,7 @@ impl Element for Deferred { ) { let child = self.child.take().unwrap(); let element_offset = window.element_offset(); - window.defer_draw(child, element_offset, self.priority) + window.defer_draw(child, element_offset, self.priority, None) } fn paint( diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index df5948cb99e75a1f15d5b9a63cb1c3a5a29fac03..3fcb911d2c58f8968bc6b0c66f26ed2de365dd53 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -726,6 +726,7 @@ pub(crate) struct DeferredDraw { parent_node: DispatchNodeId, element_id_stack: SmallVec<[ElementId; 32]>, text_style_stack: Vec, + content_mask: Option>, rem_size: Pixels, element: Option, absolute_offset: Point, @@ -2429,15 +2430,18 @@ impl Window { .set_active_node(deferred_draw.parent_node); let prepaint_start = self.prepaint_index(); + let content_mask = deferred_draw.content_mask.clone(); if let Some(element) = deferred_draw.element.as_mut() { self.with_rendered_view(deferred_draw.current_view, |window| { - window.with_rem_size(Some(deferred_draw.rem_size), |window| { - window.with_absolute_element_offset( - deferred_draw.absolute_offset, - |window| { - element.prepaint(window, cx); - }, - ); + window.with_content_mask(content_mask, |window| { + window.with_rem_size(Some(deferred_draw.rem_size), |window| { + window.with_absolute_element_offset( + deferred_draw.absolute_offset, + |window| { + element.prepaint(window, cx); + }, + ); + }); }); }) } else { @@ -2469,10 +2473,13 @@ impl Window { .set_active_node(deferred_draw.parent_node); let paint_start = self.paint_index(); + let content_mask = deferred_draw.content_mask.clone(); if let Some(element) = deferred_draw.element.as_mut() { self.with_rendered_view(deferred_draw.current_view, |window| { - window.with_rem_size(Some(deferred_draw.rem_size), |window| { - element.paint(window, cx); + window.with_content_mask(content_mask, |window| { + window.with_rem_size(Some(deferred_draw.rem_size), |window| { + element.paint(window, cx); + }); }) }) } else { @@ -2536,6 +2543,7 @@ impl Window { parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node), element_id_stack: deferred_draw.element_id_stack.clone(), text_style_stack: deferred_draw.text_style_stack.clone(), + content_mask: deferred_draw.content_mask.clone(), rem_size: deferred_draw.rem_size, priority: deferred_draw.priority, element: None, @@ -3019,12 +3027,16 @@ impl Window { /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements, /// with higher values being drawn on top. /// + /// When `content_mask` is provided, the deferred element will be clipped to that region during + /// both prepaint and paint. When `None`, no additional clipping is applied. + /// /// This method should only be called as part of the prepaint phase of element drawing. pub fn defer_draw( &mut self, element: AnyElement, absolute_offset: Point, priority: usize, + content_mask: Option>, ) { self.invalidator.debug_assert_prepaint(); let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap(); @@ -3033,6 +3045,7 @@ impl Window { parent_node, element_id_stack: self.element_id_stack.clone(), text_style_stack: self.text_style_stack.clone(), + content_mask, rem_size: self.rem_size(), priority, element: Some(element),