Remove unnecessary type aliases

Richard Feldman created

Change summary

crates/gpui/src/elements/div.rs | 125 +++++++++++++++++++++++++++++++---
1 file changed, 113 insertions(+), 12 deletions(-)

Detailed changes

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

@@ -38,7 +38,7 @@ use std::{
     fmt::Debug,
     marker::PhantomData,
     mem,
-    rc::{Rc, Weak},
+    rc::Rc,
     sync::Arc,
     time::Duration,
 };
@@ -2878,7 +2878,7 @@ pub struct InteractiveElementState {
     pub(crate) hover_listener_state: Option<Rc<RefCell<bool>>>,
     pub(crate) pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
     pub(crate) scroll_offset: Option<Rc<RefCell<Point<Pixels>>>>,
-    pub(crate) active_tooltip: Option<ActiveTooltipState>,
+    pub(crate) active_tooltip: Option<Rc<RefCell<Option<ActiveTooltip>>>>,
 }
 
 /// Whether or not the element or a group that contains it is clicked by the mouse.
@@ -2907,9 +2907,6 @@ pub struct ElementHoverState {
     pub element: bool,
 }
 
-type ActiveTooltipState = Rc<RefCell<Option<ActiveTooltip>>>;
-type WeakActiveTooltipState = Weak<RefCell<Option<ActiveTooltip>>>;
-
 pub(crate) enum ActiveTooltip {
     /// Currently delaying before showing the tooltip.
     WaitingForShow { _task: Task<()> },
@@ -2926,7 +2923,10 @@ pub(crate) enum ActiveTooltip {
     },
 }
 
