# AwaitPointerEventScope

Artifact: [androidx.compose.ui:ui](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/input/pointer/SuspendingPointerInputFilter.kt+class:androidx.compose.ui.input.pointer.AwaitPointerEventScope) Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt#1.0.0) Common/AllAndroid/JVM
- Cmn

  ```
  @RestrictsSuspension
  interface AwaitPointerEventScope : Density
  ```

*** ** * ** ***

Receiver scope for awaiting pointer events in a call to `PointerInputScope.awaitPointerEventScope`.

This is a restricted suspension scope. Code in this scope is always called un-dispatched and may only suspend for calls to `awaitPointerEvent`. These functions resume synchronously and the caller may mutate the result **before** the next await call to affect the next stage of the input processing pipeline.

## Summary

| ### Public functions |
|---|---|---|
| `suspend PointerEvent` | `awaitPointerEvent(pass: PointerEventPass)` Suspend until a `PointerEvent` is reported to the specified input `pass`. | Cmn |
| `open suspend T` | `<T : Any?> withTimeout(timeMillis: Long, block: suspend AwaitPointerEventScope.() -> T)` Runs `block` and returns its results. | Cmn |
| `open suspend T?` | `<T : Any?> withTimeoutOrNull(timeMillis: Long, block: suspend AwaitPointerEventScope.() -> T)` Runs `block` and returns the result of `block` or `null` if `timeMillis` has passed before `timeMillis`. | Cmn |

| ### Public properties |
|---|---|---|
| `PointerEvent` | `currentEvent` The `PointerEvent` from the most recent touch event. | Cmn |
| `open Size` | `extendedTouchPadding` | Cmn |
| `IntSize` | `size` The measured size of the pointer input region. | Cmn |
| `ViewConfiguration` | `viewConfiguration` The `ViewConfiguration` used to tune gesture detectors. | Cmn |

| ### Extension functions |
|---|---|---|
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitDragOrCancellation(pointerId: PointerId)` Reads pointer input events until a drag is detected or all pointers are up. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitHorizontalDragOrCancellation( pointerId: PointerId )` Reads pointer input events until a horizontal drag is detected or all pointers are up. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitHorizontalPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, onPointerSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit )` Waits for horizontal drag motion to pass `pointerType`'s touch slop, using `pointerId` as the pointer to examine. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitHorizontalTouchSlopOrCancellation( pointerId: PointerId, onTouchSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit )` Waits for horizontal drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitLongPressOrCancellation( pointerId: PointerId )` Waits for a long press by examining `pointerId`. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitTouchSlopOrCancellation( pointerId: PointerId, onTouchSlopReached: (change: PointerInputChange, overSlop: Offset) -> Unit )` Waits for drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitVerticalDragOrCancellation( pointerId: PointerId )` Reads pointer input events until a vertical drag is detected or all pointers are up. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitVerticalPointerSlopOrCancellation( pointerId: PointerId, pointerType: PointerType, onPointerSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit )` Waits for vertical drag motion to pass `pointerType`'s touch slop using `pointerId` as the pointer to examine. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.awaitVerticalTouchSlopOrCancellation( pointerId: PointerId, onTouchSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit )` Waits for vertical drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. | Cmn |
| `suspend Boolean` | `AwaitPointerEventScope.drag( pointerId: PointerId, onDrag: (PointerInputChange) -> Unit )` Reads position change events for `pointerId` and calls `onDrag` for every change in position. | Cmn |
| `suspend Boolean` | `AwaitPointerEventScope.horizontalDrag( pointerId: PointerId, onDrag: (PointerInputChange) -> Unit )` Reads horizontal position change events for `pointerId` and calls `onDrag` for every change in position. | Cmn |
| `suspend Boolean` | `AwaitPointerEventScope.verticalDrag( pointerId: PointerId, onDrag: (PointerInputChange) -> Unit )` Reads vertical position change events for `pointerId` and calls `onDrag` for every change in position. | Cmn |
| `suspend PointerInputChange` | `AwaitPointerEventScope.awaitFirstDown( requireUnconsumed: Boolean, pass: PointerEventPass )` Reads events until the first down is received in the given `pass`. | Cmn |
| `suspend PointerInputChange?` | `AwaitPointerEventScope.waitForUpOrCancellation(pass: PointerEventPass)` Reads events in the given `pass` until all pointers are up or the gesture was canceled. | Cmn |

