[go: nahoru, domu]

Revert "Handling the removal of PointerInputFilters synchronously."

This reverts commit 60699735a001203befb054cc7e30067d3203291c.

Reason for revert: Raced with another CL and broke the build.

Change-Id: I57d753a237311616cf21ab3a823137acb5c003a2
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
index abfdd6d..02b4d9e1 100644
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
+++ b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/CoreDemos.kt
@@ -34,7 +34,6 @@
 import androidx.ui.core.demos.gestures.ScaleGestureFilterDemo
 import androidx.ui.core.demos.gestures.DragGestureFilterDemo
 import androidx.ui.core.demos.gestures.LongPressDragGestureFilterDemo
-import androidx.ui.core.demos.gestures.PointerInputDuringSubComp
 import androidx.ui.core.demos.keyinput.KeyInputDemo
 import androidx.ui.core.demos.viewinterop.ViewInComposeDemo
 import androidx.ui.demos.common.ComposableDemo
@@ -62,8 +61,7 @@
             ComposableDemo("Drag and Scale") { DragAndScaleGestureDetectorDemo() },
             ComposableDemo("Popup Drag") { PopupDragDemo() },
             ComposableDemo("Double Tap in Tap") { DoubleTapInTapDemo() },
-            ComposableDemo("Nested Long Press") { NestedLongPressDemo() },
-            ComposableDemo("Pointer Input During Sub Comp") { PointerInputDuringSubComp() }
+            ComposableDemo("Nested Long Press") { NestedLongPressDemo() }
         ))
 ))
 
