Start on view-level dispatch approach for keyboard events

Nathan Sobo created

Change summary

crates/chat_panel/src/chat_panel.rs            |   2 
crates/collab_ui/src/contact_finder.rs         |   2 
crates/collab_ui/src/contact_list.rs           |   4 
crates/collab_ui/src/contacts_popover.rs       |   2 
crates/command_palette/src/command_palette.rs  |   2 
crates/context_menu/src/context_menu.rs        |   2 
crates/diagnostics/src/diagnostics.rs          |   2 
crates/editor/src/editor.rs                    |   4 
crates/file_finder/src/file_finder.rs          |   2 
crates/go_to_line/src/go_to_line.rs            |   2 
crates/gpui/src/app.rs                         | 188 +++++++++++++++++--
crates/gpui/src/presenter.rs                   |  10 
crates/outline/src/outline.rs                  |   2 
crates/picker/src/picker.rs                    |   2 
crates/project_symbols/src/project_symbols.rs  |   2 
crates/search/src/buffer_search.rs             |   2 
crates/search/src/project_search.rs            |   2 
crates/terminal/src/terminal_container_view.rs |   2 
crates/terminal/src/terminal_view.rs           |   4 
crates/theme_selector/src/theme_selector.rs    |   2 
crates/workspace/src/pane.rs                   |   2 
crates/workspace/src/workspace.rs              |   2 
22 files changed, 191 insertions(+), 53 deletions(-)

Detailed changes

crates/chat_panel/src/chat_panel.rs 🔗

