@@ -506,7 +506,7 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
506506
507507 private var mModifierKeyEventActions = false
508508 private var mNotModifierKeyEventActions = false
509- private var mUnmappedKeycodesToConsumeOnUp = mutableSetOf<Int >()
509+ private var keyCodesToImitateUpAction = mutableSetOf<Int >()
510510 private var mMetaStateFromActions = 0
511511 private var mMetaStateFromKeyEvent = 0
512512
@@ -557,7 +557,8 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
557557 descriptor : String ,
558558 isExternal : Boolean ,
559559 metaState : Int ,
560- deviceId : Int
560+ deviceId : Int ,
561+ scanCode : Int = 0
561562 ): Boolean {
562563 if (! mDetectKeymaps) return false
563564
@@ -587,8 +588,8 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
587588 }
588589
589590 when (action) {
590- KeyEvent .ACTION_DOWN -> return onKeyDown(event, deviceId)
591- KeyEvent .ACTION_UP -> return onKeyUp(event, deviceId)
591+ KeyEvent .ACTION_DOWN -> return onKeyDown(event, deviceId, scanCode )
592+ KeyEvent .ACTION_UP -> return onKeyUp(event, deviceId, scanCode )
592593 }
593594
594595 return false
@@ -597,7 +598,7 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
597598 /* *
598599 * @return whether to consume the [KeyEvent].
599600 */
600- private fun onKeyDown (event : Event , deviceId : Int ): Boolean {
601+ private fun onKeyDown (event : Event , deviceId : Int , scanCode : Int ): Boolean {
601602
602603 mEventDownTimeMap[event] = currentTime
603604
@@ -763,17 +764,23 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
763764 }
764765 }
765766
766- if (mModifierKeyEventActions && ! isModifierKeyCode && mMetaStateFromActions != 0
767+ if (mModifierKeyEventActions
768+ && ! isModifierKeyCode
769+ && mMetaStateFromActions != 0
767770 && ! mappedToParallelTriggerAction) {
768771
769772 consumeEvent = true
770- mUnmappedKeycodesToConsumeOnUp .add(event.keyCode)
773+ keyCodesToImitateUpAction .add(event.keyCode)
771774
772- imitateButtonPress.value = ImitateButtonPress (event.keyCode,
773- mMetaStateFromKeyEvent.withFlag(mMetaStateFromActions), deviceId)
775+ imitateButtonPress.value = ImitateButtonPress (
776+ event.keyCode,
777+ mMetaStateFromKeyEvent.withFlag(mMetaStateFromActions),
778+ deviceId,
779+ KeyEventAction .DOWN ,
780+ scanCode)
774781
775782 mCoroutineScope.launch {
776- repeatImitatingKey(event.keyCode, deviceId)
783+ repeatImitatingKey(event.keyCode, deviceId, scanCode )
777784 }
778785 }
779786
@@ -915,14 +922,15 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
915922 /* *
916923 * @return whether to consume the event.
917924 */
918- private fun onKeyUp (event : Event , deviceId : Int ): Boolean {
925+ private fun onKeyUp (event : Event , deviceId : Int , scanCode : Int ): Boolean {
919926 val keyCode = event.keyCode
920927
921928 val downTime = mEventDownTimeMap[event] ? : currentTime
922929 mEventDownTimeMap.remove(event)
923930
924931 var consumeEvent = false
925- var imitateButtonPress = false
932+ var imitateDownUpKeyEvent = false
933+ var imitateUpKeyEvent = false
926934
927935 var successfulLongPress = false
928936 var successfulDoublePress = false
@@ -940,9 +948,12 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
940948
941949 val imitateKeyAfterDoublePressTimeout = mutableListOf<Long >()
942950
943- if (mUnmappedKeycodesToConsumeOnUp.contains(keyCode)) {
951+ var metaStateFromActionsToRemove = 0
952+
953+ if (keyCodesToImitateUpAction.contains(keyCode)) {
944954 consumeEvent = true
945- mUnmappedKeycodesToConsumeOnUp.remove(keyCode)
955+ imitateUpKeyEvent = true
956+ keyCodesToImitateUpAction.remove(keyCode)
946957 }
947958
948959 if (mDetectSequenceDoublePresses) {
@@ -1000,7 +1011,7 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
10001011 successfulLongPress = true
10011012 } else if (mDetectSequenceLongPresses &&
10021013 mLongPressSequenceEvents.any { it.first.matchesEvent(event.withLongPress) }) {
1003- imitateButtonPress = true
1014+ imitateDownUpKeyEvent = true
10041015 }
10051016
10061017 val encodedEventWithClickType = when {
@@ -1127,12 +1138,12 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
11271138 longPressSingleKeyTriggerJustReleased = true
11281139 }
11291140
1130- if (! imitateButtonPress ) {
1141+ if (! imitateDownUpKeyEvent ) {
11311142 if (singleKeyTrigger && ! successfulLongPress) {
1132- imitateButtonPress = true
1143+ imitateDownUpKeyEvent = true
11331144 } else if (lastMatchedIndex > - 1 &&
11341145 lastMatchedIndex < mParallelTriggerEvents[triggerIndex].lastIndex) {
1135- imitateButtonPress = true
1146+ imitateDownUpKeyEvent = true
11361147 }
11371148 }
11381149 }
@@ -1145,6 +1156,7 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
11451156 }
11461157
11471158 mLastMatchedParallelEventIndices[triggerIndex] = lastHeldDownEventIndex
1159+ mMetaStateFromActions = mMetaStateFromActions.minusFlag(metaStateFromActionsToRemove)
11481160
11491161 // cancel repeating action jobs for this trigger
11501162 if (lastHeldDownEventIndex != mParallelTriggerEvents[triggerIndex].lastIndex) {
@@ -1272,18 +1284,32 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
12721284 return @launch
12731285 }
12741286
1275- this @KeymapDetectionDelegate.imitateButtonPress.value = ImitateButtonPress (keyCode)
1287+ this @KeymapDetectionDelegate.imitateButtonPress.value =
1288+ ImitateButtonPress (keyCode, keyEventAction = KeyEventAction .DOWN_UP , scanCode = scanCode)
12761289 }
12771290 }
12781291 }
12791292 // only imitate a key if an action isn't going to be performed
1280- else if (imitateButtonPress
1293+ else if ((imitateDownUpKeyEvent || imitateUpKeyEvent)
12811294 && detectedSequenceTriggerIndexes.isEmpty()
12821295 && detectedParallelTriggerIndexes.isEmpty()
12831296 && ! shortPressSingleKeyTriggerJustReleased
12841297 && ! mappedToDoublePress) {
12851298
1286- this .imitateButtonPress.value = ImitateButtonPress (keyCode)
1299+ val keyEventAction = if (imitateUpKeyEvent) {
1300+ KeyEventAction .UP
1301+ } else {
1302+ KeyEventAction .DOWN_UP
1303+ }
1304+
1305+ this .imitateButtonPress.value = ImitateButtonPress (
1306+ keyCode,
1307+ mMetaStateFromKeyEvent.withFlag(mMetaStateFromActions),
1308+ deviceId,
1309+ keyEventAction,
1310+ scanCode)
1311+
1312+ keyCodesToImitateUpAction.remove(event.keyCode)
12871313 }
12881314
12891315 return consumeEvent
@@ -1319,7 +1345,7 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
13191345
13201346 mMetaStateFromActions = 0
13211347 mMetaStateFromKeyEvent = 0
1322- mUnmappedKeycodesToConsumeOnUp = mutableSetOf ()
1348+ keyCodesToImitateUpAction = mutableSetOf ()
13231349
13241350 mRepeatJobs.valueIterator().forEach {
13251351 it.forEach { job ->
@@ -1420,12 +1446,16 @@ class KeymapDetectionDelegate(private val mCoroutineScope: CoroutineScope,
14201446 throw Exception (" Action $action not in the action map!" )
14211447 }
14221448
1423- private suspend fun repeatImitatingKey (keyCode : Int , deviceId : Int ) {
1449+ private suspend fun repeatImitatingKey (keyCode : Int , deviceId : Int , scanCode : Int ) {
14241450 delay(400 )
14251451
1426- while (mUnmappedKeycodesToConsumeOnUp.contains(keyCode)) {
1427- imitateButtonPress.postValue(ImitateButtonPress (keyCode,
1428- mMetaStateFromKeyEvent.withFlag(mMetaStateFromActions), deviceId))
1452+ while (keyCodesToImitateUpAction.contains(keyCode)) {
1453+ imitateButtonPress.postValue(ImitateButtonPress (
1454+ keyCode,
1455+ mMetaStateFromKeyEvent.withFlag(mMetaStateFromActions),
1456+ deviceId,
1457+ KeyEventAction .DOWN ,
1458+ scanCode)) // use down action because this is what Android does
14291459
14301460 delay(50 )
14311461 }
0 commit comments