diff --git a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/SurviveThroughSubComp.kt b/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/SurviveThroughSubComp.kt
deleted file mode 100644
index 22fa31a..0000000
--- a/ui/ui-core/integration-tests/ui-core-demos/src/main/java/androidx/ui/core/demos/gestures/SurviveThroughSubComp.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.ui.core.demos.gestures
-
-import androidx.compose.Composable
-import androidx.compose.remember
-import androidx.compose.state
-import androidx.ui.core.Alignment
-import androidx.ui.core.Modifier
-import androidx.ui.core.PointerEventPass
-import androidx.ui.core.PointerInputChange
-import androidx.ui.core.changedToDownIgnoreConsumed
-import androidx.ui.core.changedToUpIgnoreConsumed
-import androidx.ui.core.composed
-import androidx.ui.core.pointerinput.PointerInputFilter
-import androidx.ui.core.pointerinput.PointerInputModifier
-import androidx.ui.foundation.AdapterList
-import androidx.ui.foundation.Box
-import androidx.ui.foundation.Text
-import androidx.ui.foundation.drawBackground
-import androidx.ui.foundation.drawBorder
-import androidx.ui.graphics.Color
-import androidx.ui.layout.Column
-import androidx.ui.layout.fillMaxSize
-import androidx.ui.layout.size
-import androidx.ui.layout.wrapContentSize
-import androidx.ui.unit.IntSize
-import androidx.ui.unit.TextUnit
-import androidx.ui.unit.dp
-
-/**
- * Demonstration of how various press/tap gesture interact together in a nested fashion.
- */
-@Composable
-fun PointerInputDuringSubComp() {
-    Column {
-        Text(
-            "Demonstrates that PointerInputFilters that are currently receiving pointer input " +
-                    "events can be removed from the hierarchy by sub composition with no difficulty"
-        )
-        Text(
-            "Below is an AdapterList with many touchable items.  Each item keeps track of the " +
-                    "number of pointers touching it.  If you touch an item and then scroll so " +
-                    "that it goes out of the viewport and then back into the viewport, you will" +
-                    " see that it no longer knows that a finger is touching it.  That is because " +
-                    "it is actually a new item that has not been hit tested yet.  If you keep " +
-                    "your finger there and then add more fingers, it will track those new fingers."
-        )
-        AdapterList(
-            List(100) { index -> index },
-            Modifier
-                .fillMaxSize()
-                .wrapContentSize(Alignment.Center)
-                .size(200.dp)
-                .drawBackground(Color.White)
-        ) {
-            val pointerCount = state { 0 }
-
-            Box(
-                Modifier.size(200.dp)
-                    .drawBorder(size = 1.dp, color = Color.Black)
-                    .pointerCounterGestureFilter { newCount -> pointerCount.value = newCount }
-            ) {
-                Text(
-                    "${pointerCount.value}",
-                    fontSize = TextUnit.Em(16),
-                    color = Color.Black,
-                    modifier = Modifier.fillMaxSize().wrapContentSize(Alignment.Center)
-                )
-            }
-        }
-    }
-}
-
-fun Modifier.pointerCounterGestureFilter(
-    onPointerCountChanged: (Int) -> Unit
-): Modifier =
-    composed {
-        val filter = remember { PointerCounterGestureFilter() }
-        filter.>
-        PointerInputModifierImpl(filter)
-    }
-
-internal class PointerInputModifierImpl(override val pointerInputFilter: PointerInputFilter) :
-    PointerInputModifier
-
-internal class PointerCounterGestureFilter : PointerInputFilter() {
-
-    lateinit var onPointerCountChanged: (resultingPointerCount: Int) -> Unit
-
-    override fun onPointerInput(
-        changes: List<PointerInputChange>,
-        pass: PointerEventPass,
-        bounds: IntSize
-    ): List<PointerInputChange> {
-        if (pass == PointerEventPass.PostUp) {
-            if (changes.any {
-                    it.changedToDownIgnoreConsumed() || it.changedToUpIgnoreConsumed()
-                }) {
-                onPointerCountChanged.invoke(changes.count { it.current.down })
-            }
-        }
-        return changes
-    }
-
-    override fun onCancel() {}
-}
diff --git a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
index d645955..07b2054 100644
--- a/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
+++ b/ui/ui-core/src/main/java/androidx/ui/core/pointerinput/HitPathTracker.kt
@@ -405,7 +405,6 @@
         downPass: PointerEventPass,
         upPass: PointerEventPass?
     ): Boolean {
-
         // Filter for changes that are associated with pointer ids that are relevant to this node.
         val relevantChanges =
             pointerInputChanges.filterTo(mutableMapOf()) { entry ->
@@ -417,34 +416,28 @@
             return false
         }
 
-        // TODO(b/158243568): For this attached check, and all of the following checks like this, we
-        //  should ideally be dispatching cancel to the sub tree with this node as it's root, and
-        //  we should remove the same sub tree from the tracker.  This will currently happen on
-        //  the next dispatch of events, but we shouldn't have to wait for another event.
-        if (pointerInputFilter.isAttached) {
-            relevantChanges.let {
-                // TODO(shepshapard): would be nice if we didn't have to subtract and then add
-                //  offsets. This is currently done because the calculated offsets are currently
-                //  global, not relative to each other.
-                it.subtractOffset(pointerInputFilter.position)
-                it.dispatchToPointerInputFilter(
-                    pointerInputFilter,
-                    downPass,
-                    pointerInputFilter.size
-                )
-                it.addOffset(pointerInputFilter.position)
-            }
+        // For each relevant change:
+        //  1. subtract the offset
+        //  2. dispatch the change on the down pass,
+        //  3. update it in relevantChanges.
+        relevantChanges.let {
+            // TODO(shepshapard): would be nice if we didn't have to subtract and then add
+            //  offsets.  This is currently done because the calculated offsets are currently
+            //  global, not relative to eachother.
+            it.subtractOffset(pointerInputFilter.position)
+            it.dispatchToPointerInputFilter(pointerInputFilter, downPass, pointerInputFilter.size)
+            it.addOffset(pointerInputFilter.position)
         }
 
-        if (pointerInputFilter.isAttached) {
-            children.forEach { it.dispatchChanges(relevantChanges, downPass, upPass) }
-        }
+        // Call children recursively with the relevant changes.
+        children.forEach { it.dispatchChanges(relevantChanges, downPass, upPass) }
 
-        if (pointerInputFilter.isAttached && upPass != null) {
+        // For each relevant change:
+        //  1. dispatch the change on the up pass,
+        //  2. add the offset,
+        //  3. update it in  relevant changes.
+        if (upPass != null) {
             relevantChanges.let {
-                // TODO(shepshapard): would be nice if we didn't have to subtract and then add
-                //  offsets.  This is currently done because the calculated offsets are currently
-                //  global, not relative to each other.
                 it.subtractOffset(pointerInputFilter.position)
                 it.dispatchToPointerInputFilter(pointerInputFilter, upPass, pointerInputFilter.size)
                 it.addOffset(pointerInputFilter.position)
@@ -453,6 +446,7 @@
 
         // Mutate the pointerInputChanges with the ones we modified.
         pointerInputChanges.putAll(relevantChanges)
+
         return true
     }
 
@@ -480,22 +474,16 @@
             return
         }
 
-        // TODO(b/158243568): For this attached check, and all of the following checks like this, we
-        //  should ideally be dispatching cancel to the sub tree with this node as it's root, and
-        //  we should remove the same sub tree from the tracker.  This will currently happen on
-        //  the next dispatch of events, but we shouldn't have to wait for another event.
-        if (pointerInputFilter.isAttached && this != dispatchingNode) {
+        if (this != dispatchingNode) {
             pointerInputFilter.onCustomEvent(event, downPass)
         }
 
-        if (pointerInputFilter.isAttached) {
-            // Call children recursively with the relevant changes.
-            children.forEach {
-                it.dispatchCustomEvent(event, relevantPointers, downPass, upPass, dispatchingNode)
-            }
+        // Call children recursively with the relevant changes.
+        children.forEach {
+            it.dispatchCustomEvent(event, relevantPointers, downPass, upPass, dispatchingNode)
         }
 
-        if (pointerInputFilter.isAttached && upPass != null && this != dispatchingNode) {
+        if (upPass != null && this != dispatchingNode) {
             pointerInputFilter.onCustomEvent(event, upPass)
         }
     }
diff --git a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
index b4e1d14..d560d95 100644
--- a/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
+++ b/ui/ui-core/src/test/java/androidx/ui/core/pointerinput/HitPathTrackerTest.kt
@@ -964,15 +964,15 @@
 
         // Arrange.
 
-        val pif1 = PointerInputFilterMock()
-        val pif2 = PointerInputFilterMock()
-        val pif3 = PointerInputFilterMock()
-        val pif4 = PointerInputFilterMock()
-        val pif5 = PointerInputFilterMock()
-        val pif6 = PointerInputFilterMock()
-        val pif7 = PointerInputFilterMock()
-        val pif8 = PointerInputFilterMock()
-        val pif9 = PointerInputFilterMock()
+        val pif1 = PointerInputFilterMock(isAttached = true)
+        val pif2 = PointerInputFilterMock(isAttached = true)
+        val pif3 = PointerInputFilterMock(isAttached = true)
+        val pif4 = PointerInputFilterMock(isAttached = true)
+        val pif5 = PointerInputFilterMock(isAttached = true)
+        val pif6 = PointerInputFilterMock(isAttached = true)
+        val pif7 = PointerInputFilterMock(isAttached = true)
+        val pif8 = PointerInputFilterMock(isAttached = true)
+        val pif9 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(1)
         val pointerId2 = PointerId(2)
@@ -1037,9 +1037,9 @@
     //  compositionRoot, root -> middle -> leaf
     @Test
     fun removeDetachedPointerInputFilters_1PathRootDetached_allRemovedAndCorrectCancels() {
-        val root = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root = PointerInputFilterMock(isAttached = false)
+        val middle = PointerInputFilterMock(isAttached = false)
+        val leaf = PointerInputFilterMock(isAttached = false)
 
         hitPathTracker.addHitPath(PointerId(0), listOf(root, middle, leaf))
 
@@ -1056,9 +1056,9 @@
     //  compositionRoot -> root, middle -> child
     @Test
     fun removeDetachedPointerInputFilters_1PathMiddleDetached_removesAndCancelsCorrect() {
-        val root = PointerInputFilterMock()
-        val middle = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val child = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root = PointerInputFilterMock(isAttached = true)
+        val middle = PointerInputFilterMock(isAttached = false)
+        val child = PointerInputFilterMock(isAttached = false)
 
         val pointerId = PointerId(0)
         hitPathTracker.addHitPath(pointerId, listOf(root, middle, child))
@@ -1082,9 +1082,9 @@
     //  compositionRoot -> root -> middle, leaf
     @Test
     fun removeDetachedPointerInputFilters_1PathLeafDetached_removesAndCancelsCorrect() {
-        val root = PointerInputFilterMock()
-        val middle = PointerInputFilterMock()
-        val leaf = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root = PointerInputFilterMock(isAttached = true)
+        val middle = PointerInputFilterMock(isAttached = true)
+        val leaf = PointerInputFilterMock(isAttached = false)
 
         val pointerId = PointerId(0)
         hitPathTracker.addHitPath(pointerId, listOf(root, middle, leaf))
@@ -1112,17 +1112,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots1Detached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock()
-        val leaf1 = PointerInputFilterMock()
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = true)
+        val leaf1 = PointerInputFilterMock(isAttached = true)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock()
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = true)
 
-        val root3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = false)
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1176,17 +1176,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots1MiddleDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock()
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = true)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock()
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1242,17 +1242,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots1LeafDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock()
-        val leaf1 = PointerInputFilterMock()
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = true)
+        val leaf1 = PointerInputFilterMock(isAttached = true)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock()
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1309,17 +1309,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots2Detached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = false)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock()
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = true)
 
-        val root3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = false)
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1366,17 +1366,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots2MiddlesDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock()
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1429,17 +1429,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots2LeafsDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock()
-        val leaf1 = PointerInputFilterMock()
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = true)
+        val leaf1 = PointerInputFilterMock(isAttached = true)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1492,17 +1492,17 @@
     //  compositionRoot, root3 -> middle3 -> leaf3
     @Test
     fun removeDetachedPointerInputFilters_3Roots3Detached_allRemovedAndCancelsCorrect() {
-        val root1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = false)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = false)
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = false)
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         hitPathTracker.addHitPath(PointerId(3), listOf(root1, middle1, leaf1))
         hitPathTracker.addHitPath(PointerId(5), listOf(root2, middle2, leaf2))
