From 84b05d6c0564948369383a953a65666597b082eb Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 9 Jan 2024 15:12:23 +0100 Subject: [PATCH] Maintain view stack as part of `DispatchTree` --- crates/gpui/src/key_dispatch.rs | 42 +++++++++++++++-- crates/gpui/src/scene.rs | 79 +++++++++++++++++-------------- crates/gpui/src/window.rs | 83 +++++++++++++++++++++++---------- 3 files changed, 139 insertions(+), 65 deletions(-) diff --git a/crates/gpui/src/key_dispatch.rs b/crates/gpui/src/key_dispatch.rs index 9019670b04..af836b7166 100644 --- a/crates/gpui/src/key_dispatch.rs +++ b/crates/gpui/src/key_dispatch.rs @@ -4,7 +4,7 @@ use crate::{ }; use collections::FxHashMap; use parking_lot::Mutex; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::{ any::{Any, TypeId}, mem, @@ -18,6 +18,7 @@ pub struct DispatchNodeId(usize); pub(crate) struct DispatchTree { node_stack: Vec, pub(crate) context_stack: Vec, + view_stack: Vec, nodes: Vec, focusable_node_ids: FxHashMap, view_node_ids: FxHashMap, @@ -49,6 +50,7 @@ impl DispatchTree { Self { node_stack: Vec::new(), context_stack: Vec::new(), + view_stack: Vec::new(), nodes: Vec::new(), focusable_node_ids: FxHashMap::default(), view_node_ids: FxHashMap::default(), @@ -60,8 +62,9 @@ impl DispatchTree { pub fn clear(&mut self) { self.node_stack.clear(); - self.nodes.clear(); self.context_stack.clear(); + self.view_stack.clear(); + self.nodes.clear(); self.focusable_node_ids.clear(); self.view_node_ids.clear(); self.keystroke_matchers.clear(); @@ -82,10 +85,14 @@ impl DispatchTree { } pub fn pop_node(&mut self) { - let node_id = self.node_stack.pop().unwrap(); - if self.nodes[node_id.0].context.is_some() { + let node = &self.nodes[self.active_node_id().0]; + if node.context.is_some() { self.context_stack.pop(); } + if node.view_id.is_some() { + self.view_stack.pop(); + } + self.node_stack.pop(); } fn move_node(&mut self, source_node: &mut DispatchNode) { @@ -102,7 +109,7 @@ impl DispatchTree { target_node.action_listeners = mem::take(&mut source_node.action_listeners); } - pub fn graft(&mut self, view_id: EntityId, source: &mut Self) { + pub fn graft(&mut self, view_id: EntityId, source: &mut Self) -> SmallVec<[EntityId; 8]> { let view_source_node_id = source .view_node_ids .get(&view_id) @@ -110,6 +117,7 @@ impl DispatchTree { let view_source_node = &mut source.nodes[view_source_node_id.0]; self.move_node(view_source_node); + let mut grafted_view_ids = smallvec![view_id]; let mut source_stack = vec![*view_source_node_id]; for (source_node_id, source_node) in source .nodes @@ -130,12 +138,17 @@ impl DispatchTree { } else { source_stack.push(source_node_id); self.move_node(source_node); + if let Some(view_id) = source_node.view_id { + grafted_view_ids.push(view_id); + } } } while !source_stack.is_empty() { self.pop_node(); } + + grafted_view_ids } pub fn clear_pending_keystrokes(&mut self) { @@ -192,6 +205,7 @@ impl DispatchTree { let node_id = self.active_node_id(); self.active_node().view_id = Some(view_id); self.view_node_ids.insert(view_id, node_id); + self.view_stack.push(view_id); } pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool { @@ -322,6 +336,24 @@ impl DispatchTree { focus_path } + pub fn view_path(&self, view_id: EntityId) -> SmallVec<[EntityId; 8]> { + let mut view_path: SmallVec<[EntityId; 8]> = SmallVec::new(); + let mut current_node_id = self.view_node_ids.get(&view_id).copied(); + while let Some(node_id) = current_node_id { + let node = self.node(node_id); + if let Some(view_id) = node.view_id { + view_path.push(view_id); + } + current_node_id = node.parent; + } + view_path.reverse(); // Reverse the path so it goes from the root to the view node. + view_path + } + + pub fn active_view_id(&self) -> Option { + self.view_stack.last().copied() + } + pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode { &self.nodes[node_id.0] } diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index e922c11f53..42183100b7 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -11,13 +11,12 @@ pub(crate) type PointF = Point; pub(crate) type PathVertex_ScaledPixels = PathVertex; pub type LayerId = u32; - pub type DrawOrder = u32; #[derive(Default)] pub(crate) struct SceneBuilder { - last_order: Option<(StackingOrder, LayerId)>, layers_by_order: BTreeMap, + orders_by_layer: BTreeMap, shadows: Vec, quads: Vec, paths: Vec>, @@ -34,40 +33,39 @@ impl SceneBuilder { orders[*layer_id as usize] = ix as u32; } self.layers_by_order.clear(); - self.last_order = None; for shadow in &mut self.shadows { - shadow.order = orders[shadow.order as usize]; + shadow.order = orders[shadow.layer_id as usize]; } self.shadows.sort_by_key(|shadow| shadow.order); for quad in &mut self.quads { - quad.order = orders[quad.order as usize]; + quad.order = orders[quad.layer_id as usize]; } self.quads.sort_by_key(|quad| quad.order); for path in &mut self.paths { - path.order = orders[path.order as usize]; + path.order = orders[path.layer_id as usize]; } self.paths.sort_by_key(|path| path.order); for underline in &mut self.underlines { - underline.order = orders[underline.order as usize]; + underline.order = orders[underline.layer_id as usize]; } self.underlines.sort_by_key(|underline| underline.order); for monochrome_sprite in &mut self.monochrome_sprites { - monochrome_sprite.order = orders[monochrome_sprite.order as usize]; + monochrome_sprite.order = orders[monochrome_sprite.layer_id as usize]; } self.monochrome_sprites.sort_by_key(|sprite| sprite.order); for polychrome_sprite in &mut self.polychrome_sprites { - polychrome_sprite.order = orders[polychrome_sprite.order as usize]; + polychrome_sprite.order = orders[polychrome_sprite.layer_id as usize]; } self.polychrome_sprites.sort_by_key(|sprite| sprite.order); for surface in &mut self.surfaces { - surface.order = orders[surface.order as usize]; + surface.order = orders[surface.layer_id as usize]; } self.surfaces.sort_by_key(|surface| surface.order); @@ -96,53 +94,46 @@ impl SceneBuilder { let layer_id = self.layer_id_for_order(order); match primitive { Primitive::Shadow(mut shadow) => { - shadow.order = layer_id; + shadow.layer_id = layer_id; self.shadows.push(shadow); } Primitive::Quad(mut quad) => { - quad.order = layer_id; + quad.layer_id = layer_id; self.quads.push(quad); } Primitive::Path(mut path) => { - path.order = layer_id; + path.layer_id = layer_id; path.id = PathId(self.paths.len()); self.paths.push(path); } Primitive::Underline(mut underline) => { - underline.order = layer_id; + underline.layer_id = layer_id; self.underlines.push(underline); } Primitive::MonochromeSprite(mut sprite) => { - sprite.order = layer_id; + sprite.layer_id = layer_id; self.monochrome_sprites.push(sprite); } Primitive::PolychromeSprite(mut sprite) => { - sprite.order = layer_id; + sprite.layer_id = layer_id; self.polychrome_sprites.push(sprite); } Primitive::Surface(mut surface) => { - surface.order = layer_id; + surface.layer_id = layer_id; self.surfaces.push(surface); } } } - fn layer_id_for_order(&mut self, order: &StackingOrder) -> u32 { - if let Some((last_order, last_layer_id)) = self.last_order.as_ref() { - if last_order == order { - return *last_layer_id; - } - }; - - let layer_id = if let Some(layer_id) = self.layers_by_order.get(order) { + fn layer_id_for_order(&mut self, order: &StackingOrder) -> LayerId { + if let Some(layer_id) = self.layers_by_order.get(order) { *layer_id } else { let next_id = self.layers_by_order.len() as LayerId; self.layers_by_order.insert(order.clone(), next_id); + self.orders_by_layer.insert(next_id, order.clone()); next_id - }; - self.last_order = Some((order.clone(), layer_id)); - layer_id + } } } @@ -439,7 +430,9 @@ pub(crate) enum PrimitiveBatch<'a> { #[derive(Default, Debug, Clone, Eq, PartialEq)] #[repr(C)] pub struct Quad { - pub order: u32, // Initially a LayerId, then a DrawOrder. + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub content_mask: ContentMask, pub background: Hsla, @@ -469,7 +462,9 @@ impl From for Primitive { #[derive(Debug, Clone, Eq, PartialEq)] #[repr(C)] pub struct Underline { - pub order: u32, + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub content_mask: ContentMask, pub thickness: ScaledPixels, @@ -498,7 +493,9 @@ impl From for Primitive { #[derive(Debug, Clone, Eq, PartialEq)] #[repr(C)] pub struct Shadow { - pub order: u32, + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub corner_radii: Corners, pub content_mask: ContentMask, @@ -527,7 +524,9 @@ impl From for Primitive { #[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] pub struct MonochromeSprite { - pub order: u32, + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub content_mask: ContentMask, pub color: Hsla, @@ -558,7 +557,9 @@ impl From for Primitive { #[derive(Clone, Debug, Eq, PartialEq)] #[repr(C)] pub struct PolychromeSprite { - pub order: u32, + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub content_mask: ContentMask, pub corner_radii: Corners, @@ -589,7 +590,9 @@ impl From for Primitive { #[derive(Clone, Debug, Eq, PartialEq)] pub struct Surface { - pub order: u32, + pub view_id: u32, + pub layer_id: LayerId, + pub order: DrawOrder, pub bounds: Bounds, pub content_mask: ContentMask, pub image_buffer: media::core_video::CVImageBuffer, @@ -619,7 +622,9 @@ pub(crate) struct PathId(pub(crate) usize); #[derive(Debug)] pub struct Path { pub(crate) id: PathId, - order: u32, + pub(crate) view_id: u32, + layer_id: LayerId, + order: DrawOrder, pub(crate) bounds: Bounds

, pub(crate) content_mask: ContentMask

, pub(crate) vertices: Vec>, @@ -633,6 +638,8 @@ impl Path { pub fn new(start: Point) -> Self { Self { id: PathId(0), + view_id: 0, + layer_id: 0, order: 0, vertices: Vec::new(), start, @@ -650,6 +657,8 @@ impl Path { pub fn scale(&self, factor: f32) -> Path { Path { id: self.id, + view_id: self.view_id, + layer_id: self.layer_id, order: self.order, bounds: self.bounds.scale(factor), content_mask: self.content_mask.scale(factor), diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index e5f9195b69..f21b8b3b80 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -295,8 +295,6 @@ pub(crate) struct Frame { pub(crate) next_stacking_order_id: u32, content_mask_stack: Vec>, element_offset_stack: Vec>, - pub(crate) view_parents: FxHashMap, - pub(crate) view_stack: Vec, pub(crate) reused_views: FxHashSet, } @@ -313,8 +311,6 @@ impl Frame { depth_map: Default::default(), content_mask_stack: Vec::new(), element_offset_stack: Vec::new(), - view_parents: FxHashMap::default(), - view_stack: Vec::new(), reused_views: FxHashSet::default(), } } @@ -325,8 +321,6 @@ impl Frame { self.dispatch_tree.clear(); self.depth_map.clear(); self.next_stacking_order_id = 0; - self.view_parents.clear(); - debug_assert!(self.view_stack.is_empty()); self.reused_views.clear(); } @@ -886,8 +880,8 @@ impl<'a> WindowContext<'a> { &mut self, mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { + let view_id = self.active_view_id(); let order = self.window.next_frame.z_index_stack.clone(); - let view_id = *self.window.next_frame.view_stack.last().unwrap(); self.window .next_frame .mouse_listeners @@ -1029,6 +1023,7 @@ impl<'a> WindowContext<'a> { ) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); + let view_id = self.active_view_id(); let window = &mut *self.window; for shadow in shadows { let mut shadow_bounds = bounds; @@ -1037,6 +1032,8 @@ impl<'a> WindowContext<'a> { window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, Shadow { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds: shadow_bounds.scale(scale_factor), content_mask: content_mask.scale(scale_factor), @@ -1054,11 +1051,14 @@ impl<'a> WindowContext<'a> { pub fn paint_quad(&mut self, quad: PaintQuad) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, Quad { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds: quad.bounds.scale(scale_factor), content_mask: content_mask.scale(scale_factor), @@ -1074,8 +1074,11 @@ impl<'a> WindowContext<'a> { pub fn paint_path(&mut self, mut path: Path, color: impl Into) { let scale_factor = self.scale_factor(); let content_mask = self.content_mask(); + let view_id = self.active_view_id(); + path.content_mask = content_mask; path.color = color.into(); + path.view_id = view_id.as_u64() as u32; let window = &mut *self.window; window .next_frame @@ -1101,10 +1104,14 @@ impl<'a> WindowContext<'a> { size: size(width, height), }; let content_mask = self.content_mask(); + let view_id = self.active_view_id(); + let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, Underline { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds: bounds.scale(scale_factor), content_mask: content_mask.scale(scale_factor), @@ -1154,10 +1161,13 @@ impl<'a> WindowContext<'a> { size: tile.bounds.size.map(Into::into), }; let content_mask = self.content_mask().scale(scale_factor); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, MonochromeSprite { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds, content_mask, @@ -1204,11 +1214,14 @@ impl<'a> WindowContext<'a> { size: tile.bounds.size.map(Into::into), }; let content_mask = self.content_mask().scale(scale_factor); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, PolychromeSprite { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds, corner_radii: Default::default(), @@ -1246,11 +1259,14 @@ impl<'a> WindowContext<'a> { Ok((params.size, Cow::Owned(bytes))) })?; let content_mask = self.content_mask().scale(scale_factor); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, MonochromeSprite { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds, content_mask, @@ -1282,11 +1298,14 @@ impl<'a> WindowContext<'a> { })?; let content_mask = self.content_mask().scale(scale_factor); let corner_radii = corner_radii.scale(scale_factor); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, PolychromeSprite { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds, content_mask, @@ -1303,10 +1322,13 @@ impl<'a> WindowContext<'a> { let scale_factor = self.scale_factor(); let bounds = bounds.scale(scale_factor); let content_mask = self.content_mask().scale(scale_factor); + let view_id = self.active_view_id(); let window = &mut *self.window; window.next_frame.scene_builder.insert( &window.next_frame.z_index_stack, Surface { + view_id: view_id.as_u64() as u32, + layer_id: 0, order: 0, bounds, content_mask, @@ -1316,13 +1338,23 @@ impl<'a> WindowContext<'a> { } pub(crate) fn reuse_geometry(&mut self) { + let view_id = self.active_view_id(); let window = &mut self.window; - let view_id = *window.next_frame.view_stack.last().unwrap(); - assert!(window.next_frame.reused_views.insert(view_id)); - window + let grafted_view_ids = window .next_frame .dispatch_tree - .graft(view_id, &mut window.rendered_frame.dispatch_tree) + .graft(view_id, &mut window.rendered_frame.dispatch_tree); + for view_id in grafted_view_ids { + assert!(window.next_frame.reused_views.insert(view_id)); + } + } + + fn active_view_id(&self) -> EntityId { + self.window + .next_frame + .dispatch_tree + .active_view_id() + .expect("a view should always be active") } /// Draw pixels to the display for this window based on the contents of its scene. @@ -1375,6 +1407,7 @@ impl<'a> WindowContext<'a> { .draw(active_tooltip.cursor_offset, available_space, cx); }); } + self.window.dirty_views.clear(); self.window .next_frame @@ -1385,6 +1418,7 @@ impl<'a> WindowContext<'a> { ); self.window.next_frame.focus = self.window.focus; self.window.root_view = Some(root_view); + for (type_id, listeners) in &mut self.window.rendered_frame.mouse_listeners { let next_listeners = self .window @@ -1434,7 +1468,6 @@ impl<'a> WindowContext<'a> { } self.window.drawing = false; - self.window.dirty_views.clear(); ELEMENT_ARENA.with_borrow_mut(|element_arena| element_arena.clear()); scene @@ -2132,9 +2165,13 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { } fn with_view_id(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R { - self.window_mut().next_frame.view_stack.push(view_id); + self.window_mut().next_frame.dispatch_tree.push_node(None); + self.window_mut() + .next_frame + .dispatch_tree + .associate_view(view_id); let result = f(self); - self.window_mut().next_frame.view_stack.pop(); + self.window_mut().next_frame.dispatch_tree.pop_node(); result } @@ -2495,17 +2532,13 @@ impl<'a, V: 'static> ViewContext<'a, V> { } pub fn notify(&mut self) { - let mut dirty_view_id = Some(self.view.entity_id()); - while let Some(view_id) = dirty_view_id { - if self.window_cx.window.dirty_views.insert(view_id) { - dirty_view_id = self - .window_cx - .window - .rendered_frame - .view_parents - .get(&view_id) - .copied(); - } else { + for view_id in self + .window + .rendered_frame + .dispatch_tree + .view_path(self.view.entity_id()) + { + if !self.window.dirty_views.insert(view_id) { break; } }