# PointerInputScope

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

  ```
  interface PointerInputScope : Density
  ```
Known direct subclasses [DragAndDropSourceScope](https://developer.android.com/reference/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSourceScope)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSourceScope` | **This interface is deprecated.** Replaced by a callback for obtain a transfer data,start detection is performed by Compose itself |

*** ** * ** ***

Receiver scope for `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/pointerInput.modifier#(androidx.compose.ui.Modifier).pointerInput(kotlin.coroutines.SuspendFunction1)` that permits `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)`.

## Summary

| ### Public functions |
|---|---|---|
| `suspend R` | `<R : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?> https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)(block: suspend https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/AwaitPointerEventScope.() -> R)` Suspend and install a pointer input `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)` that can await input events and respond to them immediately. | Cmn |

| ### Public properties |
|---|---|---|
| `open https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Size` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#extendedTouchPadding()` The additional space applied to each side of the layout area when the layout is smaller than `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`. | Cmn |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#interceptOutOfBoundsChildEvents()` Intercept pointer input that children receive even if the pointer is out of bounds. | Cmn |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/IntSize` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#size()` The measured size of the pointer input region. | Cmn |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#viewConfiguration()` The `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration` used to tune gesture detectors. | Cmn |

| ### Extension functions |
|---|---|---|
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)( onDragStart: (https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragEnd: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Gesture detector that waits for pointer down and touch slop in any direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)( orientationLock: https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/Orientation?, onDragStart: (down: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, slopTriggerChange: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, overSlopOffset: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragEnd: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, shouldAwaitTouchSlop: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html, onDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` A Gesture detector that waits for pointer down and touch slop in the direction specified by `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)( onDragStart: (https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragEnd: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Gesture detector that waits for pointer down and long press, after which it calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)( onDragStart: (https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragEnd: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onHorizontalDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Gesture detector that waits for pointer down and touch slop in the horizontal direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each horizontal drag event. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)( onDragStart: (https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragEnd: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onVerticalDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` Gesture detector that waits for pointer down and touch slop in the vertical direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each vertical drag event. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).awaitEachGesture(kotlin.coroutines.SuspendFunction1)(block: suspend https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/AwaitPointerEventScope.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` Repeatedly calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).awaitEachGesture(kotlin.coroutines.SuspendFunction1)` to handle gestures. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.[forEachGesture](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).forEachGesture(kotlin.coroutines.SuspendFunction1))(block: suspend https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.() -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)` **This function is deprecated.** Use awaitEachGesture instead. forEachGesture() can drop events between gestures. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)( onDoubleTap: ((https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, onLongPress: ((https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)?, onPress: suspend https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/PressGestureScope.(https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html, onTap: ((https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html)? )` Detects tap, double-tap, and long press gestures and calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, respectively, when detected. | Cmn |
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope.https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).detectTransformGestures(kotlin.Boolean,kotlin.Function4)( panZoomLock: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html, onGesture: (centroid: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset, pan: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset, zoom: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html, rotation: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html )` A gesture detector for rotation, panning, and zoom. | Cmn |

### Inherited functions

From [androidx.compose.ui.unit.Density](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density) `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.Dp).roundToPx()()`

Convert `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` to `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` by rounding
Cmn `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.TextUnit).roundToPx()()`

Convert Sp to `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` by rounding
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(kotlin.Int).toDp()()`

Convert an `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` pixel value to `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp`.
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(kotlin.Float).toDp()()`

Convert a `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` pixel value to a Dp
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpSize` `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Size.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.geometry.Size).toDpSize()()`

Convert a `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Size` to a `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpSize`.
Cmn `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.Dp).toPx()()`

Convert `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` to pixels.
Cmn `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.TextUnit).toPx()()`

Convert Sp to pixels.
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Rect` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpRect.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.DpRect).toRect()()`

Convert a `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpRect` to a `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Rect`.
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Size` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpSize.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.DpSize).toSize()()`

Convert a `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/DpSize` to a `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Size`.
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit` `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(kotlin.Int).toSp()()`

Convert an `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` pixel value to Sp.
Cmn `open https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit` `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(kotlin.Float).toSp()()`

Convert a `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` pixel value to a Sp
Cmn From [androidx.compose.ui.unit.FontScaling](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling) `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling#(androidx.compose.ui.unit.TextUnit).toDp()()`

Convert Sp to `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp`.
Cmn `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/TextUnit` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp.https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling#(androidx.compose.ui.unit.Dp).toSp()()`

Convert `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Dp` to Sp.
Cmn

### Inherited properties

From [androidx.compose.ui.unit.Density](https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density) `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#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) `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-float/index.html` `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/FontScaling#fontScale()`

Current user preference for the scaling factor for fonts.
Cmn

## Public functions

### awaitPointerEventScope

Cmn

```
suspend fun <R : Any?> awaitPointerEventScope(block: suspend AwaitPointerEventScope.() -> R): R
```

Suspend and install a pointer input `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)` that can await input events and respond to them immediately. A call to `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)` will resume with `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)`'s result after it completes.

More than one `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)` can run concurrently in the same `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope` by using `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/index.html`. `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)`s are dispatched to in the order in which they were installed.

## Public properties

### extendedTouchPadding

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

```
open val extendedTouchPadding: Size
```

The additional space applied to each side of the layout area when the layout is smaller than `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

### interceptOutOfBoundsChildEvents

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

```
open var interceptOutOfBoundsChildEvents: Boolean
```

Intercept pointer input that children receive even if the pointer is out of bounds.

If `true`, and a child has been moved out of this layout and receives an event, this will receive that event. If `false`, a child receiving pointer input outside of the bounds of this layout will not trigger any events in this.

### size

Cmn Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#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#1.0.0)

```
val viewConfiguration: ViewConfiguration
```

The `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration` used to tune gesture detectors.

## Extension functions

### PointerInputScope.detectDragGestures

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

```
suspend fun PointerInputScope.detectDragGestures(
    onDragStart: (Offset) -> Unit = {},
    onDragEnd: () -> Unit = {},
    onDragCancel: () -> Unit = {},
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
): Unit
```

Gesture detector that waits for pointer down and touch slop in any direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event. It follows the touch slop detection of `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)` but will consume the position change automatically once the touch slop has been crossed. @see `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` with orientation lock for a fuller set of capabilities.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` called when the touch slop has been passed and includes an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the last known pointer position relative to the containing element. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called after all pointers are up and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called if another gesture has consumed pointer input, canceling this gesture.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
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.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) {
                detectDragGestures { _, dragAmount ->
                    val original = Offset(offsetX.value, offsetY.value)
                    val summed = original + dragAmount
                    val newValue =
                        Offset(
                            x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                            y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                        )
                    offsetX.value = newValue.x
                    offsetY.value = newValue.y
                }
            }
    )
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` | to detect gestures after long press |

### PointerInputScope.detectDragGestures

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

```
suspend fun PointerInputScope.detectDragGestures(
    orientationLock: Orientation?,
    onDragStart: (down: PointerInputChange, slopTriggerChange: PointerInputChange, overSlopOffset: Offset) -> Unit = { _, _, _ ->
        },
    onDragEnd: (change: PointerInputChange) -> Unit = {},
    onDragCancel: () -> Unit = {},
    shouldAwaitTouchSlop: () -> Boolean = { true },
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
): Unit
```

A Gesture detector that waits for pointer down and touch slop in the direction specified by `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event. It follows the touch slop detection of `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)` but will consume the position change automatically once the touch slop has been crossed, the amount of drag over the touch slop is reported as the first drag event `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` after the slop is crossed. If `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` returns true the touch slop recognition phase will be ignored and the drag gesture will be recognized immediately.The first `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` in this case will report an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset#Zero()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called when the touch slop has been passed and includes an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the last known pointer position relative to the containing element as well as the initial down event that triggered this gesture detection cycle. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called after all pointers are up with the event change of the up event and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called if another gesture has consumed pointer input, canceling this gesture.

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
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.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) {
                detectDragGestures { _, dragAmount ->
                    val original = Offset(offsetX.value, offsetY.value)
                    val summed = original + dragAmount
                    val newValue =
                        Offset(
                            x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                            y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                        )
                    offsetX.value = newValue.x
                    offsetY.value = newValue.y
                }
            }
    )
}
```

| Parameters |
|---|---|
| `orientationLock: https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/Orientation?` | Optionally locks detection to this orientation, this means, when this is provided, touch slop detection and drag event detection will be conditioned to the given orientation axis. `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` will still dispatch events on with information in both axis, but if orientation lock is provided, only events that happen on the given orientation will be considered. This also means that if no event in the orientation is detected we will not dispatch `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(androidx.compose.foundation.gestures.Orientation,kotlin.Function3,kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` calls. If no value is provided (i.e. null) touch slop and drag detection will happen on an "any" orientation basis, that is, touch slop will be detected if crossed in either direction and drag events will be dispatched if present in either direction. |
| `onDragStart: (down: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, slopTriggerChange: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, overSlopOffset: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html = { _, _, _ -> }` | A lambda to be called when the drag gesture starts, it contains information about the last known `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange` relative to the containing element and the post slop delta, slopTriggerChange. It also contains information about the down event where this gesture started and the overSlopOffset. |
| `onDragEnd: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html = {}` | A lambda to be called when the gesture ends. It contains information about the up `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange` that finished the gesture. |
| `onDragCancel: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html = {}` | A lambda to be called when the gesture is cancelled either by an error or when it was consumed. |
| `shouldAwaitTouchSlop: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = { true }` | Indicates if touch slop detection should be skipped. |
| `onDrag: (change: https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange, dragAmount: https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset) -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | A lambda to be called for each delta event in the gesture. It contains information about the `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputChange` and the movement offset. Example Usage: |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` | to detect gestures after long press |

### PointerInputScope.detectDragGesturesAfterLongPress

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

```
suspend fun PointerInputScope.detectDragGesturesAfterLongPress(
    onDragStart: (Offset) -> Unit = {},
    onDragEnd: () -> Unit = {},
    onDragCancel: () -> Unit = {},
    onDrag: (change: PointerInputChange, dragAmount: Offset) -> Unit
): Unit
```

Gesture detector that waits for pointer down and long press, after which it calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each drag event.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` called when a long press is detected and includes an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the last known pointer position relative to the containing element. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called after all pointers are up and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGesturesAfterLongPress(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called if another gesture has consumed pointer input, canceling this gesture. This function will automatically consume all the position change after the long press.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress
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.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) {
                detectDragGesturesAfterLongPress { _, dragAmount ->
                    val original = Offset(offsetX.value, offsetY.value)
                    val summed = original + dragAmount
                    val newValue =
                        Offset(
                            x = summed.x.coerceIn(0f, size.width - 50.dp.toPx()),
                            y = summed.y.coerceIn(0f, size.height - 50.dp.toPx()),
                        )
                    offsetX.value = newValue.x
                    offsetY.value = newValue.y
                }
            }
    )
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |

### PointerInputScope.detectHorizontalDragGestures

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

```
suspend fun PointerInputScope.detectHorizontalDragGestures(
    onDragStart: (Offset) -> Unit = {},
    onDragEnd: () -> Unit = {},
    onDragCancel: () -> Unit = {},
    onHorizontalDrag: (change: PointerInputChange, dragAmount: Float) -> Unit
): Unit
```

Gesture detector that waits for pointer down and touch slop in the horizontal direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each horizontal drag event. It follows the touch slop detection of `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitHorizontalTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)`, but will consume the position change automatically once the touch slop has been crossed.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` called when the touch slop has been passed and includes an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the last known pointer position relative to the containing element. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called after all pointers are up and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called if another gesture has consumed pointer input, canceling this gesture.

This gesture detector will coordinate with `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitVerticalTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)` to ensure only vertical or horizontal dragging is locked, but not both.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.gestures.drag
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.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) {
                detectHorizontalDragGestures { _, dragAmount ->
                    val originalX = offsetX.value
                    val newValue = (originalX + dragAmount).coerceIn(0f, width - 50.dp.toPx())
                    offsetX.value = newValue
                }
            }
    )
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |

### PointerInputScope.detectVerticalDragGestures

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

```
suspend fun PointerInputScope.detectVerticalDragGestures(
    onDragStart: (Offset) -> Unit = {},
    onDragEnd: () -> Unit = {},
    onDragCancel: () -> Unit = {},
    onVerticalDrag: (change: PointerInputChange, dragAmount: Float) -> Unit
): Unit
```

Gesture detector that waits for pointer down and touch slop in the vertical direction and then calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` for each vertical drag event. It follows the touch slop detection of `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitVerticalTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)`, but will consume the position change automatically once the touch slop has been crossed.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` called when the touch slop has been passed and includes an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the last known pointer position relative to the containing element. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called after all pointers are up and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectVerticalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` is called if another gesture has consumed pointer input, canceling this gesture.

