Skip to content

Commit a069c89

Browse files
committed
Merge branch 'feature/1386-wait-for-sequence-trigger-timeout' into develop
2 parents 5214096 + 71044e4 commit a069c89

File tree

2 files changed

+288
-29
lines changed

2 files changed

+288
-29
lines changed

app/src/free/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ class KeyMapController(
249249
MutableList(triggers.size) { mutableSetOf<Int>() }
250250

251251
for (triggerIndex in parallelTriggers) {
252-
val trigger = triggers[triggerIndex]
252+
val parallelTrigger = triggers[triggerIndex]
253253

254254
otherTriggerLoop@ for (otherTriggerIndex in sequenceTriggers) {
255255
val otherTrigger = triggers[otherTriggerIndex]
@@ -259,7 +259,7 @@ class KeyMapController(
259259
continue@otherTriggerLoop
260260
}
261261

262-
for ((keyIndex, key) in trigger.keys.withIndex()) {
262+
for ((keyIndex, key) in parallelTrigger.keys.withIndex()) {
263263
var lastMatchedIndex: Int? = null
264264

265265
for ((otherKeyIndex, otherKey) in otherTrigger.keys.withIndex()) {
@@ -271,7 +271,7 @@ class KeyMapController(
271271
continue@otherTriggerLoop
272272
}
273273

274-
if (keyIndex == trigger.keys.lastIndex) {
274+
if (keyIndex == parallelTrigger.keys.lastIndex) {
275275
sequenceTriggersOverlappingParallelTriggers[triggerIndex].add(
276276
otherTriggerIndex,
277277
)
@@ -489,30 +489,36 @@ class KeyMapController(
489489

490490
private var modifierKeyEventActions: Boolean = false
491491
private var notModifierKeyEventActions: Boolean = false
492-
private var keyCodesToImitateUpAction: MutableSet<Int> = mutableSetOf<Int>()
492+
private var keyCodesToImitateUpAction: MutableSet<Int> = mutableSetOf()
493493
private var metaStateFromActions: Int = 0
494494
private var metaStateFromKeyEvent: Int = 0
495495

496-
private val eventDownTimeMap: MutableMap<Event, Long> = mutableMapOf<Event, Long>()
496+
private val eventDownTimeMap: MutableMap<Event, Long> = mutableMapOf()
497+
498+
/**
499+
* This solves issue #1386. This stores the jobs that will wait until the sequence trigger
500+
* times out and check whether the overlapping sequence trigger was indeed triggered.
501+
*/
502+
private val performActionsAfterSequenceTriggerTimeout: MutableMap<Int, Job> = mutableMapOf()
497503

498504
/**
499505
* The indexes of parallel triggers that didn't have their actions performed because there is a matching trigger but
500506
* for a long-press. These actions should only be performed if the long-press fails, otherwise when the user
501507
* holds down the trigger keys for the long-press trigger, actions from both triggers will be performed.
502508
*/
503-
private val performActionsOnFailedLongPress: MutableSet<Int> = mutableSetOf<Int>()
509+
private val performActionsOnFailedLongPress: MutableSet<Int> = mutableSetOf()
504510

505511
/**
506512
* The indexes of parallel triggers that didn't have their actions performed because there is a matching trigger but
507513
* for a double-press. These actions should only be performed if the double-press fails, otherwise each time the user
508514
* presses the keys for the double press, actions from both triggers will be performed.
509515
*/
510-
private val performActionsOnFailedDoublePress: MutableSet<Int> = mutableSetOf<Int>()
516+
private val performActionsOnFailedDoublePress: MutableSet<Int> = mutableSetOf()
511517

512518
/**
513519
* Maps jobs to perform an action after a long press to their corresponding parallel trigger index
514520
*/
515-
private val parallelTriggerLongPressJobs: SparseArrayCompat<Job> = SparseArrayCompat<Job>()
521+
private val parallelTriggerLongPressJobs: SparseArrayCompat<Job> = SparseArrayCompat()
516522

517523
/**
518524
* Keys that are detected through an input method will potentially send multiple DOWN key events
@@ -849,31 +855,63 @@ class KeyMapController(
849855
mappedToParallelTriggerAction = true
850856
parallelTriggersAwaitingReleaseAfterBeingTriggered[triggerIndex] = true
851857

852-
val actionKeys = triggerActions[triggerIndex]
858+
// See issue #1386.
859+
val overlappingSequenceTrigger =
860+
sequenceTriggersOverlappingParallelTriggers[triggerIndex]
861+
// Only consider the sequence triggers where this
862+
// short press trigger has been already pressed
863+
// or will be pressed next.
864+
.filter {
865+
for (i in 0..(lastMatchedEventIndices[it] + 1)) {
866+
val matchingEvent = triggers[it].matchingEventAtIndex(
867+
event.withShortPress,
868+
i,
869+
)
870+
871+
if (matchingEvent) {
872+
return@filter true
873+
}
874+
}
875+
876+
return@filter false
877+
}
878+
.maxByOrNull { sequenceTriggerTimeout(triggers[it]) }
879+
880+
if (overlappingSequenceTrigger == null) {
881+
val actionKeys = triggerActions[triggerIndex]
853882

854-
actionKeys.forEach { actionKey ->
855-
val action = actionMap[actionKey] ?: return@forEach
883+
actionKeys.forEach { actionKey ->
884+
val action = actionMap[actionKey] ?: return@forEach
856885

857-
if (action.data is ActionData.InputKeyEvent) {
858-
val actionKeyCode = action.data.keyCode
886+
if (action.data is ActionData.InputKeyEvent) {
887+
val actionKeyCode = action.data.keyCode
859888

860-
if (isModifierKey(actionKeyCode)) {
861-
val actionMetaState =
862-
InputEventUtils.modifierKeycodeToMetaState(actionKeyCode)
863-
metaStateFromActions =
864-
metaStateFromActions.withFlag(actionMetaState)
889+
if (isModifierKey(actionKeyCode)) {
890+
val actionMetaState =
891+
InputEventUtils.modifierKeycodeToMetaState(actionKeyCode)
892+
metaStateFromActions =
893+
metaStateFromActions.withFlag(actionMetaState)
894+
}
865895
}
866-
}
867896

868-
detectedShortPressTriggers.add(triggerIndex)
897+
detectedShortPressTriggers.add(triggerIndex)
869898

870-
val vibrateDuration = when {
871-
trigger.vibrate -> vibrateDuration(trigger)
872-
forceVibrate.value -> defaultVibrateDuration.value
873-
else -> -1L
899+
val vibrateDuration = when {
900+
trigger.vibrate -> vibrateDuration(trigger)
901+
forceVibrate.value -> defaultVibrateDuration.value
902+
else -> -1L
903+
}
904+
905+
vibrateDurations.add(vibrateDuration)
874906
}
907+
} else {
908+
performActionsAfterSequenceTriggerTimeout[triggerIndex]?.cancel()
875909

876-
vibrateDurations.add(vibrateDuration)
910+
performActionsAfterSequenceTriggerTimeout[triggerIndex] =
911+
performActionsAfterSequenceTriggerTimeout(
912+
triggerIndex,
913+
overlappingSequenceTrigger,
914+
)
877915
}
878916
}
879917
}
@@ -1443,14 +1481,14 @@ class KeyMapController(
14431481
metaStateFromKeyEvent = 0
14441482
keyCodesToImitateUpAction = mutableSetOf()
14451483

1446-
parallelTriggerLongPressJobs.valueIterator().forEach {
1447-
it.cancel()
1448-
}
1449-
1484+
parallelTriggerLongPressJobs.valueIterator().forEach { it.cancel() }
14501485
parallelTriggerLongPressJobs.clear()
14511486

14521487
parallelTriggerActionPerformers.values.forEach { it.reset() }
14531488
sequenceTriggerActionPerformers.values.forEach { it.reset() }
1489+
1490+
performActionsAfterSequenceTriggerTimeout.forEach { (_, job) -> job.cancel() }
1491+
performActionsAfterSequenceTriggerTimeout.clear()
14541492
}
14551493

14561494
/**
@@ -1499,6 +1537,40 @@ class KeyMapController(
14991537
return detectedTriggerIndexes.isNotEmpty()
15001538
}
15011539

1540+
/**
1541+
* For parallel triggers only.
1542+
*/
1543+
private fun performActionsAfterSequenceTriggerTimeout(
1544+
triggerIndex: Int,
1545+
sequenceTriggerIndex: Int,
1546+
) = coroutineScope.launch {
1547+
val timeout = sequenceTriggerTimeout(triggers[sequenceTriggerIndex])
1548+
1549+
delay(timeout)
1550+
1551+
// If it equals -1 then it means the sequence trigger was triggered
1552+
// and it reset the counter.
1553+
if (lastMatchedEventIndices[sequenceTriggerIndex] == -1) {
1554+
return@launch
1555+
}
1556+
1557+
parallelTriggerActionPerformers[triggerIndex]?.onTriggered(
1558+
calledOnTriggerRelease = true,
1559+
metaState = metaStateFromActions.withFlag(metaStateFromKeyEvent),
1560+
)
1561+
1562+
if (triggers[triggerIndex].vibrate ||
1563+
forceVibrate.value ||
1564+
triggers[triggerIndex].longPressDoubleVibration
1565+
) {
1566+
useCase.vibrate(vibrateDuration(triggers[triggerIndex]))
1567+
}
1568+
1569+
if (triggers[triggerIndex].showToast) {
1570+
useCase.showTriggeredToast()
1571+
}
1572+
}
1573+
15021574
private fun encodeActionList(actions: List<KeyMapAction>): IntArray = actions.map { getActionKey(it) }.toIntArray()
15031575

15041576
/**

0 commit comments

Comments
 (0)