@@ -397,7 +397,7 @@ impl View for ChatPanel {
         .boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if matches!(
             *self.rpc.status().borrow(),
             client::Status::Connected { .. }

crates/collab_ui/src/contact_finder.rs 🔗

@@ -36,7 +36,7 @@ impl View for ContactFinder {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/collab_ui/src/contact_list.rs 🔗

@@ -1121,13 +1121,13 @@ impl View for ContactList {
             .boxed()
     }
 
-    fn on_focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
         if !self.filter_editor.is_focused(cx) {
             cx.focus(&self.filter_editor);
         }
     }
 
-    fn on_focus_out(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_out(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
         if !self.filter_editor.is_focused(cx) {
             cx.emit(Event::Dismissed);
         }

crates/collab_ui/src/contacts_popover.rs 🔗

@@ -160,7 +160,7 @@ impl View for ContactsPopover {
         .boxed()
     }
 
-    fn on_focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             match &self.child {
                 Child::ContactList(child) => cx.focus(child),

crates/command_palette/src/command_palette.rs 🔗

@@ -135,7 +135,7 @@ impl View for CommandPalette {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/context_menu/src/context_menu.rs 🔗

@@ -107,7 +107,7 @@ impl View for ContextMenu {
             .boxed()
     }
 
-    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         self.reset(cx);
     }
 }

crates/diagnostics/src/diagnostics.rs 🔗

@@ -99,7 +99,7 @@ impl View for ProjectDiagnosticsEditor {
         }
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if !self.path_states.is_empty() {
             cx.focus(&self.editor);
         }

crates/editor/src/editor.rs 🔗

@@ -6477,7 +6477,7 @@ impl View for Editor {
         "Editor"
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         let focused_event = EditorFocused(cx.handle());
         cx.emit_global(focused_event);
         if let Some(rename) = self.pending_rename.as_ref() {
@@ -6498,7 +6498,7 @@ impl View for Editor {
         }
     }
 
-    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         let blurred_event = EditorBlurred(cx.handle());
         cx.emit_global(blurred_event);
         self.focused = false;

crates/file_finder/src/file_finder.rs 🔗

@@ -53,7 +53,7 @@ impl View for FileFinder {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/go_to_line/src/go_to_line.rs 🔗

@@ -183,7 +183,7 @@ impl View for GoToLine {
         .named("go to line")
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         cx.focus(&self.line_editor);
     }
 }

crates/gpui/src/app.rs 🔗

@@ -41,8 +41,8 @@ use crate::{
     platform::{self, KeyDownEvent, Platform, PromptLevel, WindowOptions},
     presenter::Presenter,
     util::post_inc,
-    Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, MouseButton,
-    MouseRegionId, PathPromptOptions, TextLayoutCache,
+    Appearance, AssetCache, AssetSource, ClipboardItem, FontCache, InputHandler, KeyUpEvent,
+    ModifiersChangedEvent, MouseButton, MouseRegionId, PathPromptOptions, TextLayoutCache,
 };
 
 pub trait Entity: 'static {
@@ -60,8 +60,18 @@ pub trait Entity: 'static {
 pub trait View: Entity + Sized {
     fn ui_name() -> &'static str;
     fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox;
-    fn on_focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
-    fn on_focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
+    fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
+    fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {}
+    fn key_down(&mut self, _: &KeyDownEvent, _: &mut ViewContext<Self>) -> bool {
+        false
+    }
+    fn key_up(&mut self, _: &KeyUpEvent, _: &mut ViewContext<Self>) -> bool {
+        false
+    }
+    fn modifiers_changed(&mut self, _: &ModifiersChangedEvent, _: &mut ViewContext<Self>) -> bool {
+        false
+    }
+
     fn keymap_context(&self, _: &AppContext) -> keymap::Context {
         Self::default_keymap_context()
     }
@@ -1297,7 +1307,7 @@ impl MutableAppContext {
     ) -> impl Iterator<Item = (&'static str, Box<dyn Action>, SmallVec<[&Binding; 1]>)> {
         let mut action_types: HashSet<_> = self.global_actions.keys().copied().collect();
 
-        for view_id in self.parents(window_id, view_id) {
+        for view_id in self.ancestors(window_id, view_id) {
             if let Some(view) = self.views.get(&(window_id, view_id)) {
                 let view_type = view.as_any().type_id();
                 if let Some(actions) = self.actions.get(&view_type) {
@@ -1327,7 +1337,7 @@ impl MutableAppContext {
         let action_type = action.as_any().type_id();
         if let Some(window_id) = self.cx.platform.key_window_id() {
             if let Some(focused_view_id) = self.focused_view_id(window_id) {
-                for view_id in self.parents(window_id, focused_view_id) {
+                for view_id in self.ancestors(window_id, focused_view_id) {
                     if let Some(view) = self.views.get(&(window_id, view_id)) {
                         let view_type = view.as_any().type_id();
                         if let Some(actions) = self.actions.get(&view_type) {
@@ -1376,7 +1386,7 @@ impl MutableAppContext {
         mut visit: impl FnMut(usize, bool, &mut MutableAppContext) -> bool,
     ) -> bool {
         // List of view ids from the leaf to the root of the window
-        let path = self.parents(window_id, view_id).collect::<Vec<_>>();
+        let path = self.ancestors(window_id, view_id).collect::<Vec<_>>();
 
         // Walk down from the root to the leaf calling visit with capture_phase = true
         for view_id in path.iter().rev() {
@@ -1397,7 +1407,7 @@ impl MutableAppContext {
 
     // Returns an iterator over all of the view ids from the passed view up to the root of the window
     // Includes the passed view itself
-    fn parents(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
+    fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator<Item = usize> + '_ {
         std::iter::once(view_id)
             .into_iter()
             .chain(std::iter::from_fn(move || {
@@ -1445,11 +1455,81 @@ impl MutableAppContext {
         self.keystroke_matcher.clear_bindings();
     }
 
+    pub fn dispatch_key_down(&mut self, window_id: usize, event: &KeyDownEvent) -> bool {
+        if let Some(focused_view_id) = self.focused_view_id(window_id) {
+            for view_id in self
+                .ancestors(window_id, focused_view_id)
+                .collect::<Vec<_>>()
+            {
+                if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
+                    let handled = view.key_down(event, self, window_id, view_id);
+                    self.cx.views.insert((window_id, view_id), view);
+                    if handled {
+                        return true;
+                    }
+                } else {
+                    log::error!("view {} does not exist", view_id)
+                }
+            }
+        }
+
+        false
+    }
+
+    pub fn dispatch_key_up(&mut self, window_id: usize, event: &KeyUpEvent) -> bool {
+        if let Some(focused_view_id) = self.focused_view_id(window_id) {
+            for view_id in self
+                .ancestors(window_id, focused_view_id)
+                .collect::<Vec<_>>()
+            {
+                if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
+                    let handled = view.key_up(event, self, window_id, view_id);
+                    self.cx.views.insert((window_id, view_id), view);
+                    if handled {
+                        return true;
+                    }
+                } else {
+                    log::error!("view {} does not exist", view_id)
+                }
+            }
+        }
+
+        false
+    }
+
+    pub fn dispatch_modifiers_changed(
+        &mut self,
+        window_id: usize,
+        event: &ModifiersChangedEvent,
+    ) -> bool {
+        if let Some(focused_view_id) = self.focused_view_id(window_id) {
+            for view_id in self
+                .ancestors(window_id, focused_view_id)
+                .collect::<Vec<_>>()
+            {
+                if let Some(mut view) = self.cx.views.remove(&(window_id, view_id)) {
+                    let handled = view.modifiers_changed(event, self, window_id, view_id);
+                    self.cx.views.insert((window_id, view_id), view);
+                    if handled {
+                        return true;
+                    }
+                } else {
+                    log::error!("view {} does not exist", view_id)
+                }
+            }
+        }
+
+        false
+    }
+
     pub fn dispatch_keystroke(&mut self, window_id: usize, keystroke: &Keystroke) -> bool {
         let mut pending = false;
 
         if let Some(focused_view_id) = self.focused_view_id(window_id) {
-            for view_id in self.parents(window_id, focused_view_id).collect::<Vec<_>>() {
+            for view_id in self
+                .ancestors(window_id, focused_view_id)
+                .collect::<Vec<_>>()
+            {
                 let keymap_context = self
                     .cx
                     .views
@@ -1580,7 +1660,7 @@ impl MutableAppContext {
                     is_fullscreen: false,
                 },
             );
-            root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
+            root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
 
             let window =
                 this.cx
@@ -1612,7 +1692,7 @@ impl MutableAppContext {
                     is_fullscreen: false,
                 },
             );
-            root_view.update(this, |view, cx| view.on_focus_in(cx.handle().into(), cx));
+            root_view.update(this, |view, cx| view.focus_in(cx.handle().into(), cx));
 
             let status_item = this.cx.platform.add_status_item();
             this.register_platform_window(window_id, status_item);
@@ -2235,12 +2315,12 @@ impl MutableAppContext {
 
             //Handle focus
             let focused_id = window.focused_view_id?;
-            for view_id in this.parents(window_id, focused_id).collect::<Vec<_>>() {
+            for view_id in this.ancestors(window_id, focused_id).collect::<Vec<_>>() {
                 if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
                     if active {
-                        view.on_focus_in(this, window_id, view_id, focused_id);
+                        view.focus_in(this, window_id, view_id, focused_id);
                     } else {
-                        view.on_focus_out(this, window_id, view_id, focused_id);
+                        view.focus_out(this, window_id, view_id, focused_id);
                     }
                     this.cx.views.insert((window_id, view_id), view);
                 }
@@ -2272,16 +2352,16 @@ impl MutableAppContext {
             });
 
             let blurred_parents = blurred_id
-                .map(|blurred_id| this.parents(window_id, blurred_id).collect::<Vec<_>>())
+                .map(|blurred_id| this.ancestors(window_id, blurred_id).collect::<Vec<_>>())
                 .unwrap_or_default();
             let focused_parents = focused_id
-                .map(|focused_id| this.parents(window_id, focused_id).collect::<Vec<_>>())
+                .map(|focused_id| this.ancestors(window_id, focused_id).collect::<Vec<_>>())
                 .unwrap_or_default();
 
             if let Some(blurred_id) = blurred_id {
                 for view_id in blurred_parents.iter().copied() {
                     if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
-                        view.on_focus_out(this, window_id, view_id, blurred_id);
+                        view.focus_out(this, window_id, view_id, blurred_id);
                         this.cx.views.insert((window_id, view_id), view);
                     }
                 }
@@ -2294,7 +2374,7 @@ impl MutableAppContext {
             if let Some(focused_id) = focused_id {
                 for view_id in focused_parents {
                     if let Some(mut view) = this.cx.views.remove(&(window_id, view_id)) {
-                        view.on_focus_in(this, window_id, view_id, focused_id);
+                        view.focus_in(this, window_id, view_id, focused_id);
                         this.cx.views.insert((window_id, view_id), view);
                     }
                 }
@@ -2961,20 +3041,41 @@ pub trait AnyView {
     ) -> Option<Pin<Box<dyn 'static + Future<Output = ()>>>>;
     fn ui_name(&self) -> &'static str;
     fn render(&mut self, params: RenderParams, cx: &mut MutableAppContext) -> ElementBox;
-    fn on_focus_in(
+    fn focus_in(
         &mut self,
         cx: &mut MutableAppContext,
         window_id: usize,
         view_id: usize,
         focused_id: usize,
     );
-    fn on_focus_out(
+    fn focus_out(
         &mut self,
         cx: &mut MutableAppContext,
         window_id: usize,
         view_id: usize,
         focused_id: usize,
     );
+    fn key_down(
+        &mut self,
+        event: &KeyDownEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool;
+    fn key_up(
+        &mut self,
+        event: &KeyUpEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool;
+    fn modifiers_changed(
+        &mut self,
+        event: &ModifiersChangedEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool;
     fn keymap_context(&self, cx: &AppContext) -> keymap::Context;
     fn debug_json(&self, cx: &AppContext) -> serde_json::Value;
 
@@ -3040,7 +3141,7 @@ where
         View::render(self, &mut RenderContext::new(params, cx))
     }
 
-    fn on_focus_in(
+    fn focus_in(
         &mut self,
         cx: &mut MutableAppContext,
         window_id: usize,
@@ -3059,10 +3160,10 @@ where
                 .type_id();
             AnyViewHandle::new(window_id, focused_id, focused_type, cx.ref_counts.clone())
         };
-        View::on_focus_in(self, focused_view_handle, &mut cx);
+        View::focus_in(self, focused_view_handle, &mut cx);
     }
 
-    fn on_focus_out(
+    fn focus_out(
         &mut self,
         cx: &mut MutableAppContext,
         window_id: usize,
@@ -3081,7 +3182,40 @@ where
                 .type_id();
             AnyViewHandle::new(window_id, blurred_id, blurred_type, cx.ref_counts.clone())
         };
-        View::on_focus_out(self, blurred_view_handle, &mut cx);
+        View::focus_out(self, blurred_view_handle, &mut cx);
+    }
+
+    fn key_down(
+        &mut self,
+        event: &KeyDownEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool {
+        let mut cx = ViewContext::new(cx, window_id, view_id);
+        View::key_down(self, event, &mut cx)
+    }
+
+    fn key_up(
+        &mut self,
+        event: &KeyUpEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool {
+        let mut cx = ViewContext::new(cx, window_id, view_id);
+        View::key_up(self, event, &mut cx)
+    }
+
+    fn modifiers_changed(
+        &mut self,
+        event: &ModifiersChangedEvent,
+        cx: &mut MutableAppContext,
+        window_id: usize,
+        view_id: usize,
+    ) -> bool {
+        let mut cx = ViewContext::new(cx, window_id, view_id);
+        View::modifiers_changed(self, event, &mut cx)
     }
 
     fn keymap_context(&self, cx: &AppContext) -> keymap::Context {
@@ -3463,7 +3597,7 @@ impl<'a, T: View> ViewContext<'a, T> {
         if self.window_id != view.window_id {
             return false;
         }
-        self.parents(view.window_id, view.view_id)
+        self.ancestors(view.window_id, view.view_id)
             .any(|parent| parent == self.view_id)
     }
 
@@ -6354,13 +6488,13 @@ mod tests {
                 "View"
             }
 
-            fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
+            fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
                 if cx.handle().id() == focused.id() {
                     self.events.lock().push(format!("{} focused", &self.name));
                 }
             }
 
-            fn on_focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
+            fn focus_out(&mut self, blurred: AnyViewHandle, cx: &mut ViewContext<Self>) {
                 if cx.handle().id() == blurred.id() {
                     self.events.lock().push(format!("{} blurred", &self.name));
                 }

crates/gpui/src/presenter.rs 🔗

@@ -232,10 +232,16 @@ impl Presenter {
             let mut mouse_events = SmallVec::<[_; 2]>::new();
             let mut notified_views: HashSet<usize> = Default::default();
 
-            // 1. Map the platform event into mouse events, which interact with mouse regions.
+            // 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
+            //    get mapped into the mouse-specific MouseEvent type.
             //  -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
             //  -> Also updates mouse-related state
             match &event {
+                Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
+                Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
+                Event::ModifiersChanged(e) => {
+                    return cx.dispatch_modifiers_changed(self.window_id, e)
+                }
                 Event::MouseDown(e) => {
                     // Click events are weird because they can be fired after a drag event.
                     // MDN says that browsers handle this by starting from 'the most
@@ -345,8 +351,6 @@ impl Presenter {
                         platform_event: e.clone(),
                     }))
                 }
-
-                _ => {}
             }
 
             if let Some(position) = event.position() {

crates/outline/src/outline.rs 🔗

@@ -52,7 +52,7 @@ impl View for OutlineView {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/picker/src/picker.rs 🔗

@@ -116,7 +116,7 @@ impl<D: PickerDelegate> View for Picker<D> {
         cx
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.query_editor);
         }

crates/project_symbols/src/project_symbols.rs 🔗

@@ -51,7 +51,7 @@ impl View for ProjectSymbolsView {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/search/src/buffer_search.rs 🔗

@@ -82,7 +82,7 @@ impl View for BufferSearchBar {
         "BufferSearchBar"
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.query_editor);
         }

crates/search/src/project_search.rs 🔗

@@ -195,7 +195,7 @@ impl View for ProjectSearchView {
         }
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         let handle = cx.weak_handle();
         cx.update_global(|state: &mut ActiveSearches, cx| {
             state

crates/terminal/src/terminal_container_view.rs 🔗

@@ -174,7 +174,7 @@ impl View for TerminalContainer {
         }
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(self.content.handle());
         }

crates/terminal/src/terminal_view.rs 🔗

@@ -343,14 +343,14 @@ impl View for TerminalView {
             .boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         self.has_new_content = false;
         self.terminal.read(cx).focus_in();
         self.blink_cursors(self.blink_epoch, cx);
         cx.notify();
     }
 
-    fn on_focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         self.terminal.update(cx, |terminal, _| {
             terminal.focus_out();
         });

crates/theme_selector/src/theme_selector.rs 🔗

@@ -266,7 +266,7 @@ impl View for ThemeSelector {
         ChildView::new(self.picker.clone(), cx).boxed()
     }
 
-    fn on_focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.picker);
         }

crates/workspace/src/pane.rs 🔗

@@ -1485,7 +1485,7 @@ impl View for Pane {
             .named("pane")
     }
 
-    fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if let Some(active_item) = self.active_item() {
             if cx.is_self_focused() {
                 // Pane was focused directly. We need to either focus a view inside the active item,

crates/workspace/src/workspace.rs 🔗

@@ -2656,7 +2656,7 @@ impl View for Workspace {
             .named("workspace")
     }
 
-    fn on_focus_in(&mut self, view: AnyViewHandle, cx: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, view: AnyViewHandle, cx: &mut ViewContext<Self>) {
         if cx.is_self_focused() {
             cx.focus(&self.active_pane);
         } else {