This gesture detector will coordinate with `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.AwaitPointerEventScope).awaitHorizontalTouchSlopOrCancellation(androidx.compose.ui.input.pointer.PointerId,kotlin.Function2)` to ensure only vertical or horizontal dragging is locked, but not both.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectVerticalDragGestures
import androidx.compose.foundation.gestures.drag
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.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) {
                detectVerticalDragGestures { _, dragAmount ->
                    val originalY = offsetY.value
                    val newValue = (originalY + dragAmount).coerceIn(0f, height - 50.dp.toPx())
                    offsetY.value = newValue
                }
            }
    )
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectHorizontalDragGestures(kotlin.Function1,kotlin.Function0,kotlin.Function0,kotlin.Function2)` |   |

### PointerInputScope.awaitEachGesture

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

```
suspend fun PointerInputScope.awaitEachGesture(block: suspend AwaitPointerEventScope.() -> Unit): Unit
```

Repeatedly calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).awaitEachGesture(kotlin.coroutines.SuspendFunction1)` to handle gestures. If there is a `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines.cancellation/-cancellation-exception/index.html`, it will wait until all pointers are raised before another gesture is detected, or it exits if `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/index.html` is `false`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).awaitEachGesture(kotlin.coroutines.SuspendFunction1)` is run within `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#awaitPointerEventScope(kotlin.coroutines.SuspendFunction1)` and will loop entirely within the `https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/AwaitPointerEventScope` so events will not be lost between gestures.

