Skip to content

Commit 3ea5e4c

Browse files
authored
Add a demo for touch events issues on web (#2521)
Related issue https://youtrack.jetbrains.com/issue/CMP-9030 ## Testing N/A ## Release Notes N/A
1 parent 4ef8eef commit 3ea5e4c

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

compose/mpp/demo/src/webMain/kotlin/androidx/compose/mpp/demo/bugs/BugsScreen.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,10 @@ import androidx.compose.mpp.demo.Screen
2121
val BugsScreen = Screen.Selection("Web Bug Reproducers", screens = listOf(
2222
Screen.Example("Text Fields in Scrollable") {
2323
TextFieldsInTallScrollableContainer()
24+
},
25+
Screen.Example("Touch events") {
26+
// https://youtrack.jetbrains.com/issue/CMP-9030/wasm-canvas-incorrect-handling-of-multi-touch-input
27+
PointerInputDebugOverlay()
2428
}
25-
))
29+
))
30+
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package androidx.compose.mpp.demo.bugs
18+
19+
import androidx.compose.foundation.Canvas
20+
import androidx.compose.foundation.layout.Box
21+
import androidx.compose.foundation.layout.BoxScope
22+
import androidx.compose.foundation.layout.fillMaxSize
23+
import androidx.compose.material.Text
24+
import androidx.compose.runtime.Composable
25+
import androidx.compose.runtime.mutableStateOf
26+
import androidx.compose.runtime.remember
27+
import androidx.compose.ui.Modifier
28+
import androidx.compose.ui.geometry.Offset
29+
import androidx.compose.ui.graphics.Color
30+
import androidx.compose.ui.input.pointer.pointerInput
31+
import androidx.compose.ui.unit.Dp
32+
import androidx.compose.ui.unit.dp
33+
34+
// https://youtrack.jetbrains.com/issue/CMP-9030/wasm-canvas-incorrect-handling-of-multi-touch-input
35+
@Composable
36+
fun PointerInputDebugOverlay(
37+
modifier: Modifier = Modifier.fillMaxSize(),
38+
circleRadius: Dp = 50.dp,
39+
circleColor: Color = Color.Red,
40+
) {
41+
// Keep a map of active pointer positions (keyed by pointer id value)
42+
val pointers = remember { mutableStateOf<Map<Long, Offset>>(emptyMap()) }
43+
val log = remember { mutableStateOf("") }
44+
45+
fun logString(s: String) {
46+
log.value = s + "\n" + log.value
47+
if (log.value.length > 500) {
48+
log.value = log.value.take(500)
49+
}
50+
}
51+
52+
Box(modifier = modifier) {
53+
Text(log.value)
54+
// overlay that listens to pointer events and draws circles
55+
Box(
56+
modifier = Modifier
57+
.matchParentSize()
58+
.pointerInput(Unit) {
59+
// Use awaitPointerEventScope to get raw pointer events and positions
60+
awaitPointerEventScope {
61+
while (true) {
62+
val event = awaitPointerEvent()
63+
logString(">")
64+
65+
// update positions for each pointer change
66+
for (change in event.changes) {
67+
val idValue = change.id.value
68+
if (change.pressed) {
69+
// pointer is down or moved
70+
pointers.value += (idValue to change.position)
71+
logString("+ $idValue")
72+
} else {
73+
// pointer was released
74+
logString("- $idValue")
75+
pointers.value -= idValue
76+
}
77+
}
78+
}
79+
}
80+
}
81+
) {
82+
// Draw the active pointer locations
83+
Canvas(modifier = Modifier.matchParentSize()) {
84+
val radiusPx = circleRadius.toPx()
85+
for ((_, pos) in pointers.value) {
86+
// draw a small red circle at each pointer position
87+
drawCircle(
88+
color = circleColor,
89+
radius = radiusPx,
90+
center = pos
91+
)
92+
}
93+
}
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)