@@ -1536,17 +1536,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots3MiddlesDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1594,17 +1594,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3Roots3LeafsDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock()
-        val middle1 = PointerInputFilterMock()
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = true)
+        val middle1 = PointerInputFilterMock(isAttached = true)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1655,17 +1655,17 @@
     @Test
     fun removeDetachedPointerInputFilters_3RootsStaggeredDetached_removesAndCancelsCorrect() {
 
-        val root1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root1 = PointerInputFilterMock(isAttached = false)
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val root2 = PointerInputFilterMock()
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root2 = PointerInputFilterMock(isAttached = true)
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val root3 = PointerInputFilterMock()
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root3 = PointerInputFilterMock(isAttached = true)
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1711,16 +1711,16 @@
     //   middle3 -> leaf3
     @Test
     fun removeDetachedPointerInputFilters_rootWith3MiddlesDetached_allRemovedAndCorrectCancels() {
-        val root = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val root = PointerInputFilterMock(isAttached = false)
 
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         hitPathTracker.addHitPath(PointerId(3), listOf(root, middle1, leaf1))
         hitPathTracker.addHitPath(PointerId(5), listOf(root, middle2, leaf2))
@@ -1755,16 +1755,16 @@
     @Test
     fun removeDetachedPointerInputFilters_rootWith3Middles1Detached_removesAndCancelsCorrect() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle1 = PointerInputFilterMock()
-        val leaf1 = PointerInputFilterMock()
+        val middle1 = PointerInputFilterMock(isAttached = true)
+        val leaf1 = PointerInputFilterMock(isAttached = true)
 
-        val middle2 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock()
+        val middle2 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = true)
 
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1815,16 +1815,16 @@
     @Test
     fun removeDetachedPointerInputFilters_rootWith3Middles2Detached_removesAndCancelsCorrect() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val middle3 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock()
+        val middle3 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1871,16 +1871,16 @@
     @Test
     fun removeDetachedPointerInputFilters_rootWith3MiddlesAllDetached_allMiddlesRemoved() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle1 = PointerInputFilterMock(isAttached = false)
+        val leaf1 = PointerInputFilterMock(isAttached = false)
 
-        val middle2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle2 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
 
-        val middle3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val middle3 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1923,13 +1923,13 @@
     @Test
     fun removeDetachedPointerInputFilters_middleWith3Leafs1Detached_correctLeafRemoved() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle = PointerInputFilterMock()
+        val middle = PointerInputFilterMock(isAttached = true)
 
-        val leaf1 = PointerInputFilterMock()
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock()
+        val leaf1 = PointerInputFilterMock(isAttached = true)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = true)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -1975,13 +1975,13 @@
     @Test
     fun removeDetachedPointerInputFilters_middleWith3Leafs2Detached_correctLeafsRemoved() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle = PointerInputFilterMock()