### Inherited functions

From [androidx.compose.ui.unit.Density](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density.md.txt) `open Int` `Dp.roundToPx()`

Convert `Dp` to `Int` by rounding
Cmn `open Int` `TextUnit.roundToPx()`

Convert Sp to `Int` by rounding
Cmn `open Dp` `Int.toDp()`

Convert an `Int` pixel value to `Dp`.
Cmn `open Dp` `Float.toDp()`

Convert a `Float` pixel value to a Dp
Cmn `open DpSize` `Size.toDpSize()`

Convert a `Size` to a `DpSize`.
Cmn `open Float` `Dp.toPx()`

Convert `Dp` to pixels.
Cmn `open Float` `TextUnit.toPx()`

Convert Sp to pixels.
Cmn `open Rect` `DpRect.toRect()`

Convert a `DpRect` to a `Rect`.
Cmn `open Size` `DpSize.toSize()`

Convert a `DpSize` to a `Size`.
Cmn `open TextUnit` `Int.toSp()`

Convert an `Int` pixel value to Sp.
Cmn `open TextUnit` `Float.toSp()`

Convert a `Float` pixel value to a Sp
Cmn From [androidx.compose.ui.unit.FontScaling](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling.md.txt) `Dp` `TextUnit.toDp()`

Convert Sp to `Dp`.
Cmn `TextUnit` `Dp.toSp()`

Convert `Dp` to Sp.
Cmn

### Inherited properties

From [androidx.compose.ui.unit.Density](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density.md.txt) `Float` `density`

The logical density of the display.
Cmn From [androidx.compose.ui.unit.FontScaling](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling.md.txt) `Float` `fontScale`

Current user preference for the scaling factor for fonts.
Cmn

## Public functions

### awaitPointerEvent

Cmn

```
suspend fun awaitPointerEvent(pass: PointerEventPass = PointerEventPass.Main): PointerEvent
```

Suspend until a `PointerEvent` is reported to the specified input `pass`. `pass` defaults to `PointerEventPass.Main`.

`awaitPointerEvent` resumes **synchronously** in the restricted suspension scope. This means that callers can react immediately to input after `awaitPointerEvent` returns and affect both the current frame and the next handler or phase of the input processing pipeline. Callers should mutate the returned `PointerEvent` before awaiting another event to consume aspects of the event before the next stage of input processing runs.

### withTimeout

Cmn

```
open suspend fun <T : Any?> withTimeout(timeMillis: Long, block: suspend AwaitPointerEventScope.() -> T): T
```

Runs `block` and returns its results. An `PointerEventTimeoutCancellationException` is thrown if `timeMillis` has passed before `block` completes.

### withTimeoutOrNull

Cmn

```
open suspend fun <T : Any?> withTimeoutOrNull(timeMillis: Long, block: suspend AwaitPointerEventScope.() -> T): T?
```

Runs `block` and returns the result of `block` or `null` if `timeMillis` has passed before `timeMillis`.

## Public properties

### currentEvent

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt#1.0.0)

```
val currentEvent: PointerEvent
```

The `PointerEvent` from the most recent touch event.

### extendedTouchPadding