-pub(crate) fn clear_active_tooltip(active_tooltip: &ActiveTooltipState, window: &mut Window) {
+pub(crate) fn clear_active_tooltip(
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
+    window: &mut Window,
+) {
     match active_tooltip.borrow_mut().take() {
         None => {}
         Some(ActiveTooltip::WaitingForShow { .. }) => {}
@@ -2936,7 +2936,7 @@ pub(crate) fn clear_active_tooltip(active_tooltip: &ActiveTooltipState, window:
 }
 
 pub(crate) fn clear_active_tooltip_if_not_hoverable(
-    active_tooltip: &ActiveTooltipState,
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
     window: &mut Window,
 ) {
     let should_clear = match active_tooltip.borrow().as_ref() {
@@ -2952,7 +2952,7 @@ pub(crate) fn clear_active_tooltip_if_not_hoverable(
 }
 
 pub(crate) fn set_tooltip_on_window(
-    active_tooltip: &ActiveTooltipState,
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
     window: &mut Window,
 ) -> Option<TooltipId> {
     let tooltip = match active_tooltip.borrow().as_ref() {
@@ -2965,7 +2965,7 @@ pub(crate) fn set_tooltip_on_window(
 }
 
 pub(crate) fn register_tooltip_mouse_handlers(
-    active_tooltip: &ActiveTooltipState,
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
     tooltip_id: Option<TooltipId>,
     build_tooltip: Rc<dyn Fn(&mut Window, &mut App) -> Option<(AnyView, bool)>>,
     check_is_hovered: Rc<dyn Fn(&Window) -> bool>,
@@ -3020,7 +3020,7 @@ pub(crate) fn register_tooltip_mouse_handlers(
 /// does not know if the hitbox is occluded. In the case where a tooltip gets displayed and then
 /// gets occluded after display, it will stick around until the mouse exits the hover bounds.
 fn handle_tooltip_mouse_move(
-    active_tooltip: &ActiveTooltipState,
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
     build_tooltip: &Rc<dyn Fn(&mut Window, &mut App) -> Option<(AnyView, bool)>>,
     check_is_hovered: &Rc<dyn Fn(&Window) -> bool>,
     check_is_hovered_during_prepaint: &Rc<dyn Fn(&Window) -> bool>,
@@ -3123,7 +3123,7 @@ fn handle_tooltip_mouse_move(
 /// purpose of doing this logic here instead of the mouse move handler is that the mouse move
 /// handler won't get called when the element is not painted (e.g. via use of `visible_on_hover`).
 fn handle_tooltip_check_visible_and_update(
-    active_tooltip: &ActiveTooltipState,
+    active_tooltip: &Rc<RefCell<Option<ActiveTooltip>>>,
     tooltip_is_hoverable: bool,
     check_is_hovered: &Rc<dyn Fn(&Window) -> bool>,
     tooltip_bounds: Bounds<Pixels>,
@@ -3168,7 +3168,7 @@ fn handle_tooltip_check_visible_and_update(
         Action::Hide => clear_active_tooltip(active_tooltip, window),
         Action::ScheduleHide(tooltip) => {
             let delayed_hide_task = window.spawn(cx, {
-                let weak_active_tooltip: WeakActiveTooltipState = Rc::downgrade(active_tooltip);
+                let weak_active_tooltip = Rc::downgrade(active_tooltip);
                 async move |cx| {
                     cx.background_executor()
                         .timer(HOVERABLE_TOOLTIP_HIDE_DELAY)
@@ -3588,6 +3588,62 @@ impl ScrollHandle {
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::{AppContext as _, Context, Modifiers, TestAppContext, size};
+    use std::sync::{
+        Arc,
+        atomic::{AtomicUsize, Ordering::SeqCst},
+    };
+
+    struct TooltipLifecycleCounts {
+        created: AtomicUsize,
+        dropped: AtomicUsize,
+    }
+
+    struct DropTrackingTooltip {
+        tooltip_lifecycle_counts: Arc<TooltipLifecycleCounts>,
+    }
+
+    impl Drop for DropTrackingTooltip {
+        fn drop(&mut self) {
+            self.tooltip_lifecycle_counts.dropped.fetch_add(1, SeqCst);
+        }
+    }
+
+    impl Render for DropTrackingTooltip {
+        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+            div().w(px(20.)).h(px(20.)).child("tooltip")
+        }
+    }
+
+    struct TooltipOwner {
+        show_target: bool,
+        tooltip_lifecycle_counts: Arc<TooltipLifecycleCounts>,
+    }
+
+    impl Render for TooltipOwner {
+        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
+            let root = div().size_full();
+            if self.show_target {
+                let tooltip_lifecycle_counts = self.tooltip_lifecycle_counts.clone();
+                root.child(
+                    div()
+                        .id("target")
+                        .w(px(50.))
+                        .h(px(50.))
+                        .tooltip(move |_window, cx| {
+                            tooltip_lifecycle_counts.created.fetch_add(1, SeqCst);
+                            let tooltip_lifecycle_counts = tooltip_lifecycle_counts.clone();
+                            cx.new(|_| DropTrackingTooltip {
+                                tooltip_lifecycle_counts,
+                            })
+                            .into()
+                        }),
+                )
+            } else {
+                root
+            }
+        }
+    }
 
     #[test]
     fn scroll_handle_aligns_wide_children_to_left_edge() {
@@ -3626,4 +3682,49 @@ mod tests {
 
         assert_eq!(handle.offset().y, px(-25.));
     }
+
+    #[test]
+    fn tooltip_is_released_when_its_owner_disappears() {
+        let mut test_app = TestAppContext::single();
+        let tooltip_lifecycle_counts = Arc::new(TooltipLifecycleCounts {
+            created: AtomicUsize::new(0),
+            dropped: AtomicUsize::new(0),
+        });
+
+        let (view, cx) = test_app.add_window_view({
+            let tooltip_lifecycle_counts = tooltip_lifecycle_counts.clone();
+            move |_window, _cx| TooltipOwner {
+                show_target: true,
+                tooltip_lifecycle_counts,
+            }
+        });
+
+        cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| {
+            view.clone().into_any_element()
+        });
+        cx.simulate_mouse_move(point(px(10.), px(10.)), None, Modifiers::default());
+        cx.run_until_parked();
+        cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| {
+            view.clone().into_any_element()
+        });
+
+        assert_eq!(tooltip_lifecycle_counts.created.load(SeqCst), 1);
+        assert_eq!(tooltip_lifecycle_counts.dropped.load(SeqCst), 0);
+
+        cx.update(|_window, app| {
+            view.update(app, |tooltip_owner, cx| {
+                tooltip_owner.show_target = false;
+                cx.notify();
+            });
+        });
+        cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| {
+            view.clone().into_any_element()
+        });
+        cx.run_until_parked();
+        cx.draw(point(px(0.), px(0.)), size(px(100.), px(100.)), |_, _| {
+            view.clone().into_any_element()
+        });
+
+        assert_eq!(tooltip_lifecycle_counts.dropped.load(SeqCst), 1);
+    }
 }