WIP

Nathan Sobo created

Change summary

crates/command_palette2/src/command_palette.rs |   2 
crates/editor2/src/element.rs                  | 114 ++++++++++----------
crates/gpui2/src/elements/div.rs               |  11 +
crates/gpui2/src/interactive.rs                |  17 +-
crates/gpui2/src/keymap/matcher.rs             |   1 
crates/gpui2/src/window.rs                     |   7 
6 files changed, 82 insertions(+), 70 deletions(-)

Detailed changes

crates/command_palette2/src/command_palette.rs 🔗

@@ -32,7 +32,9 @@ pub struct CommandPalette {
 
 impl CommandPalette {
     fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
+        dbg!("registering command palette toggle");
         workspace.register_action(|workspace, _: &Toggle, cx| {
+            dbg!("got cmd-shift-p");
             let Some(previous_focus_handle) = cx.focused() else {
                 return;
             };

crates/editor2/src/element.rs 🔗

@@ -2446,7 +2446,7 @@ impl Element<Editor> for EditorElement {
     type ElementState = ();
 
     fn element_id(&self) -> Option<gpui::ElementId> {
-        None
+        None // todo! can we change the element trait to return an id here from the view context?
     }
 
     fn initialize(
@@ -2456,6 +2456,41 @@ impl Element<Editor> for EditorElement {
         cx: &mut gpui::ViewContext<Editor>,
     ) -> Self::ElementState {
         editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
+    }
+
+    fn layout(
+        &mut self,
+        editor: &mut Editor,
+        element_state: &mut Self::ElementState,
+        cx: &mut gpui::ViewContext<Editor>,
+    ) -> gpui::LayoutId {
+        let rem_size = cx.rem_size();
+        let mut style = Style::default();
+        style.size.width = relative(1.).into();
+        style.size.height = match editor.mode {
+            EditorMode::SingleLine => self.style.text.line_height_in_pixels(cx.rem_size()).into(),
+            EditorMode::AutoHeight { .. } => todo!(),
+            EditorMode::Full => relative(1.).into(),
+        };
+        cx.request_layout(&style, None)
+    }
+
+    fn paint(
+        &mut self,
+        bounds: Bounds<gpui::Pixels>,
+        editor: &mut Editor,
+        element_state: &mut Self::ElementState,
+        cx: &mut gpui::ViewContext<Editor>,
+    ) {
+        let mut layout = self.compute_layout(editor, cx, bounds);
+        let gutter_bounds = Bounds {
+            origin: bounds.origin,
+            size: layout.gutter_size,
+        };
+        let text_bounds = Bounds {
+            origin: gutter_bounds.upper_right(),
+            size: layout.text_size,
+        };
 
         let dispatch_context = editor.dispatch_context(cx);
         cx.with_element_id(Some(cx.view().entity_id()), |cx| {
@@ -2621,63 +2656,28 @@ impl Element<Editor> for EditorElement {
                     register_action(cx, Editor::context_menu_prev);
                     register_action(cx, Editor::context_menu_next);
                     register_action(cx, Editor::context_menu_last);
-                },
-            )
-        });
-    }
-
-    fn layout(
-        &mut self,
-        editor: &mut Editor,
-        element_state: &mut Self::ElementState,
-        cx: &mut gpui::ViewContext<Editor>,
-    ) -> gpui::LayoutId {
-        let rem_size = cx.rem_size();
-        let mut style = Style::default();
-        style.size.width = relative(1.).into();
-        style.size.height = match editor.mode {
-            EditorMode::SingleLine => self.style.text.line_height_in_pixels(cx.rem_size()).into(),
-            EditorMode::AutoHeight { .. } => todo!(),
-            EditorMode::Full => relative(1.).into(),
-        };
-        cx.request_layout(&style, None)
-    }
 
-    fn paint(
-        &mut self,
-        bounds: Bounds<gpui::Pixels>,
-        editor: &mut Editor,
-        element_state: &mut Self::ElementState,
-        cx: &mut gpui::ViewContext<Editor>,
-    ) {
-        let mut layout = self.compute_layout(editor, cx, bounds);
-        let gutter_bounds = Bounds {
-            origin: bounds.origin,
-            size: layout.gutter_size,
-        };
-        let text_bounds = Bounds {
-            origin: gutter_bounds.upper_right(),
-            size: layout.text_size,
-        };
-
-        // We call with_z_index to establish a new stacking context.
-        cx.with_z_index(0, |cx| {
-            cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
-                self.paint_mouse_listeners(
-                    bounds,
-                    gutter_bounds,
-                    text_bounds,
-                    &layout.position_map,
-                    cx,
-                );
-                self.paint_background(gutter_bounds, text_bounds, &layout, cx);
-                if layout.gutter_size.width > Pixels::ZERO {
-                    self.paint_gutter(gutter_bounds, &mut layout, editor, cx);
-                }
-                self.paint_text(text_bounds, &mut layout, editor, cx);
-                let input_handler = ElementInputHandler::new(bounds, cx);
-                cx.handle_input(&editor.focus_handle, input_handler);
-            });
+                    // We call with_z_index to establish a new stacking context.
+                    cx.with_z_index(0, |cx| {
+                        cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
+                            self.paint_mouse_listeners(
+                                bounds,
+                                gutter_bounds,
+                                text_bounds,
+                                &layout.position_map,
+                                cx,
+                            );
+                            self.paint_background(gutter_bounds, text_bounds, &layout, cx);
+                            if layout.gutter_size.width > Pixels::ZERO {
+                                self.paint_gutter(gutter_bounds, &mut layout, editor, cx);
+                            }
+                            self.paint_text(text_bounds, &mut layout, editor, cx);
+                            let input_handler = ElementInputHandler::new(bounds, cx);
+                            cx.handle_input(&editor.focus_handle, input_handler);
+                        });
+                    });
+                },
+            );
         });
     }
 }