Cmn Added in [1.1.0](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt#1.1.0)

```
open val extendedTouchPadding: Size
```

### size

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt#1.0.0)

```
val size: IntSize
```

The measured size of the pointer input region. Input events will be reported with a coordinate space of (0, 0) to (size.width, size,height) as the input region, with (0, 0) indicating the upper left corner.

### viewConfiguration

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui.md.txt#1.0.0)

```
val viewConfiguration: ViewConfiguration
```

The `ViewConfiguration` used to tune gesture detectors.

## Extension functions

### AwaitPointerEventScope.awaitDragOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitDragOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitDragOrCancellation(pointerId: PointerId): PointerInputChange?
```

Reads pointer input events until a drag is detected or all pointers are up. When the final pointer is raised, the up event is returned. When a drag event is detected, the drag change will be returned. Note that if `pointerId` has been raised, another pointer that is down will be used, if available, so the returned `PointerInputChange.id` may differ from `pointerId`. If the position change in the any direction has been consumed by the `PointerEventPass.Main` pass, then the drag is considered canceled and `null` is returned. If `pointerId` is not down when `awaitDragOrCancellation` is called, then `null` is returned.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitDragOrCancellation
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var size by remember { mutableStateOf(Size.Zero) }
Box(Modifier.fillMaxSize().onSizeChanged { size = it.toSize() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .size(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitTouchSlopOrCancellation(down.id) { change, over ->
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + over
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            change.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    while (change != null && change.pressed) {
                        change = awaitDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + change.positionChange()
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            change.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    }
                }
            }
    )
}
```

| See also |
|---|---|
| `awaitVerticalDragOrCancellation` |   |
| `awaitHorizontalDragOrCancellation` |   |
| `drag` |   |

### AwaitPointerEventScope.awaitHorizontalDragOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitHorizontalDragOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitHorizontalDragOrCancellation(
    pointerId: PointerId
): PointerInputChange?
```

Reads pointer input events until a horizontal drag is detected or all pointers are up. When the final pointer is raised, the up event is returned. When a drag event is detected, the drag change will be returned. Note that if `pointerId` has been raised, another pointer that is down will be used, if available, so the returned `PointerInputChange.id` may differ from `pointerId`. If the position change has been consumed by the `PointerEventPass.Main` pass, then the drag is considered canceled and `null` is returned. If `pointerId` is not down when `awaitHorizontalDragOrCancellation` is called, then `null` is returned.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitHorizontalDragOrCancellation
import androidx.compose.foundation.gestures.awaitHorizontalTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var width by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { width = it.width.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxHeight()
            .width(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitHorizontalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalX = offsetX.value
                            val newValue = (originalX + over).coerceIn(0f, width - 50.dp.toPx())
                            change.consume()
                            offsetX.value = newValue
                        }
                    while (change != null && change.pressed) {
                        change = awaitHorizontalDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val originalX = offsetX.value
                            val newValue =
                                (originalX + change.positionChange().x).coerceIn(
                                    0f,
                                    width - 50.dp.toPx(),
                                )
                            change.consume()
                            offsetX.value = newValue
                        }
                    }
                }
            }
    )
}
```

| See also |
|---|---|
| `horizontalDrag` |   |
| `awaitVerticalDragOrCancellation` |   |
| `awaitDragOrCancellation` |   |

### AwaitPointerEventScope.awaitHorizontalPointerSlopOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitHorizontalPointerSlopOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitHorizontalPointerSlopOrCancellation(
    pointerId: PointerId,
    pointerType: PointerType,
    onPointerSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit
): PointerInputChange?
```

Waits for horizontal drag motion to pass `pointerType`'s touch slop, using `pointerId` as the pointer to examine. If `pointerId` is raised, another pointer from those that are down will be chosen to lead the gesture, and if none are down, `null` is returned. If `pointerId` is not down when `awaitHorizontalPointerSlopOrCancellation` is called, then `null` is returned.

`onPointerSlopReached` is called after `pointerType`'s touch slop motion in the horizontal direction with the change that caused the motion beyond touch slop and the pixels beyond touch slop. `onPointerSlopReached` should consume the position change if it accepts the motion. If it does, then the method returns that `PointerInputChange`. If not, touch slop detection will continue.

| Returns |
|---|---|
| `PointerInputChange?` | The `PointerInputChange` that was consumed in `onPointerSlopReached` or `null` if all pointers are raised before touch slop is detected or another gesture consumed the position change. |

| See also |
|---|---|
| `awaitVerticalTouchSlopOrCancellation` |   |
| `awaitTouchSlopOrCancellation` |   |

### AwaitPointerEventScope.awaitHorizontalTouchSlopOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitHorizontalTouchSlopOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitHorizontalTouchSlopOrCancellation(
    pointerId: PointerId,
    onTouchSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit
): PointerInputChange?
```

