glasses: ignore scroll drags shorter than 96px (guest counts them as item clicks); phone: skip centroid jump on finger-count change

This commit is contained in:
2026-09-25 20:27:26 +03:00
parent 05daf3fc7b
commit 94f0ed28fc
2 changed files with 30 additions and 2 deletions
@@ -6,6 +6,7 @@ import android.content.Intent
import android.content.IntentFilter
import android.graphics.SurfaceTexture
import android.os.IBinder
import android.os.SystemClock
import android.util.Log
import android.view.Surface
import androidx.compose.runtime.staticCompositionLocalOf
@@ -182,12 +183,15 @@ class VmGlassesController {
scrollPump = testScope.launch {
var accX = 0f
var accY = 0f
var lastDeltaAt = 0L
while (isActive) {
delay(SCROLL_TICK_MS)
var got = false
while (true) {
val r = scrollChannel.tryReceive().getOrNull() ?: break
accX += r[0]
accY += r[1]
got = true
}
val src = activeSource
val pos = _cursor.value
@@ -196,6 +200,16 @@ class VmGlassesController {
accY = 0f
continue
}
val now = SystemClock.uptimeMillis()
if (got) lastDeltaAt = now
// Копили мало и пауза — сбрасываем хвост, иначе он выстрелит в следующем жесте.
if (!got && now - lastDeltaAt > SCROLL_IDLE_RESET_MS) {
accX = 0f
accY = 0f
continue
}
// Драг короче ~90 px гость считает кликом по элементу списка, а не скроллом,
// поэтому короткие пачки продолжаем копить.
if (abs(accX) < SCROLL_MIN_PX && abs(accY) < SCROLL_MIN_PX) continue
val ok = ShizukuVdBinder.scroll(
binder = src.shizukuBinder,
@@ -398,9 +412,14 @@ class VmGlassesController {
private const val VIRTUAL_HEIGHT = VmDisplay.HEIGHT
private const val VIRTUAL_DENSITY = VmDisplay.DENSITY
/** Скролл-драг: как часто сливаем накопленные дельты и минимальный порог (px). */
/** Скролл-драг: как часто сливаем накопленные дельты, порог и сброс «хвоста». */
private const val SCROLL_TICK_MS = 90L
private const val SCROLL_MIN_PX = 16f
/** Минимальная длина драга: короче гость трактует как клик по элементу (проверено на Settings ~50-60 px). */
private const val SCROLL_MIN_PX = 96f
/** Если дельты пропали дольше этого — накопленное не тащим в следующий жест. */
private const val SCROLL_IDLE_RESET_MS = 300L
/** Активность RayNeo-лаунчера, чей `onStart` включает вендорский `tmpStopBackgroundKill`. */
private const val GUARD_PACKAGE = "com.ffalconxr.mercury.launcher"
@@ -88,6 +88,7 @@ fun RemoteScreen(
val gainY = VmDisplay.HEIGHT / size.height.toFloat()
var mode = PadMode.UNDECIDED
var lastCentroid = Offset.Zero
var lastPressedCount = 1
var travel = 0f
awaitFirstDown(requireUnconsumed = false)
@@ -105,6 +106,14 @@ fun RemoteScreen(
if (mode == PadMode.UNDECIDED || (mode == PadMode.CURSOR && pressed.size >= 2)) {
mode = if (pressed.size >= 2) PadMode.SCROLL else PadMode.CURSOR
lastCentroid = centroid
lastPressedCount = pressed.size
continue
}
// Число пальцев изменилось (отпустили один из двух) — центроид скачет,
// этот скачок не скроллим, иначе список прыгает.
if (pressed.size != lastPressedCount) {
lastPressedCount = pressed.size
lastCentroid = centroid
continue
}