Detailed changes
@@ -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<DispatchNodeId>,
pub(crate) context_stack: Vec<KeyContext>,
+ view_stack: Vec<EntityId>,
nodes: Vec<DispatchNode>,
focusable_node_ids: FxHashMap<FocusId, DispatchNodeId>,
view_node_ids: FxHashMap<EntityId, DispatchNodeId>,
@@ -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<EntityId> {
+ self.view_stack.last().copied()
+ }
+
pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
&self.nodes[node_id.0]
}
@@ -11,13 +11,12 @@ pub(crate) type PointF = Point<f32>;
pub(crate) type PathVertex_ScaledPixels = PathVertex<ScaledPixels>;
pub type LayerId = u32;
-
pub type DrawOrder = u32;
#[derive(Default)]
pub(crate) struct SceneBuilder {
- last_order: Option<(StackingOrder, LayerId)>,
layers_by_order: BTreeMap<StackingOrder, LayerId>,
+ orders_by_layer: BTreeMap<LayerId, StackingOrder>,
shadows: Vec<Shadow>,
quads: Vec<Quad>,
paths: Vec<Path<ScaledPixels>>,
@@ -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<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub background: Hsla,
@@ -469,7 +462,9 @@ impl From<Quad> 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<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub thickness: ScaledPixels,
@@ -498,7 +493,9 @@ impl From<Underline> 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<ScaledPixels>,
pub corner_radii: Corners<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
@@ -527,7 +524,9 @@ impl From<Shadow> 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<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub color: Hsla,
@@ -558,7 +557,9 @@ impl From<MonochromeSprite> 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<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub corner_radii: Corners<ScaledPixels>,
@@ -589,7 +590,9 @@ impl From<PolychromeSprite> 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<ScaledPixels>,
pub content_mask: ContentMask<ScaledPixels>,
pub image_buffer: media::core_video::CVImageBuffer,
@@ -619,7 +622,9 @@ pub(crate) struct PathId(pub(crate) usize);
#[derive(Debug)]
pub struct Path<P: Clone + Default + Debug> {
pub(crate) id: PathId,
- order: u32,
+ pub(crate) view_id: u32,
+ layer_id: LayerId,
+ order: DrawOrder,
pub(crate) bounds: Bounds<P>,
pub(crate) content_mask: ContentMask<P>,
pub(crate) vertices: Vec<PathVertex<P>>,
@@ -633,6 +638,8 @@ impl Path<Pixels> {
pub fn new(start: Point<Pixels>) -> Self {
Self {
id: PathId(0),
+ view_id: 0,
+ layer_id: 0,
order: 0,
vertices: Vec::new(),
start,
@@ -650,6 +657,8 @@ impl Path<Pixels> {
pub fn scale(&self, factor: f32) -> Path<ScaledPixels> {
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),
@@ -295,8 +295,6 @@ pub(crate) struct Frame {
pub(crate) next_stacking_order_id: u32,
content_mask_stack: Vec<ContentMask<Pixels>>,
element_offset_stack: Vec<Point<Pixels>>,
- pub(crate) view_parents: FxHashMap<EntityId, EntityId>,
- pub(crate) view_stack: Vec<EntityId>,
pub(crate) reused_views: FxHashSet<EntityId>,
}
@@ -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<Pixels>, color: impl Into<Hsla>) {
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<Window> + BorrowMut<AppContext> {
}
fn with_view_id<R>(&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;
}
}