Waits for horizontal drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. If `pointerId` is raised, another pointer from those that are down will be chosen to lead the gesture, and if none are down, `null` is returned.

`onTouchSlopReached` is called after `ViewConfiguration.touchSlop` motion in the horizontal direction with the change that caused the motion beyond touch slop and the pixels beyond touch slop. `onTouchSlopReached` should consume the position change if it accepts the motion. If it does, then the method returns that `PointerInputChange`. If not, touch slop detection will continue. If `pointerId` is not down when `awaitHorizontalTouchSlopOrCancellation` is called, then `null` is returned.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitHorizontalDragOrCancellation
import androidx.compose.foundation.gestures.awaitHorizontalTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var width by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { width = it.width.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxHeight()
            .width(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitHorizontalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalX = offsetX.value
                            val newValue = (originalX + over).coerceIn(0f, width - 50.dp.toPx())
                            change.consume()
                            offsetX.value = newValue
                        }
                    while (change != null && change.pressed) {
                        change = awaitHorizontalDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val originalX = offsetX.value
                            val newValue =
                                (originalX + change.positionChange().x).coerceIn(
                                    0f,
                                    width - 50.dp.toPx(),
                                )
                            change.consume()
                            offsetX.value = newValue
                        }
                    }
                }
            }
    )
}
```

| Returns |
|---|---|
| `PointerInputChange?` | The `PointerInputChange` that was consumed in `onTouchSlopReached` or `null` if all pointers are raised before touch slop is detected or another gesture consumed the position change. Example Usage: |

| See also |
|---|---|
| `awaitVerticalTouchSlopOrCancellation` |   |
| `awaitTouchSlopOrCancellation` |   |

### AwaitPointerEventScope.awaitLongPressOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitLongPressOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitLongPressOrCancellation(
    pointerId: PointerId
): PointerInputChange?
```

Waits for a long press by examining `pointerId`.

If that `pointerId` is raised (that is, the user lifts their finger), but another finger (`PointerId`) is down at that time, another pointer will be chosen as the lead for the gesture, and if none are down, `null` is returned.

```kotlin
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitLongPressOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.dp

var count by remember { mutableStateOf(0) }

Column {
    Text("Long Press to increase count. Long Press count: $count")
    Box(
        Modifier.fillMaxSize()
            .wrapContentSize(Alignment.Center)
            .size(192.dp)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown(requireUnconsumed = false)
                    awaitLongPressOrCancellation(down.id)?.let { count++ }
                }
            }
            .clipToBounds()
            .background(Color.Blue)
            .border(BorderStroke(2.dp, Color.Black))
    )
}
```

| Returns |
|---|---|
| `PointerInputChange?` | The latest `PointerInputChange` associated with a long press or `null` if all pointers are raised before a long press is detected or another gesture consumed the change. Example Usage: |

### AwaitPointerEventScope.awaitTouchSlopOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitTouchSlopOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitTouchSlopOrCancellation(
    pointerId: PointerId,
    onTouchSlopReached: (change: PointerInputChange, overSlop: Offset) -> Unit
): PointerInputChange?
```

Waits for drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. If `pointerId` is raised, another pointer from those that are down will be chosen to lead the gesture, and if none are down, `null` is returned. If `pointerId` is not down when `awaitTouchSlopOrCancellation` is called, then `null` is returned.

`onTouchSlopReached` is called after `ViewConfiguration.touchSlop` motion in the any direction with the change that caused the motion beyond touch slop and the `Offset` beyond touch slop that has passed. `onTouchSlopReached` should consume the position change if it accepts the motion. If it does, then the method returns that `PointerInputChange`. If not, touch slop detection will continue.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitDragOrCancellation
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var size by remember { mutableStateOf(Size.Zero) }
Box(Modifier.fillMaxSize().onSizeChanged { size = it.toSize() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .size(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitTouchSlopOrCancellation(down.id) { change, over ->
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + over
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            change.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    while (change != null && change.pressed) {
                        change = awaitDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + change.positionChange()
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            change.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    }
                }
            }
    )
}
```