### PointerInputScope.forEachGesture

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

```
suspend fun PointerInputScope.[forEachGesture](https://developer.android.com/reference/kotlin/androidx/compose/ui/input/pointer/PointerInputScope#(androidx.compose.ui.input.pointer.PointerInputScope).forEachGesture(kotlin.coroutines.SuspendFunction1))(block: suspend PointerInputScope.() -> Unit): Unit
```

> [!CAUTION]
> **This function is deprecated.**   
> Use awaitEachGesture instead. forEachGesture() can drop events between gestures, use this instead:
>
> ```kotlin
> awaitEachGesture(block)
> ```

Repeatedly calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).forEachGesture(kotlin.coroutines.SuspendFunction1)` to handle gestures. If there is a `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.coroutines.cancellation/-cancellation-exception/index.html`, it will wait until all pointers are raised before another gesture is detected, or it exits if `https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/index.html` is `false`.

`https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).awaitEachGesture(kotlin.coroutines.SuspendFunction1)` does the same thing without the possibility of missing events between gestures, but also lacks the ability to call arbitrary suspending functions within `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).forEachGesture(kotlin.coroutines.SuspendFunction1)`.

### PointerInputScope.detectTapGestures

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

```
suspend fun PointerInputScope.detectTapGestures(
    onDoubleTap: ((Offset) -> Unit)? = null,
    onLongPress: ((Offset) -> Unit)? = null,
    onPress: suspend PressGestureScope.(Offset) -> Unit = NoPressGesture,
    onTap: ((Offset) -> Unit)? = null
): Unit
```

Detects tap, double-tap, and long press gestures and calls `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, respectively, when detected. `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` is called when the press is detected and the `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/PressGestureScope#tryAwaitRelease()` and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/PressGestureScope#awaitRelease()` can be used to detect when pointers have released or the gesture was canceled. The first pointer down and final pointer up are consumed, and in the case of long press, all changes after the long press is detected are consumed.