+        val middle = PointerInputFilterMock(isAttached = true)
 
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock()
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val leaf1 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = true)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -2024,13 +2024,13 @@
     @Test
     fun removeDetachedPointerInputFilters_middleWith3LeafsAllDetached_allLeafsRemoved() {
 
-        val root = PointerInputFilterMock()
+        val root = PointerInputFilterMock(isAttached = true)
 
-        val middle = PointerInputFilterMock()
+        val middle = PointerInputFilterMock(isAttached = true)
 
-        val leaf1 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf2 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
-        val leaf3 = PointerInputFilterMock(layoutCoordinates = LayoutCoordinatesStub(false))
+        val leaf1 = PointerInputFilterMock(isAttached = false)
+        val leaf2 = PointerInputFilterMock(isAttached = false)
+        val leaf3 = PointerInputFilterMock(isAttached = false)
 
         val pointerId1 = PointerId(3)
         val pointerId2 = PointerId(5)
@@ -2913,440 +2913,6 @@
         }
     }
 
-    @Test
-    fun dispatchChanges_pifRemovesSelfDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovesSelfDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovesSelfDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovesSelfDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovesSelfDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchChanges_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-        val layoutCoordinates = LayoutCoordinatesStub(true)
-        val pif: PointerInputFilter = PointerInputFilterMock(
-            pointerInputHandler =
-            spy(StubPointerInputHandler { changes, pass, _ ->
-                if (pass == removalPass) {
-                    layoutCoordinates.isAttached = false
-                }
-                changes
-            }),
-            layoutCoordinates = layoutCoordinates
-        )
-        hitPathTracker.addHitPath(PointerId(13), listOf(pif))
-
-        hitPathTracker.dispatchChanges(listOf(down(13)))
-
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            if (!passedRemovalPass) {
-                verify(pif).onPointerInput(any(), eq(it), any())
-                passedRemovalPass = it == removalPass
-            } else {
-                verify(pif, never()).onPointerInput(any(), eq(it), any())
-            }
-        }
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByParentDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByParentDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByParentDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByParentDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByParentDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchChanges_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-        val childLayoutCoordinates = LayoutCoordinatesStub(true)
-        val parentPif: PointerInputFilter = PointerInputFilterMock(
-            pointerInputHandler =
-            spy(StubPointerInputHandler { changes, pass, _ ->
-                if (pass == removalPass) {
-                    childLayoutCoordinates.isAttached = false
-                }
-                changes
-            })
-        )
-        val childPif: PointerInputFilter = PointerInputFilterMock(
-            layoutCoordinates = childLayoutCoordinates
-        )
-        hitPathTracker.addHitPath(PointerId(13), listOf(parentPif, childPif))
-
-        hitPathTracker.dispatchChanges(listOf(down(13)))
-
-        val removalPassIsDown =
-            when (removalPass) {
-                PointerEventPass.InitialDown -> true
-                PointerEventPass.PreDown -> true
-                PointerEventPass.PostDown -> true
-                else -> false
-            }
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            passedRemovalPass = passedRemovalPass || removalPassIsDown && it == removalPass
-            if (!passedRemovalPass) {
-                verify(childPif).onPointerInput(any(), eq(it), any())
-            } else {
-                verify(childPif, never()).onPointerInput(any(), eq(it), any())
-            }
-            passedRemovalPass = passedRemovalPass || !removalPassIsDown && it == removalPass
-        }
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByChildDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByChildDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByChildDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByChildDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchChanges_pifRemovedByChildDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchChanges_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-        val parentLayoutCoordinates = LayoutCoordinatesStub(true)
-        val parentPif: PointerInputFilter = PointerInputFilterMock(
-            layoutCoordinates = parentLayoutCoordinates
-        )
-        val childPif: PointerInputFilter = PointerInputFilterMock(
-            pointerInputHandler =
-            spy(StubPointerInputHandler { changes, pass, _ ->
-                if (pass == removalPass) {
-                    parentLayoutCoordinates.isAttached = false
-                }
-                changes
-            })
-        )
-        hitPathTracker.addHitPath(PointerId(13), listOf(parentPif, childPif))
-
-        hitPathTracker.dispatchChanges(listOf(down(13)))
-
-        val removalPassIsDown =
-            when (removalPass) {
-                PointerEventPass.InitialDown -> true
-                PointerEventPass.PreDown -> true
-                PointerEventPass.PostDown -> true
-                else -> false
-            }
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            passedRemovalPass = passedRemovalPass || !removalPassIsDown && it == removalPass
-            if (!passedRemovalPass) {
-                verify(parentPif).onPointerInput(any(), eq(it), any())
-            } else {
-                verify(parentPif, never()).onPointerInput(any(), eq(it), any())
-            }
-            passedRemovalPass = passedRemovalPass || removalPassIsDown && it == removalPass
-        }
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovesSelfDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovesSelfDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovesSelfDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovesSelfDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovesSelfDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchCustomMessage_pifRemovesSelfDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-
-        lateinit var dispatcher: CustomEventDispatcher
-
-        val layoutCoordinates = LayoutCoordinatesStub(true)
-
-        val dispatchingPif = PointerInputFilterMock(initHandler = { dispatcher = it })
-        val receivingPif = PointerInputFilterMock(
-             _, pointerEventPass ->
-                if (pointerEventPass == removalPass) {
-                    layoutCoordinates.isAttached = false
-                }
-            },
-            layoutCoordinates = layoutCoordinates
-        )
-
-        hitPathTracker.addHitPath(PointerId(13), listOf(dispatchingPif, receivingPif))
-
-        dispatcher.dispatchCustomEvent(object : CustomEvent {})
-
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            if (!passedRemovalPass) {
-                verify(receivingPif).onCustomEvent(any(), eq(it))
-                passedRemovalPass = it == removalPass
-            } else {
-                verify(receivingPif, never()).onCustomEvent(any(), eq(it))
-            }
-        }
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByParentDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByParentDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByParentDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByParentDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByParentDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchCustomMessage_pifRemovedByParentDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-        lateinit var dispatcher: CustomEventDispatcher
-
-        val layoutCoordinates = LayoutCoordinatesStub(true)
-
-        val dispatchingPif = PointerInputFilterMock(initHandler = { dispatcher = it })
-        val parentPif = PointerInputFilterMock(
-             _, pointerEventPass ->
-                if (pointerEventPass == removalPass) {
-                    layoutCoordinates.isAttached = false
-                }
-            }
-        )
-        val childPif = PointerInputFilterMock(
-            layoutCoordinates = layoutCoordinates
-        )
-
-        hitPathTracker.addHitPath(PointerId(13), listOf(dispatchingPif, parentPif, childPif))
-
-        dispatcher.dispatchCustomEvent(object : CustomEvent {})
-
-        val removalPassIsDown =
-            when (removalPass) {
-                PointerEventPass.InitialDown -> true
-                PointerEventPass.PreDown -> true
-                PointerEventPass.PostDown -> true
-                else -> false
-            }
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            passedRemovalPass = passedRemovalPass || removalPassIsDown && it == removalPass
-            if (!passedRemovalPass) {
-                verify(childPif).onCustomEvent(any(), eq(it))
-            } else {
-                verify(childPif, never()).onCustomEvent(any(), eq(it))
-            }
-            passedRemovalPass = passedRemovalPass || !removalPassIsDown && it == removalPass
-        }
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByChildDuringInitialDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.InitialDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByChildDuringPreUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByChildDuringPreDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PreDown
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByChildDuringPostUp_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostUp
-        )
-    }
-
-    @Test
-    fun dispatchCustomMessage_pifRemovedByChildDuringPostDown_noPassesReceivedAfterwards() {
-        dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-            PointerEventPass.PostDown
-        )
-    }
-
-    private fun dispatchCustomMessage_pifRemovedByChildDuringDispatch_noPassesReceivedAfterwards(
-        removalPass: PointerEventPass
-    ) {
-        lateinit var dispatcher: CustomEventDispatcher
-
-        val layoutCoordinates = LayoutCoordinatesStub(true)
-
-        val dispatchingPif = PointerInputFilterMock(initHandler = { dispatcher = it })
-        val parentPif = PointerInputFilterMock(
-            layoutCoordinates = layoutCoordinates
-        )
-        val childPif = PointerInputFilterMock(
-             _, pointerEventPass ->
-                if (pointerEventPass == removalPass) {
-                    layoutCoordinates.isAttached = false
-                }
-            }
-        )
-
-        hitPathTracker.addHitPath(PointerId(13), listOf(dispatchingPif, parentPif, childPif))
-
-        dispatcher.dispatchCustomEvent(object : CustomEvent {})
-
-        val removalPassIsDown =
-            when (removalPass) {
-                PointerEventPass.InitialDown -> true
-                PointerEventPass.PreDown -> true
-                PointerEventPass.PostDown -> true
-                else -> false
-            }
-        var passedRemovalPass = false
-        PointerEventPass.values().forEach {
-            passedRemovalPass = passedRemovalPass || !removalPassIsDown && it == removalPass
-            if (!passedRemovalPass) {
-                verify(parentPif).onCustomEvent(any(), eq(it))
-            } else {
-                verify(parentPif, never()).onCustomEvent(any(), eq(it))
-            }
-            passedRemovalPass = passedRemovalPass || removalPassIsDown && it == removalPass
-        }
-    }
-
     private fun areEqual(actualNode: NodeParent, expectedNode: NodeParent): Boolean {
         var check = true
 
@@ -3394,23 +2960,20 @@
 fun PointerInputFilterMock(
     initHandler: (CustomEventDispatcher) -> Unit = mock(),
     pointerInputHandler: PointerInputHandler = spy(StubPointerInputHandler()),
-    layoutCoordinates: LayoutCoordinates = LayoutCoordinatesStub(true),
-    onCustomEvent: (CustomEvent, PointerEventPass) -> Unit = mock()
+    isAttached: Boolean = true
 ): PointerInputFilter =
     spy(
         PointerInputFilterStub(
             pointerInputHandler,
-            initHandler,
-            onCustomEvent
+            initHandler
         ).apply {
-            this.layoutCoordinates = layoutCoordinates
+            layoutCoordinates = LayoutCoordinatesStub(isAttached)
         }
     )
 
 open class PointerInputFilterStub(
     val pointerInputHandler: PointerInputHandler,
-    val initHandler: (CustomEventDispatcher) -> Unit,
-    val customEventHandler: (CustomEvent, PointerEventPass) -> Unit
+    val initHandler: (CustomEventDispatcher) -> Unit
 ) : PointerInputFilter() {
 
     override fun onPointerInput(
@@ -3427,15 +2990,13 @@
         initHandler(customEventDispatcher)
     }
 
-    override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {
-        customEventHandler(customEvent, pass)
-    }
+    override fun onCustomEvent(customEvent: CustomEvent, pass: PointerEventPass) {}
 }
 
 internal data class TestCustomEvent(val value: String) : CustomEvent
 
 class LayoutCoordinatesStub(
-    override var isAttached: Boolean = true
+    override val isAttached: Boolean = true
 ) : LayoutCoordinates {
 
     override val size: IntSize