| Returns |
|---|---|
| `PointerInputChange?` | The `PointerInputChange` that was consumed in `onTouchSlopReached` or `null` if all pointers are raised before touch slop is detected or another gesture consumed the position change. Example Usage: |

| See also |
|---|---|
| `awaitHorizontalTouchSlopOrCancellation` |   |
| `awaitVerticalTouchSlopOrCancellation` |   |

### AwaitPointerEventScope.awaitVerticalDragOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitVerticalDragOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitVerticalDragOrCancellation(
    pointerId: PointerId
): PointerInputChange?
```

Reads pointer input events until a vertical drag is detected or all pointers are up. When the final pointer is raised, the up event is returned. When a drag event is detected, the drag change will be returned. Note that if `pointerId` has been raised, another pointer that is down will be used, if available, so the returned `PointerInputChange.id` may differ from `pointerId`. If the position change has been consumed by the `PointerEventPass.Main` pass, then the drag is considered canceled and `null` is returned. If `pointerId` is not down when `awaitVerticalDragOrCancellation` is called, then `null` is returned.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitVerticalDragOrCancellation
import androidx.compose.foundation.gestures.awaitVerticalTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var height by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { height = it.height.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxWidth()
            .height(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitVerticalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + over).coerceIn(0f, height - 50.dp.toPx())
                            change.consume()
                            offsetY.value = newValue
                        }
                    while (change != null && change.pressed) {
                        change = awaitVerticalDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + change.positionChange().y).coerceIn(
                                    0f,
                                    height - 50.dp.toPx(),
                                )
                            change.consume()
                            offsetY.value = newValue
                        }
                    }
                }
            }
    )
}
```

| See also |
|---|---|
| `awaitHorizontalDragOrCancellation` |   |
| `awaitDragOrCancellation` |   |
| `verticalDrag` |   |

### AwaitPointerEventScope.awaitVerticalPointerSlopOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitVerticalPointerSlopOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitVerticalPointerSlopOrCancellation(
    pointerId: PointerId,
    pointerType: PointerType,
    onPointerSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit
): PointerInputChange?
```

Waits for vertical drag motion to pass `pointerType`'s touch slop using `pointerId` as the pointer to examine. If `pointerId` is raised, another pointer from those that are down will be chosen to lead the gesture, and if none are down, `null` is returned. If `pointerId` is not down when `awaitVerticalPointerSlopOrCancellation` is called, then `null` is returned.

`onPointerSlopReached` is called after `ViewConfiguration.touchSlop` motion in the vertical direction with the change that caused the motion beyond touch slop and the pixels beyond touch slop. `onPointerSlopReached` should consume the position change if it accepts the motion. If it does, then the method returns that `PointerInputChange`. If not, touch slop detection will continue.

| Returns |
|---|---|
| `PointerInputChange?` | The `PointerInputChange` that was consumed in `onPointerSlopReached` or `null` if all pointers are raised before touch slop is detected or another gesture consumed the position change. |

| See also |
|---|---|
| `awaitHorizontalTouchSlopOrCancellation` |   |
| `awaitTouchSlopOrCancellation` |   |

### AwaitPointerEventScope.awaitVerticalTouchSlopOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:awaitVerticalTouchSlopOrCancellation)

```
suspend fun AwaitPointerEventScope.awaitVerticalTouchSlopOrCancellation(
    pointerId: PointerId,
    onTouchSlopReached: (change: PointerInputChange, overSlop: Float) -> Unit
): PointerInputChange?
```

Waits for vertical drag motion to pass `touch slop`, using `pointerId` as the pointer to examine. If `pointerId` is raised, another pointer from those that are down will be chosen to lead the gesture, and if none are down, `null` is returned. If `pointerId` is not down when `awaitVerticalTouchSlopOrCancellation` is called, then `null` is returned.

`onTouchSlopReached` is called after `ViewConfiguration.touchSlop` motion in the vertical direction with the change that caused the motion beyond touch slop and the pixels beyond touch slop. `onTouchSlopReached` should consume the position change if it accepts the motion. If it does, then the method returns that `PointerInputChange`. If not, touch slop detection will continue.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitVerticalDragOrCancellation
import androidx.compose.foundation.gestures.awaitVerticalTouchSlopOrCancellation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var height by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { height = it.height.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxWidth()
            .height(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    var change =
                        awaitVerticalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + over).coerceIn(0f, height - 50.dp.toPx())
                            change.consume()
                            offsetY.value = newValue
                        }
                    while (change != null && change.pressed) {
                        change = awaitVerticalDragOrCancellation(change.id)
                        if (change != null && change.pressed) {
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + change.positionChange().y).coerceIn(
                                    0f,
                                    height - 50.dp.toPx(),
                                )
                            change.consume()
                            offsetY.value = newValue
                        }
                    }
                }
            }
    )
}
```