Each function parameter receives an `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` representing the position relative to the containing element. The `https://developer.android.com/reference/kotlin/androidx/compose/ui/geometry/Offset` can be outside the actual bounds of the element itself meaning the numbers can be negative or larger than the element bounds if the touch target is smaller than the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#minimumTouchTargetSize()`.

When `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` is provided, the tap gesture is detected only after the `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#doubleTapMinTimeMillis()` has passed and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` is called if the second tap is started before `https://developer.android.com/reference/kotlin/androidx/compose/ui/platform/ViewConfiguration#doubleTapTimeoutMillis()`. If `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` is not provided, then `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` is called when the pointer up has been received.

After the initial `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, if the pointer moves out of the input area, the position change is consumed, or another gesture consumes the down or up events, the gestures are considered canceled. That means `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`, and `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)` will not be called after a gesture has been canceled.

If the first down event is consumed somewhere else, the entire gesture will be skipped, including `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTapGestures(kotlin.Function1,kotlin.Function1,kotlin.coroutines.SuspendFunction2,kotlin.Function1)`.

### PointerInputScope.detectTransformGestures

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

```
suspend fun PointerInputScope.detectTransformGestures(
    panZoomLock: Boolean = false,
    onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit
): Unit
```

A gesture detector for rotation, panning, and zoom. Once touch slop has been reached, the user can use rotation, panning and zoom gestures. `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTransformGestures(kotlin.Boolean,kotlin.Function4)` will be called when any of the rotation, zoom or pan occurs, passing the rotation angle in degrees, zoom in scale factor and pan as an offset in pixels. Each of these changes is a difference between the previous call and the current gesture. This will consume all position changes after touch slop has been reached. `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTransformGestures(kotlin.Boolean,kotlin.Function4)` will also provide centroid of all the pointers that are down.

If `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTransformGestures(kotlin.Boolean,kotlin.Function4)` is `true`, rotation is allowed only if touch slop is detected for rotation before pan or zoom motions. If not, pan and zoom gestures will be detected, but rotation gestures will not be. If `https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/package-summary#(androidx.compose.ui.input.pointer.PointerInputScope).detectTransformGestures(kotlin.Boolean,kotlin.Function4)` is `false`, once touch slop is reached, all three gestures are detected.

