diff --git a/Android/app/src/main/java/com/archipelago/app/ui/components/GamepadLayout.kt b/Android/app/src/main/java/com/archipelago/app/ui/components/GamepadLayout.kt index f931ff21..c93991d6 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/components/GamepadLayout.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/components/GamepadLayout.kt @@ -38,7 +38,7 @@ import com.archipelago.app.ui.theme.neoRaised @Composable fun GamepadLayout( onKey: (String) -> Unit, - onTwoFingerHold: () -> Unit, + onThreeFingerHold: () -> Unit, modifier: Modifier = Modifier, ) { val surface = Neo.surface() @@ -54,9 +54,9 @@ fun GamepadLayout( do { val ev = awaitPointerEvent() val a = ev.changes.filter { !it.changedToUp() } - if (a.size >= 2 && t == 0L) t = System.currentTimeMillis() - if (a.size >= 2 && !fired && t > 0 && System.currentTimeMillis() - t > 500) { fired = true; onTwoFingerHold() } - if (a.size < 2) t = 0L + if (a.size >= 3 && t == 0L) t = System.currentTimeMillis() + if (a.size >= 3 && !fired && t > 0 && System.currentTimeMillis() - t > 500) { fired = true; onThreeFingerHold() } + if (a.size < 3) t = 0L } while (ev.changes.any { it.pressed }) } } diff --git a/Android/app/src/main/java/com/archipelago/app/ui/components/NESController.kt b/Android/app/src/main/java/com/archipelago/app/ui/components/NESController.kt index 6d4cb2b3..724f7c3b 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/components/NESController.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/components/NESController.kt @@ -116,7 +116,7 @@ fun NESController( Box( modifier = modifier .fillMaxSize() - .twoFingerHold(onMenu) + .threeFingerHold(onMenu) .padding(horizontal = 40.dp, vertical = 24.dp), contentAlignment = Alignment.Center, ) { @@ -451,17 +451,17 @@ fun PlayerPill(c: NESPalette, playerId: Int, onToggle: () -> Unit) { } } -/** Two-finger hold gesture modifier */ -fun Modifier.twoFingerHold(onHold: () -> Unit) = this.pointerInput(Unit) { +/** Three-finger hold gesture modifier (two fingers stay free for scrolling) */ +fun Modifier.threeFingerHold(onHold: () -> Unit) = this.pointerInput(Unit) { awaitEachGesture { awaitFirstDown(requireUnconsumed = false) var t = 0L; var fired = false do { val ev = awaitPointerEvent() val a = ev.changes.filter { !it.changedToUp() } - if (a.size >= 2 && t == 0L) t = System.currentTimeMillis() - if (a.size >= 2 && !fired && t > 0 && System.currentTimeMillis() - t > 500) { fired = true; onHold() } - if (a.size < 2) t = 0L + if (a.size >= 3 && t == 0L) t = System.currentTimeMillis() + if (a.size >= 3 && !fired && t > 0 && System.currentTimeMillis() - t > 500) { fired = true; onHold() } + if (a.size < 3) t = 0L } while (ev.changes.any { it.pressed }) } } diff --git a/Android/app/src/main/java/com/archipelago/app/ui/components/NESPortraitController.kt b/Android/app/src/main/java/com/archipelago/app/ui/components/NESPortraitController.kt index 59fac842..0b93e684 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/components/NESPortraitController.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/components/NESPortraitController.kt @@ -50,7 +50,7 @@ fun NESPortraitController( Box( Modifier .fillMaxSize() - .twoFingerHold(onMenu) + .threeFingerHold(onMenu) .padding(horizontal = 40.dp, vertical = 24.dp), contentAlignment = Alignment.Center, ) { @@ -87,7 +87,7 @@ fun NESPortraitController( onMove = { dx, dy -> onMouseMove(dx, dy) }, onClick = { onMouseClick(it) }, onScroll = { dy -> onMouseScroll(dy) }, - onTwoFingerHold = onMenu, + onThreeFingerHold = onMenu, modifier = Modifier .fillMaxWidth() .weight(1f), diff --git a/Android/app/src/main/java/com/archipelago/app/ui/components/Trackpad.kt b/Android/app/src/main/java/com/archipelago/app/ui/components/Trackpad.kt index 27b27ec7..bb02faa7 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/components/Trackpad.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/components/Trackpad.kt @@ -32,7 +32,7 @@ fun Trackpad( onMove: (dx: Int, dy: Int) -> Unit, onClick: (button: Int) -> Unit, onScroll: (dy: Int) -> Unit, - onTwoFingerHold: () -> Unit, + onThreeFingerHold: () -> Unit, modifier: Modifier = Modifier, ) { var fingers by remember { mutableIntStateOf(0) } @@ -53,7 +53,7 @@ fun Trackpad( val t0 = System.currentTimeMillis() var maxPtrs = 1 var holdFired = false - var twoStart = 0L + var threeStart = 0L var scrollAcc = 0f fingers = 1 @@ -64,19 +64,24 @@ fun Trackpad( fingers = active.size when { - active.size >= 2 -> { - if (twoStart == 0L) twoStart = System.currentTimeMillis() - if (!holdFired && System.currentTimeMillis() - twoStart > 500) { + // Three fingers = hold for menu; two = scroll. Kept + // on separate counts so a long two-finger scroll can + // never fire the menu mid-gesture. + active.size >= 3 -> { + if (threeStart == 0L) threeStart = System.currentTimeMillis() + if (!holdFired && System.currentTimeMillis() - threeStart > 500) { holdFired = true - onTwoFingerHold() + onThreeFingerHold() } - if (!holdFired) { - val dy = active.map { it.positionChange().y }.average().toFloat() - scrollAcc += dy - if (kotlin.math.abs(scrollAcc) > 12f) { - onScroll(if (scrollAcc > 0) 1 else -1) - scrollAcc = 0f - } + ev.changes.forEach { it.consume() } + } + active.size == 2 -> { + threeStart = 0L + val dy = active.map { it.positionChange().y }.average().toFloat() + scrollAcc += dy + if (kotlin.math.abs(scrollAcc) > 12f) { + onScroll(if (scrollAcc > 0) 1 else -1) + scrollAcc = 0f } ev.changes.forEach { it.consume() } } @@ -99,7 +104,11 @@ fun Trackpad( contentAlignment = Alignment.Center, ) { Text( - text = if (fingers >= 2) "hold for menu" else "", + text = when { + fingers >= 3 -> "hold for menu" + fingers == 2 -> "scroll" + else -> "" + }, style = MaterialTheme.typography.labelSmall, color = muted.copy(alpha = 0.4f), ) diff --git a/Android/app/src/main/java/com/archipelago/app/ui/screens/RemoteInputScreen.kt b/Android/app/src/main/java/com/archipelago/app/ui/screens/RemoteInputScreen.kt index 646d509d..f38cc485 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/screens/RemoteInputScreen.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/screens/RemoteInputScreen.kt @@ -172,7 +172,7 @@ fun RemoteInputScreen(onBack: () -> Unit) { onMove = { dx, dy -> ws.sendMouseMove(dx, dy) }, onClick = { ws.sendClick(it) }, onScroll = { ws.sendScroll(it) }, - onTwoFingerHold = { showModal = true }, + onThreeFingerHold = { showModal = true }, modifier = Modifier.fillMaxWidth().weight(1f) .padding(horizontal = 16.dp, vertical = 8.dp), )