| Returns |
|---|---|
| `PointerInputChange?` | The `PointerInputChange` that was consumed in `onTouchSlopReached` or `null` if all pointers are raised before touch slop is detected or another gesture consumed the position change. Example Usage: |

| See also |
|---|---|
| `awaitHorizontalTouchSlopOrCancellation` |   |
| `awaitTouchSlopOrCancellation` |   |

### AwaitPointerEventScope.drag

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:drag)

```
suspend fun AwaitPointerEventScope.drag(
    pointerId: PointerId,
    onDrag: (PointerInputChange) -> Unit
): Boolean
```

Reads position change events for `pointerId` and calls `onDrag` for every change in position. If `pointerId` is raised, a new pointer is chosen from those that are down and if none exist, the method returns. This does not wait for touch slop.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitTouchSlopOrCancellation
import androidx.compose.foundation.gestures.drag
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var size by remember { mutableStateOf(Size.Zero) }
Box(Modifier.fillMaxSize().onSizeChanged { size = it.toSize() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .size(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    val change =
                        awaitTouchSlopOrCancellation(down.id) { change, over ->
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + over
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            change.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    if (change != null) {
                        drag(change.id) {
                            val original = Offset(offsetX.value, offsetY.value)
                            val summed = original + it.positionChange()
                            val newValue =
                                Offset(
                                    x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                                    y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                                )
                            it.consume()
                            offsetX.value = newValue.x
                            offsetY.value = newValue.y
                        }
                    }
                }
            }
    )
}
```

| Returns |
|---|---|
| `Boolean` | `true` if the drag completed normally or `false` if the drag motion was canceled by another gesture detector consuming position change events. Example Usage: |

| See also |
|---|---|
| `awaitTouchSlopOrCancellation` |   |
| `awaitDragOrCancellation` |   |
| `horizontalDrag` |   |
| `verticalDrag` |   |

### AwaitPointerEventScope.horizontalDrag

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:horizontalDrag)

```
suspend fun AwaitPointerEventScope.horizontalDrag(
    pointerId: PointerId,
    onDrag: (PointerInputChange) -> Unit
): Boolean
```

Reads horizontal position change events for `pointerId` and calls `onDrag` for every change in position. If `pointerId` is raised, a new pointer is chosen from those that are down and if none exist, the method returns. This does not wait for touch slop.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitHorizontalTouchSlopOrCancellation
import androidx.compose.foundation.gestures.horizontalDrag
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var width by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { width = it.width.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxHeight()
            .width(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    val change =
                        awaitHorizontalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalX = offsetX.value
                            val newValue = (originalX + over).coerceIn(0f, width - 50.dp.toPx())
                            change.consume()
                            offsetX.value = newValue
                        }
                    if (change != null) {
                        horizontalDrag(change.id) {
                            val originalX = offsetX.value
                            val newValue =
                                (originalX + it.positionChange().x).coerceIn(
                                    0f,
                                    width - 50.dp.toPx(),
                                )
                            it.consume()
                            offsetX.value = newValue
                        }
                    }
                }
            }
    )
}
```

