WIP

Nathan Sobo created

Change summary

crates/gpui/src/app.rs                  | 76 +++++++++++++++-----------
crates/gpui/src/app/ref_counts.rs       |  5 -
crates/gpui/src/app/test_app_context.rs |  2 
crates/gpui/src/app/window.rs           |  2 
4 files changed, 47 insertions(+), 38 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -498,8 +498,8 @@ pub struct AppContext {
     // Action Types -> Action Handlers
     global_actions: HashMap<TypeId, Box<GlobalActionCallback>>,
     keystroke_matcher: KeymapMatcher,
-    next_entity_id: usize,
-    next_window_id: usize,
+    next_id: usize,
+    // next_window_id: usize,
     next_subscription_id: usize,
     frame_count: usize,
 
@@ -558,8 +558,7 @@ impl AppContext {
             actions: Default::default(),
             global_actions: Default::default(),
             keystroke_matcher: KeymapMatcher::default(),
-            next_entity_id: 0,
-            next_window_id: 0,
+            next_id: 0,
             next_subscription_id: 0,
             frame_count: 0,
             subscriptions: Default::default(),
@@ -1230,7 +1229,7 @@ impl AppContext {
         F: FnOnce(&mut ModelContext<T>) -> T,
     {
         self.update(|this| {
-            let model_id = post_inc(&mut this.next_entity_id);
+            let model_id = post_inc(&mut this.next_id);
             let handle = ModelHandle::new(model_id, &this.ref_counts);
             let mut cx = ModelContext::new(this, model_id);
             let model = build_model(&mut cx);
@@ -1310,7 +1309,7 @@ impl AppContext {
         F: FnOnce(&mut ViewContext<V>) -> V,
     {
         self.update(|this| {
-            let window_id = post_inc(&mut this.next_window_id);
+            let window_id = post_inc(&mut this.next_id);
             let platform_window =
                 this.platform
                     .open_window(window_id, window_options, this.foreground.clone());
@@ -1326,7 +1325,7 @@ impl AppContext {
         F: FnOnce(&mut ViewContext<V>) -> V,
     {
         self.update(|this| {
-            let window_id = post_inc(&mut this.next_window_id);
+            let window_id = post_inc(&mut this.next_id);
             let platform_window = this.platform.add_status_item(window_id);
             let window = this.build_window(window_id, platform_window, build_root_view);
             let root_view = window.root_view().clone().downcast::<V>().unwrap();
@@ -3810,6 +3809,7 @@ pub struct WindowHandle<T> {
     view_type: PhantomData<T>,
 }
 
+#[allow(dead_code)]
 impl<V: View> WindowHandle<V> {
     fn id(&self) -> usize {
         self.any_handle.id()
@@ -3922,6 +3922,17 @@ impl AnyWindowHandle {
     pub fn id(&self) -> usize {
         self.window_id
     }
+
+    pub fn downcast<V: View>(self) -> Option<WindowHandle<V>> {
+        if TypeId::of::<V>() == self.root_view_type {
+            Some(WindowHandle {
+                any_handle: self,
+                view_type: PhantomData,
+            })
+        } else {
+            None
+        }
+    }
 }
 
 impl Drop for AnyWindowHandle {
@@ -5613,20 +5624,18 @@ mod tests {
             child: None,
         });
         let view_1 = window.root(cx);
-        let view_2 = window
-            .update(cx, |cx| {
-                let view_2 = cx.add_view(|_| View {
-                    events: view_events.clone(),
-                    name: "view 2".to_string(),
-                    child: None,
-                });
-                view_1.update(cx, |view_1, cx| {
-                    view_1.child = Some(view_2.clone().into_any());
-                    cx.notify();
-                });
-                view_2
-            })
-            .unwrap();
+        let view_2 = window.update(cx, |cx| {
+            let view_2 = cx.add_view(|_| View {
+                events: view_events.clone(),
+                name: "view 2".to_string(),
+                child: None,
+            });
+            view_1.update(cx, |view_1, cx| {
+                view_1.child = Some(view_2.clone().into_any());
+                cx.notify();
+            });
+            view_2
+        });
 
         let observed_events: Arc<Mutex<Vec<String>>> = Default::default();
         view_1.update(cx, |_, cx| {
@@ -6071,26 +6080,26 @@ mod tests {
             }
         });
 
-        cx.update_window(window_id, |cx| {
+        window.update(cx, |cx| {
             cx.dispatch_keystroke(&Keystroke::parse("a").unwrap())
         });
         assert_eq!(&*actions.borrow(), &["2 a"]);
         actions.borrow_mut().clear();
 
-        cx.update_window(window_id, |cx| {
+        window.update(cx, |cx| {
             cx.dispatch_keystroke(&Keystroke::parse("b").unwrap());
         });
 
         assert_eq!(&*actions.borrow(), &["3 b", "2 b", "1 b", "global b"]);
         actions.borrow_mut().clear();
 
-        cx.update_window(window_id, |cx| {
+        window.update(cx, |cx| {
             cx.dispatch_keystroke(&Keystroke::parse("c").unwrap());
         });
         assert_eq!(&*actions.borrow(), &["3 c"]);
         actions.borrow_mut().clear();
 
-        cx.update_window(window_id, |cx| {
+        window.update(cx, |cx| {
             cx.dispatch_keystroke(&Keystroke::parse("d").unwrap());
         });
         assert_eq!(&*actions.borrow(), &["2 d"]);
@@ -6201,7 +6210,7 @@ mod tests {
 
         // Check that global actions do not have a binding, even if a binding does exist in another view
         assert_eq!(
-            &available_actions(window_id, view_1.id(), cx),
+            &available_actions(window.id(), view_1.id(), cx),
             &[
                 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
                 ("test::GlobalAction", vec![])
@@ -6210,7 +6219,7 @@ mod tests {
 
         // Check that view 1 actions and bindings are available even when called from view 2
         assert_eq!(
-            &available_actions(window_id, view_2.id(), cx),
+            &available_actions(window.id(), view_2.id(), cx),
             &[
                 ("test::Action1", vec![Keystroke::parse("a").unwrap()]),
                 ("test::Action2", vec![Keystroke::parse("b").unwrap()]),
@@ -6273,7 +6282,7 @@ mod tests {
             ]);
         });
 
-        let actions = cx.available_actions(window_id, view.id());
+        let actions = cx.available_actions(window.id(), view.id());
         assert_eq!(
             actions[0].1.as_any().downcast_ref::<ActionWithArg>(),
             Some(&ActionWithArg { arg: false })
@@ -6559,25 +6568,25 @@ mod tests {
             [("window 2", false), ("window 3", true)]
         );
 
-        cx.simulate_window_activation(Some(window_2));
+        cx.simulate_window_activation(Some(window_2.id()));
         assert_eq!(
             mem::take(&mut *events.borrow_mut()),
             [("window 3", false), ("window 2", true)]
         );
 
-        cx.simulate_window_activation(Some(window_1));
+        cx.simulate_window_activation(Some(window_1.id()));
         assert_eq!(
             mem::take(&mut *events.borrow_mut()),
             [("window 2", false), ("window 1", true)]
         );
 
-        cx.simulate_window_activation(Some(window_3));
+        cx.simulate_window_activation(Some(window_3.id()));
         assert_eq!(
             mem::take(&mut *events.borrow_mut()),
             [("window 1", false), ("window 3", true)]
         );
 
-        cx.simulate_window_activation(Some(window_3));
+        cx.simulate_window_activation(Some(window_3.id()));
         assert_eq!(mem::take(&mut *events.borrow_mut()), []);
     }
 
@@ -6633,12 +6642,13 @@ mod tests {
 
         let child_rendered = Rc::new(Cell::new(false));
         let child_dropped = Rc::new(Cell::new(false));
-        let (_, root_view) = cx.add_window(|cx| Parent {
+        let window = cx.add_window(|cx| Parent {
             child: Some(cx.add_view(|_| Child {
                 rendered: child_rendered.clone(),
                 dropped: child_dropped.clone(),
             })),
         });
+        let root_view = window.root(cx);
         assert!(child_rendered.take());
         assert!(!child_dropped.take());
 

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

@@ -23,7 +23,6 @@ struct ElementStateRefCount {
 
 #[derive(Default)]
 pub struct RefCounts {
-    window_counts: HashMap<usize, usize>,
     entity_counts: HashMap<usize, usize>,
     element_state_counts: HashMap<ElementStateId, ElementStateRefCount>,
     dropped_windows: HashSet<usize>,
@@ -46,7 +45,7 @@ impl RefCounts {
     }
 
     pub fn inc_window(&mut self, window_id: usize) {
-        match self.window_counts.entry(window_id) {
+        match self.entity_counts.entry(window_id) {
             Entry::Occupied(mut entry) => {
                 *entry.get_mut() += 1;
             }
@@ -100,7 +99,7 @@ impl RefCounts {
     }
 
     pub fn dec_window(&mut self, window_id: usize) {
-        let count = self.window_counts.get_mut(&window_id).unwrap();
+        let count = self.entity_counts.get_mut(&window_id).unwrap();
         *count -= 1;
         if *count == 0 {
             self.entity_counts.remove(&window_id);

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

@@ -60,7 +60,7 @@ impl TestAppContext {
             RefCounts::new(leak_detector),
             (),
         );
-        cx.next_entity_id = first_entity_id;
+        cx.next_id = first_entity_id;
         let cx = TestAppContext {
             cx: Rc::new(RefCell::new(cx)),
             foreground_platform,

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

@@ -1176,7 +1176,7 @@ impl<'a> WindowContext<'a> {
         F: FnOnce(&mut ViewContext<T>) -> Option<T>,
     {
         let window_id = self.window_id;
-        let view_id = post_inc(&mut self.next_entity_id);
+        let view_id = post_inc(&mut self.next_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();