Rework frame rendering (#3531)

Antonio Scandurra created

This pull request replaces the old `previous_frame` and `current_frame`
with a new pair of `rendered_frame` and `next_frame` that are swapped
once we are ready to draw a finished frame.

This makes it clearer when to use which: `rendered_frame` should be used
to query the existing state, whereas `next_frame` should be used and
mutated when redrawing a dirty window.

The change was prompted by a bug I encountered in
`FocusHandle::contains`. The implementation was reading `current_frame`,
but that was the wrong field to access if e.g. we were reading it inside
of a `render` function or any other time while drawing the window.

Release Notes:

- N/A

Change summary

crates/gpui2/src/app.rs    |  13 +
crates/gpui2/src/window.rs | 248 ++++++++++++++++++---------------------
2 files changed, 120 insertions(+), 141 deletions(-)

Detailed changes

crates/gpui2/src/app.rs 🔗

@@ -704,14 +704,13 @@ impl AppContext {
                     let focus_changed = focused.is_some() || blurred.is_some();
                     let event = FocusEvent { focused, blurred };
 
-                    let mut listeners = mem::take(&mut cx.window.current_frame.focus_listeners);
+                    let mut listeners = mem::take(&mut cx.window.rendered_frame.focus_listeners);
                     if focus_changed {
                         for listener in &mut listeners {
                             listener(&event, cx);
                         }
                     }
-                    listeners.extend(cx.window.current_frame.focus_listeners.drain(..));
-                    cx.window.current_frame.focus_listeners = listeners;
+                    cx.window.rendered_frame.focus_listeners = listeners;
 
                     if focus_changed {
                         cx.window
@@ -1029,9 +1028,13 @@ impl AppContext {
             window
                 .update(self, |_, cx| {
                     cx.window
-                        .current_frame
+                        .rendered_frame
                         .dispatch_tree
-                        .clear_pending_keystrokes()
+                        .clear_pending_keystrokes();
+                    cx.window
+                        .next_frame
+                        .dispatch_tree
+                        .clear_pending_keystrokes();
                 })
                 .ok();
         }

crates/gpui2/src/window.rs 🔗

@@ -90,7 +90,7 @@ impl FocusId {
     /// Obtains whether this handle contains the given handle in the most recently rendered frame.
     pub(crate) fn contains(&self, other: Self, cx: &WindowContext) -> bool {
         cx.window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .focus_contains(*self, other)
     }
@@ -212,8 +212,8 @@ pub struct Window {
     layout_engine: Option<TaffyLayoutEngine>,
     pub(crate) root_view: Option<AnyView>,
     pub(crate) element_id_stack: GlobalElementId,
-    pub(crate) previous_frame: Frame,
-    pub(crate) current_frame: Frame,
+    pub(crate) rendered_frame: Frame,
+    pub(crate) next_frame: Frame,
     pub(crate) focus_handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
     pub(crate) focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
     default_prevented: bool,
@@ -249,7 +249,7 @@ pub(crate) struct Frame {
 }
 
 impl Frame {
-    pub fn new(dispatch_tree: DispatchTree) -> Self {
+    fn new(dispatch_tree: DispatchTree) -> Self {
         Frame {
             element_states: HashMap::default(),
             mouse_listeners: HashMap::default(),
@@ -262,6 +262,14 @@ impl Frame {
             element_offset_stack: Vec::new(),
         }
     }
+
+    fn clear(&mut self) {
+        self.element_states.clear();
+        self.mouse_listeners.values_mut().for_each(Vec::clear);
+        self.focus_listeners.clear();
+        self.dispatch_tree.clear();
+        self.depth_map.clear();
+    }
 }
 
 impl Window {
@@ -330,8 +338,8 @@ impl Window {
             layout_engine: Some(TaffyLayoutEngine::new()),
             root_view: None,
             element_id_stack: GlobalElementId::default(),
-            previous_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
-            current_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
+            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
+            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
             focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
             focus_listeners: SubscriberSet::new(),
             default_prevented: true,
@@ -428,7 +436,7 @@ impl<'a> WindowContext<'a> {
 
         self.window.focus = Some(focus_id);
         self.window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .clear_pending_keystrokes();
         self.app.push_effect(Effect::FocusChanged {
@@ -459,11 +467,11 @@ impl<'a> WindowContext<'a> {
             let node_id = focus_handle
                 .and_then(|handle| {
                     cx.window
-                        .current_frame
+                        .rendered_frame
                         .dispatch_tree
                         .focusable_node_id(handle.id)
                 })
-                .unwrap_or_else(|| cx.window.current_frame.dispatch_tree.root_node_id());
+                .unwrap_or_else(|| cx.window.rendered_frame.dispatch_tree.root_node_id());
 
             cx.propagate_event = true;
             cx.dispatch_action_on_node(node_id, action);
@@ -743,7 +751,7 @@ impl<'a> WindowContext<'a> {
         self.window.default_prevented
     }
 
-    /// Register a mouse event listener on the window for the current frame. The type of event
+    /// Register a mouse event listener on the window for the next frame. The type of event
     /// is determined by the first parameter of the given listener. When the next frame is rendered
     /// the listener will be cleared.
     ///
@@ -753,9 +761,9 @@ impl<'a> WindowContext<'a> {
         &mut self,
         handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static,
     ) {
-        let order = self.window.current_frame.z_index_stack.clone();
+        let order = self.window.next_frame.z_index_stack.clone();
         self.window
-            .current_frame
+            .next_frame
             .mouse_listeners
             .entry(TypeId::of::<Event>())
             .or_default()
@@ -767,7 +775,7 @@ impl<'a> WindowContext<'a> {
             ))
     }
 
-    /// Register a key event listener on the window for the current frame. The type of event
+    /// Register a key event listener on the window for the next frame. The type of event
     /// is determined by the first parameter of the given listener. When the next frame is rendered
     /// the listener will be cleared.
     ///
@@ -778,7 +786,7 @@ impl<'a> WindowContext<'a> {
         handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static,
     ) {
         self.window
-            .current_frame
+            .next_frame
             .dispatch_tree
             .on_key_event(Rc::new(move |event, phase, cx| {
                 if let Some(event) = event.downcast_ref::<Event>() {
@@ -787,7 +795,7 @@ impl<'a> WindowContext<'a> {
             }));
     }
 
-    /// Register an action listener on the window for the current frame. The type of action
+    /// Register an action listener on the window for the next frame. The type of action
     /// is determined by the first parameter of the given listener. When the next frame is rendered
     /// the listener will be cleared.
     ///
@@ -798,7 +806,7 @@ impl<'a> WindowContext<'a> {
         action_type: TypeId,
         handler: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static,
     ) {
-        self.window.current_frame.dispatch_tree.on_action(
+        self.window.next_frame.dispatch_tree.on_action(
             action_type,
             Rc::new(move |action, phase, cx| handler(action, phase, cx)),
         );
@@ -809,13 +817,13 @@ impl<'a> WindowContext<'a> {
             .focused()
             .and_then(|focused_handle| {
                 self.window
-                    .current_frame
+                    .rendered_frame
                     .dispatch_tree
                     .focusable_node_id(focused_handle.id)
             })
-            .unwrap_or_else(|| self.window.current_frame.dispatch_tree.root_node_id());
+            .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
         self.window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .is_action_available(action, target)
     }
@@ -832,16 +840,16 @@ impl<'a> WindowContext<'a> {
     /// Called during painting to invoke the given closure in a new stacking context. The given
     /// z-index is interpreted relative to the previous call to `stack`.
     pub fn with_z_index<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
-        self.window.current_frame.z_index_stack.push(z_index);
+        self.window.next_frame.z_index_stack.push(z_index);
         let result = f(self);
-        self.window.current_frame.z_index_stack.pop();
+        self.window.next_frame.z_index_stack.pop();
         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<Pixels>) {
-        let stacking_order = self.window.current_frame.z_index_stack.clone();
-        let depth_map = &mut self.window.current_frame.depth_map;
+        let stacking_order = self.window.next_frame.z_index_stack.clone();
+        let depth_map = &mut self.window.next_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)),
         }
@@ -850,7 +858,7 @@ impl<'a> WindowContext<'a> {
     /// 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<Pixels>, level: &StackingOrder) -> bool {
-        for (stack, bounds) in self.window.previous_frame.depth_map.iter() {
+        for (stack, bounds) in self.window.rendered_frame.depth_map.iter() {
             if bounds.contains_point(point) {
                 return level.starts_with(stack) || stack.starts_with(level);
             }
@@ -861,10 +869,10 @@ impl<'a> WindowContext<'a> {
 
     /// Called during painting to get the current stacking order.
     pub fn stacking_order(&self) -> &StackingOrder {
-        &self.window.current_frame.z_index_stack
+        &self.window.next_frame.z_index_stack
     }
 
-    /// Paint one or more drop shadows into the scene for the current frame at the current z-index.
+    /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
     pub fn paint_shadows(
         &mut self,
         bounds: Bounds<Pixels>,
@@ -878,8 +886,8 @@ impl<'a> WindowContext<'a> {
             let mut shadow_bounds = bounds;
             shadow_bounds.origin += shadow.offset;
             shadow_bounds.dilate(shadow.spread_radius);
-            window.current_frame.scene_builder.insert(
-                &window.current_frame.z_index_stack,
+            window.next_frame.scene_builder.insert(
+                &window.next_frame.z_index_stack,
                 Shadow {
                     order: 0,
                     bounds: shadow_bounds.scale(scale_factor),
@@ -892,7 +900,7 @@ impl<'a> WindowContext<'a> {
         }
     }
 
-    /// Paint one or more quads into the scene for the current frame at the current stacking context.
+    /// Paint one or more quads into the scene for the next frame at the current stacking context.
     /// Quads are colored rectangular regions with an optional background, border, and corner radius.
     pub fn paint_quad(
         &mut self,
@@ -906,8 +914,8 @@ impl<'a> WindowContext<'a> {
         let content_mask = self.content_mask();
 
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
+        window.next_frame.scene_builder.insert(
+            &window.next_frame.z_index_stack,
             Quad {
                 order: 0,
                 bounds: bounds.scale(scale_factor),
@@ -920,20 +928,20 @@ impl<'a> WindowContext<'a> {
         );
     }
 
-    /// Paint the given `Path` into the scene for the current frame at the current z-index.
+    /// Paint the given `Path` into the scene for the next frame at the current z-index.
     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();
         path.content_mask = content_mask;
         path.color = color.into();
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
-            path.scale(scale_factor),
-        );
+        window
+            .next_frame
+            .scene_builder
+            .insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
     }
 
-    /// Paint an underline into the scene for the current frame at the current z-index.
+    /// Paint an underline into the scene for the next frame at the current z-index.
     pub fn paint_underline(
         &mut self,
         origin: Point<Pixels>,
@@ -952,8 +960,8 @@ impl<'a> WindowContext<'a> {
         };
         let content_mask = self.content_mask();
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
+        window.next_frame.scene_builder.insert(
+            &window.next_frame.z_index_stack,
             Underline {
                 order: 0,
                 bounds: bounds.scale(scale_factor),
@@ -965,7 +973,7 @@ impl<'a> WindowContext<'a> {
         );
     }
 
-    /// Paint a monochrome (non-emoji) glyph into the scene for the current frame at the current z-index.
+    /// Paint a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
     /// The y component of the origin is the baseline of the glyph.
     pub fn paint_glyph(
         &mut self,
@@ -1005,8 +1013,8 @@ impl<'a> WindowContext<'a> {
             };
             let content_mask = self.content_mask().scale(scale_factor);
             let window = &mut *self.window;
-            window.current_frame.scene_builder.insert(
-                &window.current_frame.z_index_stack,
+            window.next_frame.scene_builder.insert(
+                &window.next_frame.z_index_stack,
                 MonochromeSprite {
                     order: 0,
                     bounds,
@@ -1019,7 +1027,7 @@ impl<'a> WindowContext<'a> {
         Ok(())
     }
 
-    /// Paint an emoji glyph into the scene for the current frame at the current z-index.
+    /// Paint an emoji glyph into the scene for the next frame at the current z-index.
     /// The y component of the origin is the baseline of the glyph.
     pub fn paint_emoji(
         &mut self,
@@ -1056,8 +1064,8 @@ impl<'a> WindowContext<'a> {
             let content_mask = self.content_mask().scale(scale_factor);
             let window = &mut *self.window;
 
-            window.current_frame.scene_builder.insert(
-                &window.current_frame.z_index_stack,
+            window.next_frame.scene_builder.insert(
+                &window.next_frame.z_index_stack,
                 PolychromeSprite {
                     order: 0,
                     bounds,
@@ -1071,7 +1079,7 @@ impl<'a> WindowContext<'a> {
         Ok(())
     }
 
-    /// Paint a monochrome SVG into the scene for the current frame at the current stacking context.
+    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
     pub fn paint_svg(
         &mut self,
         bounds: Bounds<Pixels>,
@@ -1098,8 +1106,8 @@ impl<'a> WindowContext<'a> {
         let content_mask = self.content_mask().scale(scale_factor);
 
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
+        window.next_frame.scene_builder.insert(
+            &window.next_frame.z_index_stack,
             MonochromeSprite {
                 order: 0,
                 bounds,
@@ -1112,7 +1120,7 @@ impl<'a> WindowContext<'a> {
         Ok(())
     }
 
-    /// Paint an image into the scene for the current frame at the current z-index.
+    /// Paint an image into the scene for the next frame at the current z-index.
     pub fn paint_image(
         &mut self,
         bounds: Bounds<Pixels>,
@@ -1134,8 +1142,8 @@ impl<'a> WindowContext<'a> {
         let corner_radii = corner_radii.scale(scale_factor);
 
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
+        window.next_frame.scene_builder.insert(
+            &window.next_frame.z_index_stack,
             PolychromeSprite {
                 order: 0,
                 bounds,
@@ -1148,14 +1156,14 @@ impl<'a> WindowContext<'a> {
         Ok(())
     }
 
-    /// Paint a surface into the scene for the current frame at the current z-index.
+    /// Paint a surface into the scene for the next frame at the current z-index.
     pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
         let scale_factor = self.scale_factor();
         let bounds = bounds.scale(scale_factor);
         let content_mask = self.content_mask().scale(scale_factor);
         let window = &mut *self.window;
-        window.current_frame.scene_builder.insert(
-            &window.current_frame.z_index_stack,
+        window.next_frame.scene_builder.insert(
+            &window.next_frame.z_index_stack,
             Surface {
                 order: 0,
                 bounds,
@@ -1167,15 +1175,17 @@ impl<'a> WindowContext<'a> {
 
     /// Draw pixels to the display for this window based on the contents of its scene.
     pub(crate) fn draw(&mut self) {
+        self.text_system().start_frame();
+        self.window.platform_window.clear_input_handler();
+        self.window.layout_engine.as_mut().unwrap().clear();
+        self.window.next_frame.clear();
         let root_view = self.window.root_view.take().unwrap();
 
-        self.start_frame();
-
         self.with_z_index(0, |cx| {
             cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| {
                 for (action_type, action_listeners) in &cx.app.global_action_listeners {
                     for action_listener in action_listeners.iter().cloned() {
-                        cx.window.current_frame.dispatch_tree.on_action(
+                        cx.window.next_frame.dispatch_tree.on_action(
                             *action_type,
                             Rc::new(move |action, phase, cx| action_listener(action, phase, cx)),
                         )
@@ -1204,16 +1214,18 @@ impl<'a> WindowContext<'a> {
         }
 
         self.window
-            .current_frame
+            .next_frame
             .dispatch_tree
             .preserve_pending_keystrokes(
-                &mut self.window.previous_frame.dispatch_tree,
+                &mut self.window.rendered_frame.dispatch_tree,
                 self.window.focus,
             );
-
         self.window.root_view = Some(root_view);
-        let scene = self.window.current_frame.scene_builder.build();
 
+        let window = &mut self.window;
+        mem::swap(&mut window.rendered_frame, &mut window.next_frame);
+
+        let scene = self.window.rendered_frame.scene_builder.build();
         self.window.platform_window.draw(scene);
         let cursor_style = self
             .window
@@ -1225,24 +1237,6 @@ impl<'a> WindowContext<'a> {
         self.window.dirty = false;
     }
 
-    /// Rotate the current frame and the previous frame, then clear the current frame.
-    /// We repopulate all state in the current frame during each paint.
-    fn start_frame(&mut self) {
-        self.window.platform_window.clear_input_handler();
-        self.text_system().start_frame();
-
-        let window = &mut *self.window;
-        window.layout_engine.as_mut().unwrap().clear();
-
-        mem::swap(&mut window.previous_frame, &mut window.current_frame);
-        let frame = &mut window.current_frame;
-        frame.element_states.clear();
-        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.
     pub fn dispatch_event(&mut self, event: InputEvent) -> bool {
         // Handlers may set this to false by calling `stop_propagation`
@@ -1321,7 +1315,7 @@ impl<'a> WindowContext<'a> {
     fn dispatch_mouse_event(&mut self, event: &dyn Any) {
         if let Some(mut handlers) = self
             .window
-            .current_frame
+            .rendered_frame
             .mouse_listeners
             .remove(&event.type_id())
         {
@@ -1351,17 +1345,8 @@ impl<'a> WindowContext<'a> {
                 self.active_drag = None;
             }
 
-            // Just in case any handlers added new handlers, which is weird, but possible.
-            handlers.extend(
-                self.window
-                    .current_frame
-                    .mouse_listeners
-                    .get_mut(&event.type_id())
-                    .into_iter()
-                    .flat_map(|handlers| handlers.drain(..)),
-            );
             self.window
-                .current_frame
+                .rendered_frame
                 .mouse_listeners
                 .insert(event.type_id(), handlers);
         }
@@ -1373,15 +1358,15 @@ impl<'a> WindowContext<'a> {
             .focus
             .and_then(|focus_id| {
                 self.window
-                    .current_frame
+                    .rendered_frame
                     .dispatch_tree
                     .focusable_node_id(focus_id)
             })
-            .unwrap_or_else(|| self.window.current_frame.dispatch_tree.root_node_id());
+            .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
 
         let dispatch_path = self
             .window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .dispatch_path(node_id);
 
@@ -1392,7 +1377,7 @@ impl<'a> WindowContext<'a> {
         self.propagate_event = true;
 
         for node_id in &dispatch_path {
-            let node = self.window.current_frame.dispatch_tree.node(*node_id);
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
 
             if let Some(context) = node.context.clone() {
                 context_stack.push(context);
@@ -1409,7 +1394,7 @@ impl<'a> WindowContext<'a> {
         // Bubble phase
         for node_id in dispatch_path.iter().rev() {
             // Handle low level key events
-            let node = self.window.current_frame.dispatch_tree.node(*node_id);
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
             for key_listener in node.key_listeners.clone() {
                 key_listener(event, DispatchPhase::Bubble, self);
                 if !self.propagate_event {
@@ -1418,12 +1403,12 @@ impl<'a> WindowContext<'a> {
             }
 
             // Match keystrokes
-            let node = self.window.current_frame.dispatch_tree.node(*node_id);
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
             if node.context.is_some() {
                 if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
                     if let Some(found) = self
                         .window
-                        .current_frame
+                        .rendered_frame
                         .dispatch_tree
                         .dispatch_key(&key_down_event.keystroke, &context_stack)
                     {
@@ -1446,13 +1431,13 @@ impl<'a> WindowContext<'a> {
     fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box<dyn Action>) {
         let dispatch_path = self
             .window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .dispatch_path(node_id);
 
         // Capture phase
         for node_id in &dispatch_path {
-            let node = self.window.current_frame.dispatch_tree.node(*node_id);
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
             for DispatchActionListener {
                 action_type,
                 listener,
@@ -1469,7 +1454,7 @@ impl<'a> WindowContext<'a> {
         }
         // Bubble phase
         for node_id in dispatch_path.iter().rev() {
-            let node = self.window.current_frame.dispatch_tree.node(*node_id);
+            let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
             for DispatchActionListener {
                 action_type,
                 listener,
@@ -1529,25 +1514,25 @@ impl<'a> WindowContext<'a> {
             .focus
             .and_then(|focus_id| {
                 self.window
-                    .current_frame
+                    .rendered_frame
                     .dispatch_tree
                     .focusable_node_id(focus_id)
             })
-            .unwrap_or_else(|| self.window.current_frame.dispatch_tree.root_node_id());
+            .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
 
         self.window
-            .current_frame
+            .rendered_frame
             .dispatch_tree
             .available_actions(node_id)
     }
 
     pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
         self.window
-            .previous_frame
+            .rendered_frame
             .dispatch_tree
             .bindings_for_action(
                 action,
-                &self.window.previous_frame.dispatch_tree.context_stack,
+                &self.window.rendered_frame.dispatch_tree.context_stack,
             )
     }
 
@@ -1556,7 +1541,7 @@ impl<'a> WindowContext<'a> {
         action: &dyn Action,
         focus_handle: &FocusHandle,
     ) -> Vec<KeyBinding> {
-        let dispatch_tree = &self.window.previous_frame.dispatch_tree;
+        let dispatch_tree = &self.window.rendered_frame.dispatch_tree;
 
         let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {
             return vec![];
@@ -1599,24 +1584,21 @@ impl<'a> WindowContext<'a> {
         f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
     ) -> R {
         let window = &mut self.window;
-        window
-            .current_frame
-            .dispatch_tree
-            .push_node(context.clone());
+        window.next_frame.dispatch_tree.push_node(context.clone());
         if let Some(focus_handle) = focus_handle.as_ref() {
             window
-                .current_frame
+                .next_frame
                 .dispatch_tree
                 .make_focusable(focus_handle.id);
         }
         let result = f(focus_handle, self);
 
-        self.window.current_frame.dispatch_tree.pop_node();
+        self.window.next_frame.dispatch_tree.pop_node();
 
         result
     }
 
-    /// Register a focus listener for the current frame only. It will be cleared
+    /// Register a focus listener for the next frame only. It will be cleared
     /// on the next frame render. You should use this method only from within elements,
     /// and we may want to enforce that better via a different context type.
     // todo!() Move this to `FrameContext` to emphasize its individuality?
@@ -1625,7 +1607,7 @@ impl<'a> WindowContext<'a> {
         listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static,
     ) {
         self.window
-            .current_frame
+            .next_frame
             .focus_listeners
             .push(Box::new(move |event, cx| {
                 listener(event, cx);
@@ -1876,12 +1858,9 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
     ) -> R {
         if let Some(mask) = mask {
             let mask = mask.intersect(&self.content_mask());
-            self.window_mut()
-                .current_frame
-                .content_mask_stack
-                .push(mask);
+            self.window_mut().next_frame.content_mask_stack.push(mask);
             let result = f(self);
-            self.window_mut().current_frame.content_mask_stack.pop();
+            self.window_mut().next_frame.content_mask_stack.pop();
             result
         } else {
             f(self)
@@ -1897,12 +1876,9 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
                 size: self.window().viewport_size,
             },
         };
-        self.window_mut()
-            .current_frame
-            .content_mask_stack
-            .push(mask);
+        self.window_mut().next_frame.content_mask_stack.push(mask);
         let result = f(self);
-        self.window_mut().current_frame.content_mask_stack.pop();
+        self.window_mut().next_frame.content_mask_stack.pop();
         result
     }
 
@@ -1929,26 +1905,26 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
         f: impl FnOnce(&mut Self) -> R,
     ) -> R {
         self.window_mut()
-            .current_frame
+            .next_frame
             .element_offset_stack
             .push(offset);
         let result = f(self);
-        self.window_mut().current_frame.element_offset_stack.pop();
+        self.window_mut().next_frame.element_offset_stack.pop();
         result
     }
 
     /// Obtain the current element offset.
     fn element_offset(&self) -> Point<Pixels> {
         self.window()
-            .current_frame
+            .next_frame
             .element_offset_stack
             .last()
             .copied()
             .unwrap_or_default()
     }
 
-    /// Update or intialize state for an element with the given id that lives across multiple
-    /// frames. If an element with this id existed in the previous frame, its state will be passed
+    /// Update or initialize state for an element with the given id that lives across multiple
+    /// frames. If an element with this id existed in the rendered frame, its state will be passed
     /// to the given closure. The state returned by the closure will be stored so it can be referenced
     /// when drawing the next frame.
     fn with_element_state<S, R>(
@@ -1964,12 +1940,12 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
 
             if let Some(any) = cx
                 .window_mut()
-                .current_frame
+                .next_frame
                 .element_states
                 .remove(&global_id)
                 .or_else(|| {
                     cx.window_mut()
-                        .previous_frame
+                        .rendered_frame
                         .element_states
                         .remove(&global_id)
                 })
@@ -2011,7 +1987,7 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
                 let (result, state) = f(Some(state), cx);
                 state_box.replace(state);
                 cx.window_mut()
-                    .current_frame
+                    .next_frame
                     .element_states
                     .insert(global_id, ElementStateBox {
                         inner: state_box,
@@ -2023,7 +1999,7 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
             } else {
                 let (result, state) = f(None, cx);
                 cx.window_mut()
-                    .current_frame
+                    .next_frame
                     .element_states
                     .insert(global_id,
                         ElementStateBox {
@@ -2042,7 +2018,7 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
     /// Obtain the current content mask.
     fn content_mask(&self) -> ContentMask<Pixels> {
         self.window()
-            .current_frame
+            .next_frame
             .content_mask_stack
             .last()
             .cloned()
@@ -2130,9 +2106,9 @@ impl<'a, V: 'static> ViewContext<'a, V> {
     }
 
     pub fn with_z_index<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
-        self.window.current_frame.z_index_stack.push(z_index);
+        self.window.next_frame.z_index_stack.push(z_index);
         let result = f(self);
-        self.window.current_frame.z_index_stack.pop();
+        self.window.next_frame.z_index_stack.pop();
         result
     }