crates/gpui2/src/elements/div.rs 🔗

@@ -612,6 +612,7 @@ impl<V: 'static> Element<V> for Div<V> {
         let interactive_state = self
             .interactivity
             .initialize(element_state.map(|s| s.interactive_state), cx);
+
         for child in &mut self.children {
             child.initialize(view_state, cx);
         }
@@ -763,6 +764,7 @@ where
                     .unwrap_or_else(|| cx.focus_handle())
             });
         }
+
         element_state
     }
 
@@ -773,11 +775,7 @@ where
         f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
     ) -> LayoutId {
         let style = self.compute_style(None, element_state, cx);
-        cx.with_key_dispatch(
-            self.key_context.clone(),
-            self.tracked_focus_handle.clone(),
-            |_, cx| f(style, cx),
-        )
+        f(style, cx)
     }
 
     pub fn paint(
@@ -1078,6 +1076,9 @@ where
                     })
                 }
 
+                if !self.key_context.is_empty() {
+                    dbg!(&self.key_context, self.action_listeners.len());
+                }
                 for (action_type, listener) in self.action_listeners.drain(..) {
                     cx.on_action(action_type, listener)
                 }

crates/gpui2/src/interactive.rs 🔗

@@ -286,8 +286,8 @@ pub struct FocusEvent {
 #[cfg(test)]
 mod test {
     use crate::{
-        self as gpui, div, Div, FocusHandle, InteractiveComponent, KeyBinding, Keystroke,
-        ParentComponent, Render, Stateful, TestAppContext, VisualContext,
+        self as gpui, div, Component, Div, FocusHandle, InteractiveComponent, KeyBinding,
+        Keystroke, ParentComponent, Render, Stateful, TestAppContext, ViewContext, VisualContext,
     };
 
     struct TestView {
@@ -304,10 +304,15 @@ mod test {
         fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element {
             div().id("testview").child(
                 div()
-                    .key_context("test")
-                    .track_focus(&self.focus_handle)
+                    .key_context("parent")
                     .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
-                    .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true),
+                    .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true)
+                    .child(|this: &mut Self, _cx: &mut ViewContext<Self>| {
+                        div()
+                            .key_context("nested")
+                            .track_focus(&this.focus_handle)
+                            .render()
+                    }),
             )
         }
     }
@@ -325,7 +330,7 @@ mod test {
         });
 
         cx.update(|cx| {
-            cx.bind_keys(vec![KeyBinding::new("ctrl-g", TestAction, None)]);
+            cx.bind_keys(vec![KeyBinding::new("ctrl-g", TestAction, Some("parent"))]);
         });
 
         window

crates/gpui2/src/window.rs 🔗

@@ -1309,6 +1309,7 @@ impl<'a> WindowContext<'a> {
             .current_frame
             .dispatch_tree
             .dispatch_path(node_id);
+        dbg!(node_id, &dispatch_path, self.propagate_event);
 
         // Capture phase
         for node_id in &dispatch_path {
@@ -1328,6 +1329,8 @@ impl<'a> WindowContext<'a> {
             }
         }
 
+        dbg!(node_id, &dispatch_path, self.propagate_event);
+
         // Bubble phase
         for node_id in dispatch_path.iter().rev() {
             let node = self.window.current_frame.dispatch_tree.node(*node_id);
@@ -1337,6 +1340,7 @@ impl<'a> WindowContext<'a> {
             } in node.action_listeners.clone()
             {
                 let any_action = action.as_any();
+                dbg!(action_type, any_action.type_id());
                 if action_type == any_action.type_id() {
                     self.propagate_event = false; // Actions stop propagation by default during the bubble phase
                     listener(any_action, DispatchPhase::Bubble, self);
@@ -2082,11 +2086,10 @@ impl<'a, V: 'static> ViewContext<'a, V> {
         f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
     ) -> R {
         let window = &mut self.window;
-
         window
             .current_frame
             .dispatch_tree
-            .push_node(context, &mut window.previous_frame.dispatch_tree);
+            .push_node(context.clone(), &mut window.previous_frame.dispatch_tree);
         if let Some(focus_handle) = focus_handle.as_ref() {
             window
                 .current_frame