Example Usage:

```kotlin
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
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.graphics.Color
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput

/**
 * Rotates the given offset around the origin by the given angle in degrees.
 *
 * A positive angle indicates a counterclockwise rotation around the right-handed 2D Cartesian
 * coordinate system.
 *
 * See: [Rotation matrix](https://en.wikipedia.org/wiki/Rotation_matrix)
 */
fun Offset.rotateBy(angle: Float): Offset {
    val angleInRadians = angle * (PI / 180)
    val cos = cos(angleInRadians)
    val sin = sin(angleInRadians)
    return Offset((x * cos - y * sin).toFloat(), (x * sin + y * cos).toFloat())
}

var offset by remember { mutableStateOf(Offset.Zero) }
var zoom by remember { mutableStateOf(1f) }
var angle by remember { mutableStateOf(0f) }

Box(
    Modifier.pointerInput(Unit) {
            detectTransformGestures(
                onGesture = { centroid, pan, gestureZoom, gestureRotate ->
                    val oldScale = zoom
                    val newScale = zoom * gestureZoom

                    // For natural zooming and rotating, the centroid of the gesture should
                    // be the fixed point where zooming and rotating occurs.
                    // We compute where the centroid was (in the pre-transformed coordinate
                    // space), and then compute where it will be after this delta.
                    // We then compute what the new offset should be to keep the centroid
                    // visually stationary for rotating and zooming, and also apply the pan.
                    offset =
                        (offset + centroid / oldScale).rotateBy(gestureRotate) -
                            (centroid / newScale + pan / oldScale)
                    zoom = newScale
                    angle += gestureRotate
                }
            )
        }
        .graphicsLayer {
            translationX = -offset.x * zoom
            translationY = -offset.y * zoom
            scaleX = zoom
            scaleY = zoom
            rotationZ = angle
            transformOrigin = TransformOrigin(0f, 0f)
        }
        .background(Color.Blue)
        .fillMaxSize()
)
```