diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index f737c6e30b205d867133bd86561fbcd0dc10a3e6..962a0308445b48afc85dbc4492d19574917a2e9c 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -60,7 +60,7 @@ impl DispatchTree { self.keystroke_matchers.clear(); } - pub fn push_node(&mut self, context: KeyContext, old_dispatcher: &mut Self) { + pub fn push_node(&mut self, context: KeyContext) { let parent = self.node_stack.last().copied(); let node_id = DispatchNodeId(self.nodes.len()); self.nodes.push(DispatchNode { @@ -71,12 +71,6 @@ impl DispatchTree { if !context.is_empty() { self.active_node().context = context.clone(); self.context_stack.push(context); - if let Some((context_stack, matcher)) = old_dispatcher - .keystroke_matchers - .remove_entry(self.context_stack.as_slice()) - { - self.keystroke_matchers.insert(context_stack, matcher); - } } } @@ -87,6 +81,33 @@ impl DispatchTree { } } + pub fn clear_keystroke_matchers(&mut self) { + self.keystroke_matchers.clear(); + } + + /// Preserve keystroke matchers from previous frames to support multi-stroke + /// bindings across multiple frames. + pub fn preserve_keystroke_matchers(&mut self, old_tree: &mut Self, focus_id: Option) { + if let Some(node_id) = focus_id.and_then(|focus_id| self.focusable_node_id(focus_id)) { + let dispatch_path = self.dispatch_path(node_id); + + self.context_stack.clear(); + for node_id in dispatch_path { + let node = self.node(node_id); + if !node.context.is_empty() { + self.context_stack.push(node.context.clone()); + } + + if let Some((context_stack, matcher)) = old_tree + .keystroke_matchers + .remove_entry(self.context_stack.as_slice()) + { + self.keystroke_matchers.insert(context_stack, matcher); + } + } + } + } + pub fn on_key_event(&mut self, listener: KeyListener) { self.active_node().key_listeners.push(listener); } diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 5a2cc0f103630e2ff5c1a7c236e557c1598572b9..3edaa900b0435233f669ff553e01c1cdb9cb1adc 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -1,7 +1,7 @@ use crate::{ private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, - BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, - Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext, + Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, Model, Pixels, + Size, ViewContext, VisualContext, WeakModel, WindowContext, }; use anyhow::{Context, Result}; use std::{ @@ -325,12 +325,10 @@ where _: Option, cx: &mut ViewContext, ) -> Self::ElementState { - cx.with_element_id(Some(self.view.entity_id()), |cx| { - self.view.update(cx, |view, cx| { - let mut element = self.component.take().unwrap().render(); - element.initialize(view, cx); - element - }) + self.view.update(cx, |view, cx| { + let mut element = self.component.take().unwrap().render(); + element.initialize(view, cx); + element }) } @@ -340,9 +338,7 @@ where element: &mut Self::ElementState, cx: &mut ViewContext, ) -> LayoutId { - cx.with_element_id(Some(self.view.entity_id()), |cx| { - self.view.update(cx, |view, cx| element.layout(view, cx)) - }) + self.view.update(cx, |view, cx| element.layout(view, cx)) } fn paint( @@ -352,9 +348,7 @@ where element: &mut Self::ElementState, cx: &mut ViewContext, ) { - cx.with_element_id(Some(self.view.entity_id()), |cx| { - self.view.update(cx, |view, cx| element.paint(view, cx)) - }) + self.view.update(cx, |view, cx| element.paint(view, cx)) } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index c6361c8c6e4407916e2a9fe33f352d9803e386fd..0563c107c0b150fc8394acab0a4e3c2bbba4b2af 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -393,6 +393,10 @@ impl<'a> WindowContext<'a> { /// Move focus to the element associated with the given `FocusHandle`. pub fn focus(&mut self, handle: &FocusHandle) { + if self.window.focus == Some(handle.id) { + return; + } + let focus_id = handle.id; if self.window.last_blur.is_none() { @@ -400,6 +404,10 @@ impl<'a> WindowContext<'a> { } self.window.focus = Some(focus_id); + self.window + .current_frame + .dispatch_tree + .clear_keystroke_matchers(); self.app.push_effect(Effect::FocusChanged { window_handle: self.window.handle, focused: Some(focus_id), @@ -1091,6 +1099,14 @@ impl<'a> WindowContext<'a> { }); } + self.window + .current_frame + .dispatch_tree + .preserve_keystroke_matchers( + &mut self.window.previous_frame.dispatch_tree, + self.window.focus, + ); + self.window.root_view = Some(root_view); let scene = self.window.current_frame.scene_builder.build(); @@ -2093,7 +2109,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { window .current_frame .dispatch_tree - .push_node(context.clone(), &mut window.previous_frame.dispatch_tree); + .push_node(context.clone()); if let Some(focus_handle) = focus_handle.as_ref() { window .current_frame