glasses: hold Mercury kill switch on hidden VirtualDisplay; phone: brightness/WiFi panel, two-finger touchpad scroll

This commit is contained in:
2026-09-25 19:49:25 +03:00
parent 3fce3eb3ca
commit c69e8a2e80
8 changed files with 544 additions and 26 deletions
@@ -32,6 +32,7 @@ import pw.binom.rayneovm.shared.VmProtocol
import pw.binom.rayneovm.shared.GetAppList
import pw.binom.rayneovm.shared.AppEntry
import pw.binom.rayneovm.shared.AppListResponse
import pw.binom.rayneovm.shared.CursorScroll
import pw.binom.rayneovm.shared.CursorClick
import pw.binom.rayneovm.shared.CursorMove
@@ -84,6 +85,14 @@ class VmService : LifecycleService() {
}
}
/**
* Текущая активная сессия телефона.
*
* Нужна, чтобы отключение «чужой»/устаревшей сессии (например, пробного WebSocket-хендшейка
* из subnet-фоллбека при поиске очков) не сбрасывало экран в NoConnection, пока жива настоящая.
*/
private val currentConn = java.util.concurrent.atomic.AtomicReference<String?>(null)
private fun startServer() {
server = Transports.wifiServer(port = WS_PORT, path = WS_PATH)
lifecycleScope.launch(kotlinx.coroutines.Dispatchers.IO) {
@@ -94,10 +103,15 @@ class VmService : LifecycleService() {
},
onConnected = { connId ->
Log.i(TAG, "Phone connected: $connId")
currentConn.set(connId)
},
onDisconnected = { connId ->
Log.i(TAG, "Phone disconnected: $connId")
controller.setState(GlassesScreenState.NoConnection)
if (currentConn.compareAndSet(connId, null)) {
controller.setState(GlassesScreenState.NoConnection)
} else {
Log.i(TAG, "Ignoring disconnect of stale session $connId")
}
},
)
} catch (t: Throwable) {
@@ -129,6 +143,10 @@ class VmService : LifecycleService() {
Log.d(TAG, "CursorClick")
controller.clickCursor()
}
is CursorScroll -> {
Log.d(TAG, "CursorScroll: ${msg.dx},${msg.dy}")
controller.scrollCursor(msg.dx, msg.dy)
}
is VmKeyEvent -> {
Log.d(TAG, "Key: ${msg.keyCode} action=${msg.action}")
controller.sendKey(msg.keyCode, msg.action)