Skip to content

Commit ec3ecbe

Browse files
authored
Handle duplicate mouse events following touch events on web. (JetBrains#2741)
Ensure mouse events with the same timestamp as the most recent touch event are ignored, preventing duplicate inputs. Fixes https://youtrack.jetbrains.com/issue/CMP-9673 ## Testing Manually check the demo ## Release Notes ### Fixes - Web - Ignore duplicate mouse events following touch events on web to avoid unitended clicks.
1 parent 98f13d1 commit ec3ecbe

1 file changed

Lines changed: 14 additions & 7 deletions

File tree

compose/ui/ui/src/webMain/kotlin/androidx/compose/ui/window/ComposeWindowInternal.web.kt

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import androidx.compose.runtime.Composable
2121
import androidx.compose.runtime.CompositionLocalProvider
2222
import androidx.compose.runtime.InternalComposeApi
2323
import androidx.compose.runtime.LaunchedEffect
24-
import androidx.compose.runtime.rememberCoroutineScope
2524
import androidx.compose.ui.LocalSystemTheme
2625
import androidx.compose.ui.draganddrop.WebDragAndDropManager
2726
import androidx.compose.ui.events.EventTargetListener
@@ -94,7 +93,6 @@ import kotlinx.coroutines.flow.Flow
9493
import kotlinx.coroutines.flow.flow
9594
import kotlinx.coroutines.flow.receiveAsFlow
9695
import kotlinx.coroutines.isActive
97-
import kotlinx.coroutines.launch
9896
import org.jetbrains.skia.Canvas
9997
import org.jetbrains.skiko.SkiaLayer
10098
import org.jetbrains.skiko.SkikoRenderDelegate
@@ -366,6 +364,13 @@ internal class ComposeWindow(
366364
private fun initEvents(canvas: HTMLCanvasElement) {
367365
var offset = Offset.Zero
368366

367+
/*
368+
* CMP-9673 [Web] Double touch and mouse events
369+
* If a touch event is followed by mouse events with the same timestamp, the mouse events are ignored.
370+
*/
371+
var finalTouchEventTimestamp: Any? = null
372+
fun MouseEvent.isReal() = timeStamp !== finalTouchEventTimestamp
373+
369374
addTypedEvent<TouchEvent>("touchstart") { event ->
370375
canvas.getBoundingClientRect().apply {
371376
offset = Offset(x = left.toFloat(), y = top.toFloat())
@@ -380,30 +385,32 @@ internal class ComposeWindow(
380385

381386
addTypedEvent<TouchEvent>("touchend") { event ->
382387
onTouchEvent(event, offset)
388+
finalTouchEventTimestamp = event.timeStamp
383389
}
384390

385391
addTypedEvent<TouchEvent>("touchcancel") { event ->
386392
onTouchEvent(event, offset)
393+
finalTouchEventTimestamp = event.timeStamp
387394
}
388395

389396
addTypedEvent<MouseEvent>("mousedown") { event ->
390-
onMouseEvent(event)
397+
if (event.isReal()) onMouseEvent(event)
391398
}
392399

393400
addTypedEvent<MouseEvent>("mouseup") { event ->
394-
onMouseEvent(event)
401+
if (event.isReal()) onMouseEvent(event)
395402
}
396403

397404
addTypedEvent<MouseEvent>("mousemove") { event ->
398-
onMouseEvent(event)
405+
if (event.isReal()) onMouseEvent(event)
399406
}
400407

401408
addTypedEvent<MouseEvent>("mouseenter") { event ->
402-
onMouseEvent(event)
409+
if (event.isReal()) onMouseEvent(event)
403410
}
404411

405412
addTypedEvent<MouseEvent>("mouseleave") { event ->
406-
onMouseEvent(event)
413+
if (event.isReal()) onMouseEvent(event)
407414
}
408415

409416
addTypedEvent<WheelEvent>("wheel") { event ->

0 commit comments

Comments
 (0)