mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
Input: one writer per trigger when a pad reports both ways
Retroid pads have an L2/R2 mode called "both": the trigger sends KEYCODE_BUTTON_L2/R2 AND an analog axis. sendTrigger writes the pad button from the axis, and the key path wrote it again -- one physical squeeze, two independent writers on the same button, which arrives as a delayed or doubled press. Long jumps in the Ratchet games hold R2 and were unreliable because of it; a reporter had it in 0.9.2 and says 0.8 was fine. sendTrigger already carries the opposite guard: a pad with no trigger axis at all leaves "the key path in sole charge", added when Switch Pro controllers had their held trigger cancelled by every stick movement. This is that guard's mirror, and the two together mean exactly one writer owns a trigger on every pad -- the axis where there is an axis, the key where there is not. Keyed on the physical keycode before remapping, because what decides ownership is how the hardware reports the trigger, not what the user bound it to. Pads that report triggers ONLY as keys are unaffected: they have none of the three axes, so the guard does not fire and the key path still owns them.
This commit is contained in:
@@ -3290,6 +3290,35 @@ open class MainActivityRuntime : ComponentActivity() {
|
||||
val physicalCode = event.keyCode
|
||||
if (physicalCode == KeyEvent.KEYCODE_UNKNOWN) return false
|
||||
|
||||
// A trigger that reports BOTH ways gets written by both paths, and they fight.
|
||||
//
|
||||
// Retroid pads have an L2/R2 mode called "both": the trigger sends KEYCODE_BUTTON_L2/R2
|
||||
// AND an analog axis. sendTrigger already writes the button from the axis, so letting
|
||||
// the key through as well gives one physical squeeze two independent writers on the
|
||||
// same pad button -- which lands as a delayed or doubled press, and made long jumps in
|
||||
// the Ratchet games (hold R2) unreliable.
|
||||
//
|
||||
// sendTrigger has the opposite guard already: a pad with no trigger axis at all leaves
|
||||
// "the key path in sole charge". This is that guard's mirror, and the two together mean
|
||||
// exactly one writer owns a trigger on every pad -- axis where there is an axis, key
|
||||
// where there is not.
|
||||
//
|
||||
// Deliberately keyed on the PHYSICAL code before remapping: what decides ownership is
|
||||
// how the hardware reports the trigger, not what the user bound it to.
|
||||
if (physicalCode == KeyEvent.KEYCODE_BUTTON_L2 || physicalCode == KeyEvent.KEYCODE_BUTTON_R2)
|
||||
{
|
||||
val isLeft = physicalCode == KeyEvent.KEYCODE_BUTTON_L2
|
||||
val axisA = if (isLeft) MotionEvent.AXIS_LTRIGGER else MotionEvent.AXIS_RTRIGGER
|
||||
val axisB = if (isLeft) MotionEvent.AXIS_BRAKE else MotionEvent.AXIS_GAS
|
||||
val axisC = if (isLeft) -1 else rightTriggerExtraAxis(event.deviceId)
|
||||
|
||||
if (deviceHasAxis(event.deviceId, axisA) || deviceHasAxis(event.deviceId, axisB) ||
|
||||
deviceHasAxis(event.deviceId, axisC))
|
||||
{
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// Local co-op routing and macro precedence exactly match the old Compose
|
||||
// onKeyEvent path; only the dispatch layer has changed.
|
||||
val port = com.armsx2.input.PadRouter.portForDevice(event.deviceId)
|
||||
|
||||
Reference in New Issue
Block a user