mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
fix(input): Auto relative mouse stays off for direct touch without a mouse (#2305)
* fix(input): Auto relative mouse stays off for direct touch without a mouse * fix(input): re-check relative mouse when an input device changes * fix(input): reapply relative mouse after agent readiness * fix(input): only the current session clears the agent-ready hook and readiness resets relative mouse retries
This commit is contained in:
1 parent
7c89c14a84
commit
75a0230304
5 files changed
+59
-2
No files matched your search
@@ -286,6 +286,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
private var directHoldBehavior by mutableStateOf(com.droiddeck.launcher.input.TouchGestureConfig.MOUSE_BEHAVIOR_CLICK)
|
||||
private var relativeMouseMode by mutableIntStateOf(0)
|
||||
@Volatile private var appliedRelativeMouseMode: Int? = null
|
||||
private val agentReadyListener: () -> Unit = { relativeMouseRetries = 0; requestRelativeMouse() }
|
||||
private val appTextFocus get() = wowChat.request != null
|
||||
private val wowChat by lazy { com.droiddeck.launcher.ui.WowChat(this, ::sendWowChat, ::cancelWowChat, ::readGameField) }
|
||||
private var wowChatBottom: SecondScreenPresentation? = null
|
||||
@@ -636,6 +637,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
padBridge?.syncConnectedControllers()
|
||||
refreshControls()
|
||||
updatePointerCapture()
|
||||
requestRelativeMouse()
|
||||
updateHandCamera()
|
||||
refreshSecondScreenDisplays()
|
||||
}
|
||||
@@ -651,12 +653,14 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
if (::padMouse.isInitialized) padMouse.reset()
|
||||
refreshControls()
|
||||
updatePointerCapture()
|
||||
requestRelativeMouse()
|
||||
updateHandCamera()
|
||||
refreshSecondScreenDisplays()
|
||||
}
|
||||
override fun onInputDeviceChanged(deviceId: Int) {
|
||||
joyConVr?.refresh()
|
||||
refreshControls()
|
||||
requestRelativeMouse()
|
||||
refreshSecondScreenDisplays()
|
||||
}
|
||||
}
|
||||
@@ -665,6 +669,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
AgentGuest.readyListener = agentReadyListener
|
||||
if (com.droiddeck.launcher.runtime.LinuxRuntimeInstaller.isRemoving() ||
|
||||
com.droiddeck.launcher.runtime.LinuxRuntimeInstaller.isMaintaining()) {
|
||||
runtimeRemovalBlocked = true
|
||||
@@ -1960,6 +1965,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
val nextRoutedTouchMode = effectiveTouchMode()
|
||||
if (routedTouchMode != nextRoutedTouchMode) gestureTouchStreamGate.reset()
|
||||
routedTouchMode = nextRoutedTouchMode
|
||||
requestRelativeMouse()
|
||||
frameGen = FrameGen.mode(this)
|
||||
fexPreset = SessionPrefs.fexPreset(this)
|
||||
suspendPolicy = SessionPrefs.suspendPolicy(this, SessionState.mode)
|
||||
@@ -2981,7 +2987,15 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
private fun applyRelativeMouse() {
|
||||
val mode = desiredRelativeMouseMode
|
||||
val wanted = desiredRelativeMouseMode
|
||||
val touchpadRoute = com.droiddeck.launcher.input.TouchRouter.decide(com.droiddeck.launcher.input.TouchRouter.Snapshot(
|
||||
uiBlocking = false,
|
||||
mode = routedTouchMode,
|
||||
scrollLayer = false,
|
||||
steamSession = SessionState.mode == SessionService.MODE_STEAM,
|
||||
steamDesktopUi = SessionState.steamUi == "desktop",
|
||||
)) == com.droiddeck.launcher.input.TouchRouter.Route.TOUCHPAD
|
||||
val mode = com.droiddeck.launcher.input.TouchGestureConfig.gamescopeRelativeMouse(wanted, mouseAttached(), touchpadRoute)
|
||||
if (appliedRelativeMouseMode == mode) return
|
||||
val request = org.json.JSONObject()
|
||||
.put("kind", "exec")
|
||||
@@ -2997,7 +3011,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
Log.w(TAG, "gamescope did not take relative mouse $mode: ${result.exceptionOrNull() ?: answer}")
|
||||
if (relativeMouseRetries++ < RELATIVE_MOUSE_MAX_RETRIES) uiHandler.postDelayed({ requestRelativeMouse() }, 2_000)
|
||||
}
|
||||
if (desiredRelativeMouseMode != mode) requestRelativeMouse()
|
||||
if (desiredRelativeMouseMode != wanted) requestRelativeMouse()
|
||||
}
|
||||
|
||||
private fun refreshGestureConfig() {
|
||||
@@ -3813,6 +3827,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
if (next == SessionPrefs.TOUCH_OFF) cursorVisible = false
|
||||
gestureTouchStreamGate.reset()
|
||||
routedTouchMode = next
|
||||
requestRelativeMouse()
|
||||
if (directTouchCursorHidden()) cursorVisible = false
|
||||
}
|
||||
|
||||
@@ -5319,6 +5334,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
if (AgentGuest.readyListener === agentReadyListener) AgentGuest.readyListener = null
|
||||
com.droiddeck.launcher.input.HomeButtonShortcuts.detach(this)
|
||||
relativeMouseRequests.shutdownNow()
|
||||
backQamInput.cancel()
|
||||
|
||||
@@ -33,6 +33,7 @@ object AgentGuest {
|
||||
var keyboardDismissals by mutableIntStateOf(0)
|
||||
private set
|
||||
@Volatile private var keyboardRoute = false
|
||||
@Volatile var readyListener: (() -> Unit)? = null
|
||||
@Volatile private var routeDir: File? = null
|
||||
private const val TAG = "AgentGuest"
|
||||
private const val POLL_MS = 50L
|
||||
@@ -59,6 +60,7 @@ object AgentGuest {
|
||||
when (path) {
|
||||
"hello.json" -> readJson(File(dir, path))?.let {
|
||||
SessionEvents.record("agent.ready", mapOf("pid" to it.optInt("pid"), "focus" to it.optBoolean("focus")))
|
||||
readyListener?.invoke()
|
||||
}
|
||||
"focus.json" -> readJson(File(dir, path))?.let(::recordFocus)
|
||||
"keyboard.json" -> readJson(File(dir, path))?.let { recordKeyboard(this, it) }
|
||||
|
||||
@@ -213,6 +213,9 @@ data class TouchGestureConfig(
|
||||
return if (value == MOUSE_BEHAVIOR_CLICK) MOUSE_BEHAVIOR_CLICK else MOUSE_BEHAVIOR_HOLD
|
||||
}
|
||||
|
||||
fun gamescopeRelativeMouse(mode: Int, mouseAttached: Boolean, touchpad: Boolean): Int =
|
||||
if (mode == RELATIVE_MOUSE_AUTO && !mouseAttached && !touchpad) RELATIVE_MOUSE_OFF else mode
|
||||
|
||||
private fun normalizeRelativeMouseMode(mode: Int): Int {
|
||||
return if (mode in RELATIVE_MOUSE_AUTO..RELATIVE_MOUSE_OFF) mode else RELATIVE_MOUSE_AUTO
|
||||
}
|
||||
|
||||
@@ -17,6 +17,19 @@ class GesturePrefsTest {
|
||||
assertEquals(TouchGestureConfig.RELATIVE_MOUSE_AUTO, TouchGestureConfig.fromJson("{}").relativeMouseMode)
|
||||
}
|
||||
|
||||
@Test fun autoNeverGoesRelativeForDirectTouchWithoutAMouse() {
|
||||
val auto = TouchGestureConfig.RELATIVE_MOUSE_AUTO
|
||||
assertEquals(TouchGestureConfig.RELATIVE_MOUSE_OFF, TouchGestureConfig.gamescopeRelativeMouse(auto, mouseAttached = false, touchpad = false))
|
||||
assertEquals(auto, TouchGestureConfig.gamescopeRelativeMouse(auto, mouseAttached = true, touchpad = false))
|
||||
assertEquals(auto, TouchGestureConfig.gamescopeRelativeMouse(auto, mouseAttached = false, touchpad = true))
|
||||
}
|
||||
|
||||
@Test fun aChosenRelativeMouseModeIsSentAsIs() {
|
||||
for (mode in listOf(TouchGestureConfig.RELATIVE_MOUSE_ON, TouchGestureConfig.RELATIVE_MOUSE_OFF))
|
||||
for (mouse in listOf(false, true)) for (pad in listOf(false, true))
|
||||
assertEquals(mode, TouchGestureConfig.gamescopeRelativeMouse(mode, mouse, pad))
|
||||
}
|
||||
|
||||
@Test fun removedOptionsAreIgnoredWhenLoadingExistingSettings() {
|
||||
val old = """{"holdMouseButtonWhileTouchingEnabled":true,"holdMouseButtonWhileTouchingAction":"right_click",
|
||||
"showClickHighlight":true,"showCursorInTouchscreenMode":true,"tapAction":"key_E","longPressDelay":650}"""
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.droiddeck.launcher.input
|
||||
|
||||
import com.droiddeck.launcher.session.SessionPrefs
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
class TouchRouterTest {
|
||||
@Test fun gesturesAndOffAreNotTouchpadRoutes() {
|
||||
for (mode in listOf(SessionPrefs.TOUCH_GESTURES, SessionPrefs.TOUCH_OFF)) {
|
||||
assertEquals(TouchRouter.Route.GESTURES.takeIf { mode == SessionPrefs.TOUCH_GESTURES } ?: TouchRouter.Route.OFF,
|
||||
TouchRouter.decide(TouchRouter.Snapshot(false, mode, false, false, false)))
|
||||
assertEquals(TouchRouter.Route.GESTURES.takeIf { mode == SessionPrefs.TOUCH_GESTURES } ?: TouchRouter.Route.OFF,
|
||||
TouchRouter.decide(TouchRouter.Snapshot(false, mode, false, true, true)))
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun autoUsesTouchpadOnlyWhenRouterSelectsTouchpad() {
|
||||
assertEquals(TouchRouter.Route.TOUCHPAD,
|
||||
TouchRouter.decide(TouchRouter.Snapshot(false, SessionPrefs.TOUCH_AUTO, false, false, false)))
|
||||
assertEquals(TouchRouter.Route.DIRECT,
|
||||
TouchRouter.decide(TouchRouter.Snapshot(false, SessionPrefs.TOUCH_AUTO, false, true, false)))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user