| See also |
|---|---|
| `awaitHorizontalTouchSlopOrCancellation` |   |
| `awaitDragOrCancellation` |   |
| `verticalDrag` |   |
| `drag` |   |

### AwaitPointerEventScope.verticalDrag

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/DragGestureDetector.kt+function:verticalDrag)

```
suspend fun AwaitPointerEventScope.verticalDrag(
    pointerId: PointerId,
    onDrag: (PointerInputChange) -> Unit
): Boolean
```

Reads vertical position change events for `pointerId` and calls `onDrag` for every change in position. If `pointerId` is raised, a new pointer is chosen from those that are down and if none exist, the method returns. This does not wait for touch slop

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.awaitVerticalTouchSlopOrCancellation
import androidx.compose.foundation.gestures.verticalDrag
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChange
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

val offsetX = remember { mutableStateOf(0f) }
val offsetY = remember { mutableStateOf(0f) }
var height by remember { mutableStateOf(0f) }
Box(Modifier.fillMaxSize().onSizeChanged { height = it.height.toFloat() }) {
    Box(
        Modifier.offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
            .fillMaxWidth()
            .height(50.dp)
            .background(Color.Blue)
            .pointerInput(Unit) {
                awaitEachGesture {
                    val down = awaitFirstDown()
                    val change =
                        awaitVerticalTouchSlopOrCancellation(down.id) { change, over ->
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + over).coerceIn(0f, height - 50.dp.toPx())
                            change.consume()
                            offsetY.value = newValue
                        }
                    if (change != null) {
                        verticalDrag(change.id) {
                            val originalY = offsetY.value
                            val newValue =
                                (originalY + it.positionChange().y).coerceIn(
                                    0f,
                                    height - 50.dp.toPx(),
                                )
                            it.consume()
                            offsetY.value = newValue
                        }
                    }
                }
            }
    )
}
```

| Returns |
|---|---|
| `Boolean` | `true` if the vertical drag completed normally or `false` if the drag motion was canceled by another gesture detector consuming position change events. Example Usage: |

| See also |
|---|---|
| `awaitVerticalTouchSlopOrCancellation` |   |
| `awaitVerticalDragOrCancellation` |   |
| `horizontalDrag` |   |
| `drag` |   |

### AwaitPointerEventScope.awaitFirstDown

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/TapGestureDetector.kt+function:awaitFirstDown)

```
suspend fun AwaitPointerEventScope.awaitFirstDown(
    requireUnconsumed: Boolean = true,
    pass: PointerEventPass = PointerEventPass.Main
): PointerInputChange
```

Reads events until the first down is received in the given `pass`. If `requireUnconsumed` is `true` and the first down is already consumed in the pass, that gesture is ignored.

### AwaitPointerEventScope.waitForUpOrCancellation

Cmn Artifact: [androidx.compose.foundation:foundation](https://developer.android.com/jetpack/androidx/releases/compose-foundation.md.txt) [View Source](https://cs.android.com/search?q=file:androidx/compose/foundation/gestures/TapGestureDetector.kt+function:waitForUpOrCancellation)

```
suspend fun AwaitPointerEventScope.waitForUpOrCancellation(
    pass: PointerEventPass = PointerEventPass.Main
): PointerInputChange?
```

Reads events in the given `pass` until all pointers are up or the gesture was canceled. The gesture is considered canceled when a pointer leaves the event region, a position change has been consumed or a pointer down change event was already consumed in the given pass. If the gesture was not canceled, the final up change is returned or `null` if the event was canceled.