Merge pull request #2439 from zed-industries/fix-keystrokes-for-action

Antonio Scandurra created

Cache view's type id and keymap context into a separate map

Change summary

crates/collab_ui/src/contact_list.rs             |   7 
crates/context_menu/src/context_menu.rs          |   7 
crates/editor/src/editor.rs                      |  26 +-
crates/gpui/src/app.rs                           | 176 ++++++++++-------
crates/gpui/src/app/window.rs                    |  30 +-
crates/gpui/src/keymap_matcher/keymap_context.rs |   5 
crates/picker/src/picker.rs                      |   7 
crates/project_panel/src/project_panel.rs        |   7 
crates/terminal_view/src/terminal_view.rs        |  35 +-
crates/vim/src/vim.rs                            |   4 
crates/workspace/src/pane.rs                     |   5 
crates/workspace/src/workspace.rs                |   5 
12 files changed, 170 insertions(+), 144 deletions(-)

Detailed changes

crates/collab_ui/src/contact_list.rs 🔗

@@ -1306,10 +1306,9 @@ impl View for ContactList {
         "ContactList"
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut cx = Self::default_keymap_context();
-        cx.add_identifier("menu");
-        cx
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
+        keymap.add_identifier("menu");
     }
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {

crates/context_menu/src/context_menu.rs 🔗

@@ -140,10 +140,9 @@ impl View for ContextMenu {
         "ContextMenu"
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut cx = Self::default_keymap_context();
-        cx.add_identifier("menu");
-        cx
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
+        keymap.add_identifier("menu");
     }
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {

crates/editor/src/editor.rs 🔗

@@ -1425,13 +1425,19 @@ impl Editor {
         }
     }
 
-    pub fn set_keymap_context_layer<Tag: 'static>(&mut self, context: KeymapContext) {
+    pub fn set_keymap_context_layer<Tag: 'static>(
+        &mut self,
+        context: KeymapContext,
+        cx: &mut ViewContext<Self>,
+    ) {
         self.keymap_context_layers
             .insert(TypeId::of::<Tag>(), context);
+        cx.notify();
     }
 
