Fix tooltip crash when route has secondary animation (#172678)

Makes the tooltip interactive if the route is the current route and the
route is not animating out.

Added `_route` to cache `ModalRoute.of(context)`.

Consolidates [Fix the issue with
Tooltip](https://github.com/flutter/flutter/pull/168546) and [Delay
showing tooltip during page
transition](https://github.com/flutter/flutter/pull/167614)

Fix [[Desktop] [Web] [Regression] [3.32] AppBar back - RenderBox was not
laid out -
TooltipState._buildTooltipOverlay](https://github.com/flutter/flutter/issues/169741)
diff --git a/packages/flutter/lib/src/material/tooltip.dart b/packages/flutter/lib/src/material/tooltip.dart
index dcfef71..86e2e77 100644
--- a/packages/flutter/lib/src/material/tooltip.dart
+++ b/packages/flutter/lib/src/material/tooltip.dart
@@ -606,10 +606,6 @@
   }
 
   void _handlePointerDown(PointerDownEvent event) {
-    assert(mounted);
-    if (!(ModalRoute.isCurrentOf(context) ?? true)) {
-      return;
-    }
     // PointerDeviceKinds that don't support hovering.
     const Set<PointerDeviceKind> triggerModeDeviceKinds = <PointerDeviceKind>{
       PointerDeviceKind.invertedStylus,
@@ -722,10 +718,6 @@
   //    (even these tooltips are still hovered),
   //    iii. The last hovering device leaves the tooltip.
   void _handleMouseEnter(PointerEnterEvent event) {
-    assert(mounted);
-    if (!(ModalRoute.isCurrentOf(context) ?? true)) {
-      return;
-    }
     // _handleMouseEnter is only called when the mouse starts to hover over this
     // tooltip (including the actual tooltip it shows on the overlay), and this
     // tooltip is the first to be hit in the widget tree's hit testing order.
@@ -747,10 +739,6 @@
   }
 
   void _handleMouseExit(PointerExitEvent event) {
-    assert(mounted);
-    if (!(ModalRoute.isCurrentOf(context) ?? true)) {
-      return;
-    }
     if (_activeHoveringPointerDevices.isEmpty) {
       return;
     }
@@ -826,12 +814,14 @@
     };
   }
 
-  Widget _buildTooltipOverlay(BuildContext context) {
-    final OverlayState overlayState = Overlay.of(context, debugRequiredFor: widget);
-    final RenderBox box = this.context.findRenderObject()! as RenderBox;
-    final Offset target = box.localToGlobal(
-      box.size.center(Offset.zero),
-      ancestor: overlayState.context.findRenderObject(),
+  Widget _buildTooltipOverlay(BuildContext context, OverlayChildLayoutInfo layoutInfo) {
+    if (layoutInfo.childPaintTransform.determinant() == 0.0) {
+      // The child is not visible.
+      return const SizedBox.shrink();
+    }
+    final Offset target = MatrixUtils.transformPoint(
+      layoutInfo.childPaintTransform,
+      layoutInfo.childSize.center(Offset.zero),
     );
 
     final (TextStyle defaultTextStyle, BoxDecoration defaultDecoration) = switch (Theme.of(
@@ -947,7 +937,7 @@
         ),
       );
     }
-    return OverlayPortal(
+    return OverlayPortal.overlayChildLayoutBuilder(
       controller: _overlayController,
       overlayChildBuilder: _buildTooltipOverlay,
       child: result,
diff --git a/packages/flutter/test/material/tooltip_test.dart b/packages/flutter/test/material/tooltip_test.dart
index 5112c7c..65f80d7 100644
--- a/packages/flutter/test/material/tooltip_test.dart
+++ b/packages/flutter/test/material/tooltip_test.dart
@@ -3511,6 +3511,69 @@
     expect(tester.takeException(), isNull);
   });
 
+  // This is a regression test for https://github.com/flutter/flutter/issues/169741.
+  testWidgets(
+    'Tooltip does not show while transitioning from another route with secondary animation',
+    (WidgetTester tester) async {
+      final TransitionDurationObserver observer = TransitionDurationObserver();
+
+      await tester.pumpWidget(
+        MaterialApp(
+          navigatorObservers: <NavigatorObserver>[observer],
+          home: Scaffold(
+            body: Builder(
+              builder: (BuildContext context) {
+                return TextButton(
+                  onPressed: () => Navigator.push(
+                    context,
+                    CupertinoPageRoute<void>(
+                      builder: (BuildContext context) => Scaffold(
+                        appBar: AppBar(
+                          leading: const Tooltip(message: 'Hello', child: Text('World')),
+                        ),
+                        body: TextButton(
+                          onPressed: () {
+                            Navigator.of(context).push(
+                              MaterialPageRoute<void>(
+                                builder: (BuildContext context) {
+                                  return Scaffold(appBar: AppBar(title: const Text('Third Page')));
+                                },
+                              ),
+                            );
+                          },
+                          child: const Text('Go to Third Page'),
+                        ),
+                      ),
+                    ),
+                  ),
+                  child: const Text('Go to Second Page'),
+                );
+              },
+            ),
+          ),
+        ),
+      );
+
+      expect(find.text('Go to Second Page'), findsOneWidget);
+      await tester.tap(find.text('Go to Second Page'));
+      await tester.pumpAndSettle();
+      expect(find.text('Go to Third Page'), findsOneWidget);
+
+      await tester.tap(find.text('Go to Third Page'));
+      await tester.pumpAndSettle();
+      expect(find.text('Third Page'), findsOneWidget);
+
+      final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
+      await gesture.addPointer();
+      await tester.tap(find.byType(BackButton));
+      await observer.pumpPastTransition(tester);
+      await gesture.moveTo(tester.getCenter(find.text('World')));
+      await tester.pumpAndSettle();
+
+      expect(tester.takeException(), isNull);
+    },
+  );
+
   /// This is a regression test for https://github.com/flutter/flutter/issues/168545
   testWidgets('The Tooltip on the ModalBottomSheet can still be displayed after showMenu.', (
     WidgetTester tester,