-    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self) {
+    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
         self.keymap_context_layers.remove(&TypeId::of::<Tag>());
+        cx.notify();
     }
 
     pub fn set_input_enabled(&mut self, input_enabled: bool) {
@@ -7157,28 +7163,26 @@ impl View for Editor {
         false
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut context = Self::default_keymap_context();
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
         let mode = match self.mode {
             EditorMode::SingleLine => "single_line",
             EditorMode::AutoHeight { .. } => "auto_height",
             EditorMode::Full => "full",
         };
-        context.add_key("mode", mode);
+        keymap.add_key("mode", mode);
         if self.pending_rename.is_some() {
-            context.add_identifier("renaming");
+            keymap.add_identifier("renaming");
         }
         match self.context_menu.as_ref() {
-            Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
-            Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
+            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
+            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
             None => {}
         }
 
         for layer in self.keymap_context_layers.values() {
-            context.extend(layer);
+            keymap.extend(layer);
         }
-
-        context
     }
 
     fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {

crates/gpui/src/app.rs 🔗

@@ -83,14 +83,15 @@ pub trait View: Entity + Sized {
         false
     }
 
-    fn keymap_context(&self, _: &AppContext) -> keymap_matcher::KeymapContext {
-        Self::default_keymap_context()
+    fn update_keymap_context(&self, keymap: &mut keymap_matcher::KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
     }
-    fn default_keymap_context() -> keymap_matcher::KeymapContext {
-        let mut cx = keymap_matcher::KeymapContext::default();
-        cx.add_identifier(Self::ui_name());
-        cx
+
+    fn reset_to_default_keymap_context(keymap: &mut keymap_matcher::KeymapContext) {
+        keymap.clear();
+        keymap.add_identifier(Self::ui_name());
     }
+
     fn debug_json(&self, _: &AppContext) -> serde_json::Value {
         serde_json::Value::Null
     }
@@ -440,6 +441,7 @@ type WindowShouldCloseSubscriptionCallback = Box<dyn FnMut(&mut AppContext) -> b
 pub struct AppContext {
     models: HashMap<usize, Box<dyn AnyModel>>,
     views: HashMap<(usize, usize), Box<dyn AnyView>>,
+    views_metadata: HashMap<(usize, usize), ViewMetadata>,
     pub(crate) parents: HashMap<(usize, usize), ParentId>,
     windows: HashMap<usize, Window>,
     globals: HashMap<TypeId, Box<dyn Any>>,
@@ -502,6 +504,7 @@ impl AppContext {
         Self {
             models: Default::default(),
             views: Default::default(),
+            views_metadata: Default::default(),
             parents: Default::default(),
             windows: Default::default(),
             globals: Default::default(),
@@ -727,9 +730,9 @@ impl AppContext {
     }
 
     pub fn view_type_id(&self, window_id: usize, view_id: usize) -> Option<TypeId> {
-        self.views
+        self.views_metadata
             .get(&(window_id, view_id))
-            .map(|view| view.as_any().type_id())
+            .map(|metadata| metadata.type_id)
     }
 
     pub fn active_labeled_tasks<'a>(
@@ -1045,9 +1048,10 @@ impl AppContext {
                 .read_window(window_id, |cx| {
                     if let Some(focused_view_id) = cx.focused_view_id() {
                         for view_id in cx.ancestors(focused_view_id) {
-                            if let Some(view) = cx.views.get(&(window_id, view_id)) {
-                                let view_type = view.as_any().type_id();
-                                if let Some(actions) = cx.actions.get(&view_type) {
+                            if let Some(view_metadata) =
+                                cx.views_metadata.get(&(window_id, view_id))
+                            {
+                                if let Some(actions) = cx.actions.get(&view_metadata.type_id) {
                                     if actions.contains_key(&action_type) {
                                         return true;
                                     }
@@ -1448,6 +1452,7 @@ impl AppContext {
             for (window_id, view_id) in dropped_views {
                 self.subscriptions.remove(view_id);
                 self.observations.remove(view_id);
+                self.views_metadata.remove(&(window_id, view_id));
                 let mut view = self.views.remove(&(window_id, view_id)).unwrap();
                 view.release(self);
                 let change_focus_to = self.windows.get_mut(&window_id).and_then(|window| {
@@ -1779,9 +1784,11 @@ impl AppContext {
         observed_window_id: usize,
         observed_view_id: usize,
     ) {
-        if self
+        let view_key = (observed_window_id, observed_view_id);
+        if let Some((view, mut view_metadata)) = self
             .views
-            .contains_key(&(observed_window_id, observed_view_id))
+            .remove(&view_key)
+            .zip(self.views_metadata.remove(&view_key))
         {
             if let Some(window) = self.windows.get_mut(&observed_window_id) {
                 window
@@ -1791,6 +1798,10 @@ impl AppContext {
                     .insert(observed_view_id);
             }
 
+            view.update_keymap_context(&mut view_metadata.keymap_context, self);
+            self.views.insert(view_key, view);
+            self.views_metadata.insert(view_key, view_metadata);
+
             let mut observations = self.observations.clone();
             observations.emit(observed_view_id, |callback| callback(self));
         }
@@ -2037,6 +2048,11 @@ pub enum ParentId {
     Root,
 }
 
+struct ViewMetadata {
+    type_id: TypeId,
+    keymap_context: KeymapContext,
+}
+
 #[derive(Default, Clone)]
 pub struct WindowInvalidation {
     pub updated: HashSet<usize>,
@@ -2365,7 +2381,7 @@ pub trait AnyView {
         cx: &mut WindowContext,
         view_id: usize,
     ) -> bool;
-    fn keymap_context(&self, cx: &AppContext) -> KeymapContext;
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext);
     fn debug_json(&self, cx: &WindowContext) -> serde_json::Value;
 
     fn text_for_range(&self, range: Range<usize>, cx: &WindowContext) -> Option<String>;
@@ -2437,11 +2453,10 @@ where
             cx.handle().into_any()
         } else {
             let focused_type = cx
-                .views
+                .views_metadata
                 .get(&(cx.window_id, focused_id))
                 .unwrap()
-                .as_any()
-                .type_id();
+                .type_id;
             AnyViewHandle::new(
                 cx.window_id,
                 focused_id,
@@ -2458,11 +2473,10 @@ where
             cx.handle().into_any()
         } else {
             let blurred_type = cx
-                .views
+                .views_metadata
                 .get(&(cx.window_id, blurred_id))
                 .unwrap()
-                .as_any()
-                .type_id();
+                .type_id;
             AnyViewHandle::new(
                 cx.window_id,
                 blurred_id,
@@ -2493,8 +2507,8 @@ where
         View::modifiers_changed(self, event, &mut cx)
     }
 
-    fn keymap_context(&self, cx: &AppContext) -> KeymapContext {
-        View::keymap_context(self, cx)
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
+        View::update_keymap_context(self, keymap, cx)
     }
 
     fn debug_json(&self, cx: &WindowContext) -> serde_json::Value {
@@ -5559,8 +5573,8 @@ mod tests {
                 "View"
             }
 
-            fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-                self.keymap_context.clone()
+            fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+                *keymap = self.keymap_context.clone();
             }
         }
 
@@ -5664,7 +5678,7 @@ mod tests {
     }
 
     #[crate::test(self)]
-    fn test_keystrokes_for_action(cx: &mut AppContext) {
+    fn test_keystrokes_for_action(cx: &mut TestAppContext) {
         actions!(test, [Action1, Action2, GlobalAction]);
 
         struct View1 {}
@@ -5694,70 +5708,76 @@ mod tests {
             }
         }
 
-        let (window_id, view_1) = cx.add_window(Default::default(), |_| View1 {});
+        let (_, view_1) = cx.add_window(|_| View1 {});
         let view_2 = cx.add_view(&view_1, |cx| {
             cx.focus_self();
             View2 {}
         });
 
-        cx.add_action(|_: &mut View1, _: &Action1, _cx| {});
-        cx.add_action(|_: &mut View2, _: &Action2, _cx| {});
-        cx.add_global_action(|_: &GlobalAction, _| {});
-
-        cx.add_bindings(vec![
-            Binding::new("a", Action1, Some("View1")),
-            Binding::new("b", Action2, Some("View1 > View2")),
-            Binding::new("c", GlobalAction, Some("View3")), // View 3 does not exist
-        ]);
+        cx.update(|cx| {
+            cx.add_action(|_: &mut View1, _: &Action1, _cx| {});
+            cx.add_action(|_: &mut View2, _: &Action2, _cx| {});
+            cx.add_global_action(|_: &GlobalAction, _| {});
+
+            cx.add_bindings(vec![
+                Binding::new("a", Action1, Some("View1")),
+                Binding::new("b", Action2, Some("View1 > View2")),
+                Binding::new("c", GlobalAction, Some("View3")), // View 3 does not exist
+            ]);
+        });
 
-        cx.update_window(window_id, |cx| {
-            // Sanity check
-            assert_eq!(
-                cx.keystrokes_for_action(view_1.id(), &Action1)
-                    .unwrap()
-                    .as_slice(),
-                &[Keystroke::parse("a").unwrap()]
-            );
-            assert_eq!(
-                cx.keystrokes_for_action(view_2.id(), &Action2)
-                    .unwrap()
-                    .as_slice(),
-                &[Keystroke::parse("b").unwrap()]
-            );
+        // Here we update the views to ensure that, even if they are on the stack,
+        // we can still retrieve keystrokes correctly.
+        view_1.update(cx, |_, cx| {
+            view_2.update(cx, |_, cx| {
+                // Sanity check
+                assert_eq!(
+                    cx.keystrokes_for_action(view_1.id(), &Action1)
+                        .unwrap()
+                        .as_slice(),
+                    &[Keystroke::parse("a").unwrap()]
+                );
+                assert_eq!(
+                    cx.keystrokes_for_action(view_2.id(), &Action2)
+                        .unwrap()
+                        .as_slice(),
+                    &[Keystroke::parse("b").unwrap()]
+                );
 
-            // The 'a' keystroke propagates up the view tree from view_2
-            // to view_1. The action, Action1, is handled by view_1.
-            assert_eq!(
-                cx.keystrokes_for_action(view_2.id(), &Action1)
-                    .unwrap()
-                    .as_slice(),
-                &[Keystroke::parse("a").unwrap()]
-            );
+                // The 'a' keystroke propagates up the view tree from view_2
+                // to view_1. The action, Action1, is handled by view_1.
+                assert_eq!(
+                    cx.keystrokes_for_action(view_2.id(), &Action1)
+                        .unwrap()
+                        .as_slice(),
+                    &[Keystroke::parse("a").unwrap()]
+                );
 
-            // Actions that are handled below the current view don't have bindings
-            assert_eq!(cx.keystrokes_for_action(view_1.id(), &Action2), None);
+                // Actions that are handled below the current view don't have bindings
+                assert_eq!(cx.keystrokes_for_action(view_1.id(), &Action2), None);
 
-            // Actions that are handled in other branches of the tree should not have a binding
-            assert_eq!(cx.keystrokes_for_action(view_2.id(), &GlobalAction), None);
+                // Actions that are handled in other branches of the tree should not have a binding
+                assert_eq!(cx.keystrokes_for_action(view_2.id(), &GlobalAction), None);
 
-            // Check that global actions do not have a binding, even if a binding does exist in another view
-            assert_eq!(
-                &available_actions(view_1.id(), cx),
-                &[
-                    ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
-                    ("test::GlobalAction", vec![])
-                ],
-            );
+                // Check that global actions do not have a binding, even if a binding does exist in another view
+                assert_eq!(
+                    &available_actions(view_1.id(), cx),
+                    &[
+                        ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
+                        ("test::GlobalAction", vec![])
+                    ],
+                );
 
-            // Check that view 1 actions and bindings are available even when called from view 2
-            assert_eq!(
-                &available_actions(view_2.id(), cx),
-                &[
-                    ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
-                    ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
-                    ("test::GlobalAction", vec![]),
-                ],
-            );
+                // Check that view 1 actions and bindings are available even when called from view 2
+                assert_eq!(
+                    &available_actions(view_2.id(), cx),
+                    &[
+                        ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
+                        ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
+                        ("test::GlobalAction", vec![]),
+                    ],
+                );
+            });
         });
 
         // Produces a list of actions and key bindings

crates/gpui/src/app/window.rs 🔗

@@ -2,7 +2,7 @@ use crate::{
     elements::AnyRootElement,
     geometry::rect::RectF,
     json::ToJson,
-    keymap_matcher::{Binding, Keystroke, MatchResult},
+    keymap_matcher::{Binding, KeymapContext, Keystroke, MatchResult},
     platform::{
         self, Appearance, CursorStyle, Event, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent,
         MouseButton, MouseMovedEvent, PromptLevel, WindowBounds,
@@ -34,7 +34,7 @@ use std::{
 use util::ResultExt;
 use uuid::Uuid;
 
-use super::Reference;
+use super::{Reference, ViewMetadata};
 
 pub struct Window {
     pub(crate) root_view: Option<AnyViewHandle>,
@@ -369,13 +369,13 @@ impl<'a> WindowContext<'a> {
         let mut contexts = Vec::new();
         let mut handler_depth = None;
         for (i, view_id) in self.ancestors(view_id).enumerate() {
-            if let Some(view) = self.views.get(&(window_id, view_id)) {
-                if let Some(actions) = self.actions.get(&view.as_any().type_id()) {
+            if let Some(view_metadata) = self.views_metadata.get(&(window_id, view_id)) {
+                if let Some(actions) = self.actions.get(&view_metadata.type_id) {
                     if actions.contains_key(&action.as_any().type_id()) {
                         handler_depth = Some(i);
                     }
                 }
-                contexts.push(view.keymap_context(self));
+                contexts.push(view_metadata.keymap_context.clone());
             }
         }
 
@@ -406,10 +406,9 @@ impl<'a> WindowContext<'a> {
         let mut contexts = Vec::new();
         let mut handler_depths_by_action_type = HashMap::<TypeId, usize>::default();
         for (depth, view_id) in self.ancestors(view_id).enumerate() {
-            if let Some(view) = self.views.get(&(window_id, view_id)) {
-                contexts.push(view.keymap_context(self));
-                let view_type = view.as_any().type_id();
-                if let Some(actions) = self.actions.get(&view_type) {
+            if let Some(view_metadata) = self.views_metadata.get(&(window_id, view_id)) {
+                contexts.push(view_metadata.keymap_context.clone());
+                if let Some(actions) = self.actions.get(&view_metadata.type_id) {
                     handler_depths_by_action_type.extend(
                         actions
                             .keys()
@@ -458,9 +457,9 @@ impl<'a> WindowContext<'a> {
             let dispatch_path = self
                 .ancestors(focused_view_id)
                 .filter_map(|view_id| {
-                    self.views
+                    self.views_metadata
                         .get(&(window_id, view_id))
-                        .map(|view| (view_id, view.keymap_context(self)))
+                        .map(|view| (view_id, view.keymap_context.clone()))
                 })
                 .collect();
 
@@ -1177,6 +1176,15 @@ impl<'a> WindowContext<'a> {
         self.parents.insert((window_id, view_id), parent_id);
         let mut cx = ViewContext::mutable(self, view_id);
         let handle = if let Some(view) = build_view(&mut cx) {
+            let mut keymap_context = KeymapContext::default();
+            view.update_keymap_context(&mut keymap_context, cx.app_context());
+            self.views_metadata.insert(
+                (window_id, view_id),
+                ViewMetadata {
+                    type_id: TypeId::of::<T>(),
+                    keymap_context,
+                },
+            );
             self.views.insert((window_id, view_id), Box::new(view));
             self.window
                 .invalidation

crates/gpui/src/keymap_matcher/keymap_context.rs 🔗

@@ -17,6 +17,11 @@ impl KeymapContext {
         }
     }
 
+    pub fn clear(&mut self) {
+        self.set.clear();
+        self.map.clear();
+    }
+
     pub fn extend(&mut self, other: &Self) {
         for v in &other.set {
             self.set.insert(v.clone());

crates/picker/src/picker.rs 🔗

@@ -126,10 +126,9 @@ impl<D: PickerDelegate> View for Picker<D> {
             .into_any_named("picker")
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut cx = Self::default_keymap_context();
-        cx.add_identifier("menu");
-        cx
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
+        keymap.add_identifier("menu");
     }
 
     fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {

crates/project_panel/src/project_panel.rs 🔗

@@ -1316,10 +1316,9 @@ impl View for ProjectPanel {
         }
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut cx = Self::default_keymap_context();
-        cx.add_identifier("menu");
-        cx
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
+        keymap.add_identifier("menu");
     }
 }
 

crates/terminal_view/src/terminal_view.rs 🔗

@@ -446,11 +446,11 @@ impl View for TerminalView {
         });
     }
 
-    fn keymap_context(&self, cx: &gpui::AppContext) -> KeymapContext {
-        let mut context = Self::default_keymap_context();
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &gpui::AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
 
         let mode = self.terminal.read(cx).last_content.mode;
-        context.add_key(
+        keymap.add_key(
             "screen",
             if mode.contains(TermMode::ALT_SCREEN) {
                 "alt"
@@ -460,40 +460,40 @@ impl View for TerminalView {
         );
 
         if mode.contains(TermMode::APP_CURSOR) {
-            context.add_identifier("DECCKM");
+            keymap.add_identifier("DECCKM");
         }
         if mode.contains(TermMode::APP_KEYPAD) {
-            context.add_identifier("DECPAM");
+            keymap.add_identifier("DECPAM");
         } else {
-            context.add_identifier("DECPNM");
+            keymap.add_identifier("DECPNM");
         }
         if mode.contains(TermMode::SHOW_CURSOR) {
-            context.add_identifier("DECTCEM");
+            keymap.add_identifier("DECTCEM");
         }
         if mode.contains(TermMode::LINE_WRAP) {
-            context.add_identifier("DECAWM");
+            keymap.add_identifier("DECAWM");
         }
         if mode.contains(TermMode::ORIGIN) {
-            context.add_identifier("DECOM");
+            keymap.add_identifier("DECOM");
         }
         if mode.contains(TermMode::INSERT) {
-            context.add_identifier("IRM");
+            keymap.add_identifier("IRM");
         }
         //LNM is apparently the name for this. https://vt100.net/docs/vt510-rm/LNM.html
         if mode.contains(TermMode::LINE_FEED_NEW_LINE) {
-            context.add_identifier("LNM");
+            keymap.add_identifier("LNM");
         }
         if mode.contains(TermMode::FOCUS_IN_OUT) {
-            context.add_identifier("report_focus");
+            keymap.add_identifier("report_focus");
         }
         if mode.contains(TermMode::ALTERNATE_SCROLL) {
-            context.add_identifier("alternate_scroll");
+            keymap.add_identifier("alternate_scroll");
         }
         if mode.contains(TermMode::BRACKETED_PASTE) {
-            context.add_identifier("bracketed_paste");
+            keymap.add_identifier("bracketed_paste");
         }
         if mode.intersects(TermMode::MOUSE_MODE) {
-            context.add_identifier("any_mouse_reporting");
+            keymap.add_identifier("any_mouse_reporting");
         }
         {
             let mouse_reporting = if mode.contains(TermMode::MOUSE_REPORT_CLICK) {
@@ -505,7 +505,7 @@ impl View for TerminalView {
             } else {
                 "off"
             };
-            context.add_key("mouse_reporting", mouse_reporting);
+            keymap.add_key("mouse_reporting", mouse_reporting);
         }
         {
             let format = if mode.contains(TermMode::SGR_MOUSE) {
@@ -515,9 +515,8 @@ impl View for TerminalView {
             } else {
                 "normal"
             };
-            context.add_key("mouse_format", format);
+            keymap.add_key("mouse_format", format);
         }
-        context
     }
 }
 

crates/vim/src/vim.rs 🔗

@@ -309,7 +309,7 @@ impl Vim {
                 editor.set_input_enabled(!state.vim_controlled());
                 editor.selections.line_mode = matches!(state.mode, Mode::Visual { line: true });
                 let context_layer = state.keymap_context_layer();
-                editor.set_keymap_context_layer::<Self>(context_layer);
+                editor.set_keymap_context_layer::<Self>(context_layer, cx);
             } else {
                 Self::unhook_vim_settings(editor, cx);
             }
@@ -321,7 +321,7 @@ impl Vim {
         editor.set_clip_at_line_ends(false, cx);
         editor.set_input_enabled(true);
         editor.selections.line_mode = false;
-        editor.remove_keymap_context_layer::<Self>();
+        editor.remove_keymap_context_layer::<Self>(cx);
     }
 }
 

crates/workspace/src/pane.rs 🔗

@@ -1831,12 +1831,11 @@ impl View for Pane {
         });
     }
 
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        let mut keymap = Self::default_keymap_context();
+    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
+        Self::reset_to_default_keymap_context(keymap);
         if self.docked.is_some() {
             keymap.add_identifier("docked");
         }
-        keymap
     }
 }
 

crates/workspace/src/workspace.rs 🔗

@@ -37,7 +37,6 @@ use gpui::{
         vector::{vec2f, Vector2F},
     },
     impl_actions,
-    keymap_matcher::KeymapContext,
     platform::{
         CursorStyle, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds,
         WindowOptions,
@@ -2809,10 +2808,6 @@ impl View for Workspace {
             }
         }
     }
-
-    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
-        Self::default_keymap_context()
-    }
 }
 
 impl ViewId {