From b3125be8ddba7ea3382d6f7c413e7b9bcc7a2763 Mon Sep 17 00:00:00 2001 From: sds100 Date: Sun, 6 Oct 2024 10:54:46 +0200 Subject: [PATCH] #1274 wip: support assistant trigger in keymapcontroller --- .../keymaps/detection/KeyMapController.kt | 31 ++-- .../mappings/keymaps/ConfigKeyMapUseCase.kt | 138 ++++++++++------- .../mappings/keymaps/DisplayKeyMapUseCase.kt | 7 +- .../keymapper/mappings/keymaps/KeyMap.kt | 21 ++- .../mappings/keymaps/KeyMapListItemCreator.kt | 144 +++++++++++------- .../keymaps/trigger/AssistantTriggerKey.kt | 6 +- .../trigger/BaseConfigTriggerViewModel.kt | 41 +++-- .../trigger/ConfigTriggerKeyViewModel.kt | 11 +- .../keymaps/trigger/KeyCodeTriggerKey.kt | 47 +++--- .../mappings/keymaps/trigger/TriggerKey.kt | 30 ++-- .../keymaps/trigger/TriggerKeyDevice.kt | 12 +- .../keymaps/trigger/TriggerKeyListItem.kt | 1 - .../BaseAccessibilityServiceController.kt | 16 +- app/src/main/res/values/strings.xml | 5 + .../keymapper/ConfigKeyMapUseCaseTest.kt | 8 +- .../data/repositories/KeyMapRepositoryTest.kt | 1 - .../mappings/keymaps/KeyMapControllerTest.kt | 72 +++++---- .../sds100/keymapper/util/KeyMapUtils.kt | 9 +- 18 files changed, 367 insertions(+), 233 deletions(-) rename app/src/{main => free}/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt (98%) diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt b/app/src/free/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt similarity index 98% rename from app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt rename to app/src/free/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt index 1823999456..36e5ff4df4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt +++ b/app/src/free/java/io/github/sds100/keymapper/mappings/keymaps/detection/KeyMapController.kt @@ -1492,21 +1492,22 @@ class KeyMapController( this.clickType == event.clickType } - private fun KeyCodeTriggerKey.matchesWithOtherKey(otherKey: KeyCodeTriggerKey): Boolean = when (this.device) { - TriggerKeyDevice.Any -> - this.keyCode == otherKey.keyCode && - this.clickType == otherKey.clickType - - is TriggerKeyDevice.External -> - this.keyCode == otherKey.keyCode && - this.device == otherKey.device && - this.clickType == otherKey.clickType - - TriggerKeyDevice.Internal -> - this.keyCode == otherKey.keyCode && - otherKey.device == TriggerKeyDevice.Internal && - this.clickType == otherKey.clickType - } + private fun KeyCodeTriggerKey.matchesWithOtherKey(otherKey: KeyCodeTriggerKey): Boolean = + when (this.device) { + TriggerKeyDevice.Any -> + this.keyCode == otherKey.keyCode && + this.clickType == otherKey.clickType + + is TriggerKeyDevice.External -> + this.keyCode == otherKey.keyCode && + this.device == otherKey.device && + this.clickType == otherKey.clickType + + TriggerKeyDevice.Internal -> + this.keyCode == otherKey.keyCode && + otherKey.device == TriggerKeyDevice.Internal && + this.clickType == otherKey.clickType + } private fun longPressDelay(trigger: Trigger): Long = trigger.longPressDelay?.toLong() ?: defaultLongPressDelay.value diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt index 9c2089a8cf..bfeaae44ec 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/ConfigKeyMapUseCase.kt @@ -9,8 +9,11 @@ import io.github.sds100.keymapper.data.repositories.PreferenceRepository import io.github.sds100.keymapper.mappings.BaseConfigMappingUseCase import io.github.sds100.keymapper.mappings.ClickType import io.github.sds100.keymapper.mappings.ConfigMappingUseCase +import io.github.sds100.keymapper.mappings.keymaps.trigger.AssistantTriggerKey +import io.github.sds100.keymapper.mappings.keymaps.trigger.AssistantTriggerType import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.Trigger +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode import io.github.sds100.keymapper.system.devices.DevicesAdapter @@ -38,36 +41,51 @@ class ConfigKeyMapUseCaseImpl( private val showDeviceDescriptors: Flow = preferenceRepository.get(Keys.showDeviceDescriptors).map { it ?: false } - override fun addTriggerKey( - keyCode: Int, - device: TriggerKeyDevice, - ) = editTrigger { trigger -> + override fun addAssistantTriggerKey(type: AssistantTriggerType) = editTrigger { trigger -> val clickType = when (trigger.mode) { is TriggerMode.Parallel -> trigger.mode.clickType TriggerMode.Sequence -> ClickType.SHORT_PRESS TriggerMode.Undefined -> ClickType.SHORT_PRESS } - val containsKey = trigger.keys.any { keyToCompare -> - if (trigger.mode != TriggerMode.Sequence) { - val sameKeyCode = keyCode == keyToCompare.keyCode + // Check whether the trigger already contains the key because if so + // then it must be converted to a sequence trigger. + val containsKey = trigger.keys.any { it is AssistantTriggerKey } - // if the new key is not external, check whether a trigger key already exists for this device - val sameDevice = when { - keyToCompare.device is TriggerKeyDevice.External && - device is TriggerKeyDevice.External -> - keyToCompare.device.descriptor == device.descriptor + val triggerKey = AssistantTriggerKey(type = type, clickType = clickType) - else -> true - } + val newKeys = trigger.keys.plus(triggerKey) - sameKeyCode && sameDevice - } else { - false - } + val newMode = when { + trigger.mode != TriggerMode.Sequence && containsKey -> TriggerMode.Sequence + newKeys.size <= 1 -> TriggerMode.Undefined + + /* Automatically make it a parallel trigger when the user makes a trigger with more than one key + because this is what most users are expecting when they make a trigger with multiple keys */ + newKeys.size == 2 && !containsKey -> TriggerMode.Parallel(newKeys[0].clickType) + else -> trigger.mode + } + + trigger.copy(keys = newKeys, mode = newMode) + } + + override fun addKeyCodeTriggerKey( + keyCode: Int, + device: TriggerKeyDevice, + ) = editTrigger { trigger -> + val clickType = when (trigger.mode) { + is TriggerMode.Parallel -> trigger.mode.clickType + TriggerMode.Sequence -> ClickType.SHORT_PRESS + TriggerMode.Undefined -> ClickType.SHORT_PRESS } - val newKeys = trigger.keys.toMutableList() + // Check whether the trigger already contains the key because if so + // then it must be converted to a sequence trigger. + val containsKey = trigger.keys + .mapNotNull { it as? KeyCodeTriggerKey } + .any { keyToCompare -> + keyToCompare.keyCode == keyCode && keyToCompare.device.isSameDevice(device) + } var consumeKeyEvent = true @@ -80,18 +98,18 @@ class ConfigKeyMapUseCaseImpl( keyCode = keyCode, device = device, clickType = clickType, - consumeKeyEvent = consumeKeyEvent, + consumeEvent = consumeKeyEvent, ) - newKeys.add(triggerKey) + val newKeys = trigger.keys.plus(triggerKey) val newMode = when { - containsKey -> TriggerMode.Sequence + trigger.mode != TriggerMode.Sequence && containsKey -> TriggerMode.Sequence newKeys.size <= 1 -> TriggerMode.Undefined /* Automatically make it a parallel trigger when the user makes a trigger with more than one key because this is what most users are expecting when they make a trigger with multiple keys */ - newKeys.size == 2 && !containsKey -> TriggerMode.Parallel(clickType) + newKeys.size == 2 && !containsKey -> TriggerMode.Parallel(triggerKey.clickType) else -> trigger.mode } @@ -120,7 +138,9 @@ class ConfigKeyMapUseCaseImpl( } override fun setParallelTriggerMode() = editTrigger { trigger -> - if (trigger.mode is TriggerMode.Parallel) return@editTrigger trigger + if (trigger.mode is TriggerMode.Parallel) { + return@editTrigger trigger + } // undefined mode only allowed if one or no keys if (trigger.keys.size <= 1) { @@ -128,19 +148,19 @@ class ConfigKeyMapUseCaseImpl( } val oldKeys = trigger.keys - var newKeys = oldKeys.toMutableList() - - if (trigger.mode !is TriggerMode.Parallel) { - // set all the keys to a short press if coming from a non-parallel trigger - // because they must all be the same click type and can't all be double pressed - newKeys = newKeys.map { key -> - key.copy(clickType = ClickType.SHORT_PRESS) - }.toMutableList() + var newKeys = oldKeys + // set all the keys to a short press if coming from a non-parallel trigger + // because they must all be the same click type and can't all be double pressed + newKeys = newKeys + .map { key -> key.setClickType(clickType = ClickType.SHORT_PRESS) } // remove duplicates of keys that have the same keycode and device id - newKeys = - newKeys.distinctBy { Pair(it.keyCode, it.device) }.toMutableList() - } + .distinctBy { key -> + when (key) { + is AssistantTriggerKey -> key.type + is KeyCodeTriggerKey -> Pair(key.keyCode, key.device) + } + } val newMode = if (newKeys.size <= 1) { TriggerMode.Undefined @@ -178,7 +198,7 @@ class ConfigKeyMapUseCaseImpl( return@editTrigger oldTrigger } - val newKeys = oldTrigger.keys.map { it.copy(clickType = ClickType.SHORT_PRESS) } + val newKeys = oldTrigger.keys.map { it.setClickType(clickType = ClickType.SHORT_PRESS) } val newMode = if (newKeys.size <= 1) { TriggerMode.Undefined } else { @@ -189,50 +209,65 @@ class ConfigKeyMapUseCaseImpl( } override fun setTriggerLongPress() { - editTrigger { oldTrigger -> - if (oldTrigger.mode == TriggerMode.Sequence) { - return@editTrigger oldTrigger + editTrigger { trigger -> + if (trigger.mode == TriggerMode.Sequence) { + return@editTrigger trigger + } + + // You can't set the trigger to a long press if it contains a key + // that isn't detected with key codes. This is because there aren't + // separate key events for the up and down press that can be timed. + if (trigger.keys.any { it !is KeyCodeTriggerKey }) { + return@editTrigger trigger } - val newKeys = oldTrigger.keys.map { it.copy(clickType = ClickType.LONG_PRESS) } + val newKeys = trigger.keys.map { it.setClickType(clickType = ClickType.LONG_PRESS) } val newMode = if (newKeys.size <= 1) { TriggerMode.Undefined } else { TriggerMode.Parallel(ClickType.LONG_PRESS) } - oldTrigger.copy(keys = newKeys, mode = newMode) + trigger.copy(keys = newKeys, mode = newMode) } } override fun setTriggerDoublePress() { - editTrigger { oldTrigger -> - if (oldTrigger.mode != TriggerMode.Undefined) { - return@editTrigger oldTrigger + editTrigger { trigger -> + if (trigger.mode != TriggerMode.Undefined) { + return@editTrigger trigger } - val newKeys = oldTrigger.keys.map { it.copy(clickType = ClickType.DOUBLE_PRESS) } + val newKeys = trigger.keys.map { it.setClickType(clickType = ClickType.DOUBLE_PRESS) } val newMode = TriggerMode.Undefined - oldTrigger.copy(keys = newKeys, mode = newMode) + trigger.copy(keys = newKeys, mode = newMode) } } override fun setTriggerKeyClickType(keyUid: String, clickType: ClickType) { editTriggerKey(keyUid) { - it.copy(clickType = clickType) + it.setClickType(clickType = clickType) } } override fun setTriggerKeyDevice(keyUid: String, device: TriggerKeyDevice) { editTriggerKey(keyUid) { - it.copy(device = device) + if (it is KeyCodeTriggerKey) { + it.copy(device = device) + } else { + it + } } } override fun setTriggerKeyConsumeKeyEvent(keyUid: String, consumeKeyEvent: Boolean) { editTriggerKey(keyUid) { - it.copy(consumeKeyEvent = consumeKeyEvent) + if (it is KeyCodeTriggerKey) { + it.copy(consumeEvent = consumeKeyEvent) + } else { + it + } } } @@ -443,7 +478,7 @@ class ConfigKeyMapUseCaseImpl( } } - private fun editTriggerKey(uid: String, block: (key: KeyCodeTriggerKey) -> KeyCodeTriggerKey) { + private fun editTriggerKey(uid: String, block: (key: TriggerKey) -> TriggerKey) { editTrigger { oldTrigger -> val newKeys = oldTrigger.keys.map { if (it.uid == uid) { @@ -464,7 +499,8 @@ class ConfigKeyMapUseCaseImpl( interface ConfigKeyMapUseCase : ConfigMappingUseCase { // trigger - fun addTriggerKey(keyCode: Int, device: TriggerKeyDevice) + fun addKeyCodeTriggerKey(keyCode: Int, device: TriggerKeyDevice) + fun addAssistantTriggerKey(type: AssistantTriggerType) fun removeTriggerKey(uid: String) fun moveTriggerKey(fromIndex: Int, toIndex: Int) diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt index 849db6ef5b..e97ed6f0f1 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/DisplayKeyMapUseCase.kt @@ -5,6 +5,7 @@ import android.view.KeyEvent import io.github.sds100.keymapper.data.Keys import io.github.sds100.keymapper.data.repositories.PreferenceRepository import io.github.sds100.keymapper.mappings.DisplaySimpleMappingUseCase +import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerError import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter import io.github.sds100.keymapper.system.inputmethod.KeyMapperImeHelper @@ -49,7 +50,11 @@ class DisplayKeyMapUseCaseImpl( errors.add(TriggerError.CANT_DETECT_IN_PHONE_CALL) } - if (trigger.keys.any { it.keyCode in keysThatRequireDndAccess }) { + val requiresDndAccess = trigger.keys + .mapNotNull { it as? KeyCodeTriggerKey } + .any { it.keyCode in keysThatRequireDndAccess } + + if (requiresDndAccess) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !permissionAdapter.isGranted(Permission.ACCESS_NOTIFICATION_POLICY) ) { diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt index 65284bd306..edf866e9d6 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMap.kt @@ -9,6 +9,7 @@ import io.github.sds100.keymapper.constraints.ConstraintState import io.github.sds100.keymapper.data.entities.KeyMapEntity import io.github.sds100.keymapper.mappings.Mapping import io.github.sds100.keymapper.mappings.keymaps.detection.KeyMapController +import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.Trigger import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerEntityMapper import kotlinx.serialization.Serializable @@ -62,13 +63,25 @@ data class KeyMap( } /** - * @return whether this key map requires an input method to send the key events - * because otherwise it won't be detected. + * Whether this key map requires an input method to detect the key events. + * If the key map needs to answer or end a call then it must use an input method to detect + * the key events because volume key events are not sent to accessibility services when a call + * is incoming. */ -fun KeyMap.requiresImeKeyEventForwarding(): Boolean = - trigger.keys.any { it.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || it.keyCode == KeyEvent.KEYCODE_VOLUME_UP } && +fun KeyMap.requiresImeKeyEventForwarding(): Boolean { + val hasPhoneCallAction = actionList.any { it.data is ActionData.AnswerCall || it.data is ActionData.EndCall } + val hasVolumeKeys = trigger.keys + .mapNotNull { it as? KeyCodeTriggerKey } + .any { + it.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || + it.keyCode == KeyEvent.KEYCODE_VOLUME_UP + } + + return hasVolumeKeys && hasPhoneCallAction +} + object KeyMapEntityMapper { fun fromEntity(entity: KeyMapEntity): KeyMap { val actionList = entity.actionList.mapNotNull { KeymapActionEntityMapper.fromEntity(it) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt index 0e4ece49bb..3491f35ace 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapListItemCreator.kt @@ -3,6 +3,9 @@ package io.github.sds100.keymapper.mappings.keymaps import io.github.sds100.keymapper.R import io.github.sds100.keymapper.mappings.BaseMappingListItemCreator import io.github.sds100.keymapper.mappings.ClickType +import io.github.sds100.keymapper.mappings.keymaps.trigger.AssistantTriggerKey +import io.github.sds100.keymapper.mappings.keymaps.trigger.AssistantTriggerType +import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.Trigger import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerError import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice @@ -25,13 +28,17 @@ class KeyMapListItemCreator( KeyMapActionUiHelper(displayMapping, resourceProvider), resourceProvider, ) { + private val midDot by lazy { getString(R.string.middot) } + private val longPressString by lazy { getString(R.string.clicktype_long_press) } + private val doublePressString by lazy { getString(R.string.clicktype_double_press) } + private val anyAssistantString by lazy { getString(R.string.assistant_any_trigger_name) } + private val voiceAssistantString by lazy { getString(R.string.assistant_voice_trigger_name) } + private val deviceAssistantString by lazy { getString(R.string.assistant_device_trigger_name) } suspend fun create( keyMap: KeyMap, showDeviceDescriptors: Boolean, ): KeyMapListItem.KeyMapUiState { - val midDot = getString(R.string.middot) - val triggerDescription = buildString { val separator = when (keyMap.trigger.mode) { is TriggerMode.Parallel -> getString(R.string.plus) @@ -39,46 +46,15 @@ class KeyMapListItemCreator( is TriggerMode.Undefined -> null } - val longPressString = getString(R.string.clicktype_long_press) - val doublePressString = getString(R.string.clicktype_double_press) - keyMap.trigger.keys.forEachIndexed { index, key -> if (index > 0) { append(" $separator ") } - when (key.clickType) { - ClickType.LONG_PRESS -> append(longPressString).append(" ") - ClickType.DOUBLE_PRESS -> append(doublePressString).append(" ") - else -> Unit - } - - append(KeyEventUtils.keyCodeToString(key.keyCode)) - - val deviceName = when (key.device) { - is TriggerKeyDevice.Internal -> getString(R.string.this_device) - is TriggerKeyDevice.Any -> getString(R.string.any_device) - is TriggerKeyDevice.External -> { - if (showDeviceDescriptors) { - InputDeviceUtils.appendDeviceDescriptorToName( - key.device.descriptor, - key.device.name, - ) - } else { - key.device.name - } - } - } - - append(" (") - - append(deviceName) - - if (!key.consumeKeyEvent) { - append(" $midDot ${getString(R.string.flag_dont_override_default_action)}") + when (key) { + is AssistantTriggerKey -> appendAssistantTriggerKeyName(key) + is KeyCodeTriggerKey -> appendKeyCodeTriggerKeyName(key, showDeviceDescriptors) } - - append(")") } } @@ -109,28 +85,7 @@ class KeyMapListItemCreator( val triggerErrors = displayMapping.getTriggerErrors(keyMap) - val triggerErrorChips = triggerErrors.map { - when (it) { - TriggerError.DND_ACCESS_DENIED -> - ChipUi.Error( - id = TriggerError.DND_ACCESS_DENIED.toString(), - text = getString(R.string.trigger_error_dnd_access_denied_short), - error = Error.PermissionDenied(Permission.ACCESS_NOTIFICATION_POLICY), - ) - - TriggerError.SCREEN_OFF_ROOT_DENIED -> ChipUi.Error( - id = TriggerError.SCREEN_OFF_ROOT_DENIED.toString(), - text = getString(R.string.trigger_error_screen_off_root_permission_denied_short), - error = Error.PermissionDenied(Permission.ROOT), - ) - - TriggerError.CANT_DETECT_IN_PHONE_CALL -> ChipUi.Error( - id = TriggerError.SCREEN_OFF_ROOT_DENIED.toString(), - text = getString(R.string.trigger_error_cant_detect_in_phone_call), - error = Error.CantDetectKeyEventsInPhoneCall, - ) - } - } + val triggerErrorChips = triggerErrors.map(this::getTriggerChipError) return KeyMapListItem.KeyMapUiState( uid = keyMap.uid, @@ -143,6 +98,79 @@ class KeyMapListItemCreator( ) } + private fun getTriggerChipError(error: TriggerError): ChipUi.Error = + when (error) { + TriggerError.DND_ACCESS_DENIED -> + ChipUi.Error( + id = TriggerError.DND_ACCESS_DENIED.toString(), + text = getString(R.string.trigger_error_dnd_access_denied_short), + error = Error.PermissionDenied(Permission.ACCESS_NOTIFICATION_POLICY), + ) + + TriggerError.SCREEN_OFF_ROOT_DENIED -> ChipUi.Error( + id = TriggerError.SCREEN_OFF_ROOT_DENIED.toString(), + text = getString(R.string.trigger_error_screen_off_root_permission_denied_short), + error = Error.PermissionDenied(Permission.ROOT), + ) + + TriggerError.CANT_DETECT_IN_PHONE_CALL -> ChipUi.Error( + id = TriggerError.SCREEN_OFF_ROOT_DENIED.toString(), + text = getString(R.string.trigger_error_cant_detect_in_phone_call), + error = Error.CantDetectKeyEventsInPhoneCall, + ) + } + + private fun StringBuilder.appendKeyCodeTriggerKeyName( + key: KeyCodeTriggerKey, + showDeviceDescriptors: Boolean, + ) { + when (key.clickType) { + ClickType.LONG_PRESS -> append(longPressString).append(" ") + ClickType.DOUBLE_PRESS -> append(doublePressString).append(" ") + else -> Unit + } + + append(KeyEventUtils.keyCodeToString(key.keyCode)) + + val deviceName = when (key.device) { + is TriggerKeyDevice.Internal -> getString(R.string.this_device) + is TriggerKeyDevice.Any -> getString(R.string.any_device) + is TriggerKeyDevice.External -> { + if (showDeviceDescriptors) { + InputDeviceUtils.appendDeviceDescriptorToName( + key.device.descriptor, + key.device.name, + ) + } else { + key.device.name + } + } + } + + append(" (") + + append(deviceName) + + if (!key.consumeEvent) { + append(" $midDot ${getString(R.string.flag_dont_override_default_action)}") + } + + append(")") + } + + private fun StringBuilder.appendAssistantTriggerKeyName(key: AssistantTriggerKey) { + when (key.clickType) { + ClickType.DOUBLE_PRESS -> append(doublePressString).append(" ") + else -> Unit + } + + when (key.type) { + AssistantTriggerType.ANY -> append(anyAssistantString) + AssistantTriggerType.VOICE -> append(voiceAssistantString) + AssistantTriggerType.DEVICE -> append(deviceAssistantString) + } + } + private fun getTriggerOptionLabels(trigger: Trigger): List { val labels = mutableListOf() diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/AssistantTriggerKey.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/AssistantTriggerKey.kt index b2effb48c0..a5fe9dce05 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/AssistantTriggerKey.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/AssistantTriggerKey.kt @@ -11,10 +11,12 @@ data class AssistantTriggerKey( override val uid: String = UUID.randomUUID().toString(), val type: AssistantTriggerType, override val clickType: ClickType, - - val consumeKeyEvent: Boolean = true, ) : TriggerKey() { + // This is always true for an assistant key event because Key Mapper can't forward the + // assistant event to another app (or can it??). + override val consumeEvent: Boolean = true + companion object { fun fromEntity( entity: AssistantTriggerKeyEntity, diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/BaseConfigTriggerViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/BaseConfigTriggerViewModel.kt index f1723376c7..048e5b09ae 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/BaseConfigTriggerViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/BaseConfigTriggerViewModel.kt @@ -227,7 +227,7 @@ abstract class BaseConfigTriggerViewModel( showPopup("screen_pinning_message", dialog) } - config.addTriggerKey(it.keyCode, it.device) + config.addKeyCodeTriggerKey(it.keyCode, it.device) }.launchIn(coroutineScope) coroutineScope.launch { @@ -415,15 +415,6 @@ abstract class BaseConfigTriggerViewModel( showDeviceDescriptors: Boolean, ): List = trigger.keys.mapIndexed { index, key -> - val extraInfo = buildString { - append(getTriggerKeyDeviceName(key.device, showDeviceDescriptors)) - - if (!key.consumeKeyEvent) { - val midDot = getString(R.string.middot) - append(" $midDot ${getString(R.string.flag_dont_override_default_action)}") - } - } - val clickTypeString = when (key.clickType) { ClickType.SHORT_PRESS -> null ClickType.LONG_PRESS -> getString(R.string.clicktype_long_press) @@ -438,15 +429,39 @@ abstract class BaseConfigTriggerViewModel( TriggerKeyListItem( id = key.uid, - keyCode = key.keyCode, - name = KeyEventUtils.keyCodeToString(key.keyCode), + name = getTriggerKeyName(key), clickTypeString = clickTypeString, - extraInfo = extraInfo, + extraInfo = getTriggerKeyExtraInfo(key, showDeviceDescriptors), linkType = linkDrawable, isDragDropEnabled = trigger.keys.size > 1, ) } + private fun getTriggerKeyExtraInfo(key: TriggerKey, showDeviceDescriptors: Boolean): String? { + if (key !is KeyCodeTriggerKey) { + return null + } + + return buildString { + append(getTriggerKeyDeviceName(key.device, showDeviceDescriptors)) + + if (!key.consumeEvent) { + val midDot = getString(R.string.middot) + append(" $midDot ${getString(R.string.flag_dont_override_default_action)}") + } + } + } + + private fun getTriggerKeyName(key: TriggerKey): String = when (key) { + is AssistantTriggerKey -> when (key.type) { + AssistantTriggerType.ANY -> getString(R.string.assistant_any_trigger_name) + AssistantTriggerType.VOICE -> getString(R.string.assistant_voice_trigger_name) + AssistantTriggerType.DEVICE -> getString(R.string.assistant_device_trigger_name) + } + + is KeyCodeTriggerKey -> KeyEventUtils.keyCodeToString(key.keyCode) + } + private fun getTriggerKeyDeviceName( device: TriggerKeyDevice, showDeviceDescriptors: Boolean, diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt index 63e71fbe77..c25a3bff47 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/ConfigTriggerKeyViewModel.kt @@ -84,12 +84,16 @@ class ConfigTriggerKeyViewModel( triggerKeyUid.value = uid } - private fun createListItems(triggerMode: TriggerMode, key: KeyCodeTriggerKey): List = - sequence { + private fun createListItems(triggerMode: TriggerMode, key: TriggerKey): List { + if (key !is KeyCodeTriggerKey) { + return emptyList() + } + + return sequence { yield( CheckBoxListItem( id = ID_DONT_CONSUME_KEY_EVENT, - isChecked = !key.consumeKeyEvent, + isChecked = !key.consumeEvent, label = getString(R.string.flag_dont_override_default_action), ), ) @@ -115,4 +119,5 @@ class ConfigTriggerKeyViewModel( ) } }.toList() + } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/KeyCodeTriggerKey.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/KeyCodeTriggerKey.kt index 5c011179be..5c5bdcd926 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/KeyCodeTriggerKey.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/KeyCodeTriggerKey.kt @@ -14,8 +14,7 @@ data class KeyCodeTriggerKey( val keyCode: Int, val device: TriggerKeyDevice, override val clickType: ClickType, - - val consumeKeyEvent: Boolean = true, + override val consumeEvent: Boolean = true, ) : TriggerKey() { override fun toString(): String { @@ -24,31 +23,29 @@ data class KeyCodeTriggerKey( is TriggerKeyDevice.External -> "external" TriggerKeyDevice.Internal -> "internal" } - return "KeyCodeTriggerKey(uid=${uid.substring(0..5)}, keyCode=$keyCode, device=$deviceString, clickType=$clickType, consume=$consumeKeyEvent) " + return "KeyCodeTriggerKey(uid=${uid.substring(0..5)}, keyCode=$keyCode, device=$deviceString, clickType=$clickType, consume=$consumeEvent) " } companion object { - fun fromEntity(entity: KeyCodeTriggerKeyEntity): TriggerKey { - return KeyCodeTriggerKey( - uid = entity.uid, - keyCode = entity.keyCode, - device = when (entity.deviceId) { - KeyCodeTriggerKeyEntity.DEVICE_ID_THIS_DEVICE -> TriggerKeyDevice.Internal - KeyCodeTriggerKeyEntity.DEVICE_ID_ANY_DEVICE -> TriggerKeyDevice.Any - else -> TriggerKeyDevice.External( - entity.deviceId, - entity.deviceName ?: "", - ) - }, - clickType = when (entity.clickType) { - TriggerKeyEntity.SHORT_PRESS -> ClickType.SHORT_PRESS - TriggerKeyEntity.LONG_PRESS -> ClickType.LONG_PRESS - TriggerKeyEntity.DOUBLE_PRESS -> ClickType.DOUBLE_PRESS - else -> ClickType.SHORT_PRESS - }, - consumeKeyEvent = !entity.flags.hasFlag(KeyCodeTriggerKeyEntity.FLAG_DO_NOT_CONSUME_KEY_EVENT), - ) - } + fun fromEntity(entity: KeyCodeTriggerKeyEntity): TriggerKey = KeyCodeTriggerKey( + uid = entity.uid, + keyCode = entity.keyCode, + device = when (entity.deviceId) { + KeyCodeTriggerKeyEntity.DEVICE_ID_THIS_DEVICE -> TriggerKeyDevice.Internal + KeyCodeTriggerKeyEntity.DEVICE_ID_ANY_DEVICE -> TriggerKeyDevice.Any + else -> TriggerKeyDevice.External( + entity.deviceId, + entity.deviceName ?: "", + ) + }, + clickType = when (entity.clickType) { + TriggerKeyEntity.SHORT_PRESS -> ClickType.SHORT_PRESS + TriggerKeyEntity.LONG_PRESS -> ClickType.LONG_PRESS + TriggerKeyEntity.DOUBLE_PRESS -> ClickType.DOUBLE_PRESS + else -> ClickType.SHORT_PRESS + }, + consumeEvent = !entity.flags.hasFlag(KeyCodeTriggerKeyEntity.FLAG_DO_NOT_CONSUME_KEY_EVENT), + ) fun toEntity(key: KeyCodeTriggerKey): KeyCodeTriggerKeyEntity { val deviceId = when (key.device) { @@ -71,7 +68,7 @@ data class KeyCodeTriggerKey( var flags = 0 - if (!key.consumeKeyEvent) { + if (!key.consumeEvent) { flags = flags.withFlag(KeyCodeTriggerKeyEntity.FLAG_DO_NOT_CONSUME_KEY_EVENT) } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt index 84c58954a2..27a5d49b51 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKey.kt @@ -4,24 +4,34 @@ import io.github.sds100.keymapper.data.entities.AssistantTriggerKeyEntity import io.github.sds100.keymapper.data.entities.KeyCodeTriggerKeyEntity import io.github.sds100.keymapper.data.entities.TriggerKeyEntity import io.github.sds100.keymapper.mappings.ClickType +import kotlinx.serialization.Serializable +@Serializable sealed class TriggerKey { abstract val clickType: ClickType + + /** + * Whether the event that triggers this key will be consumed and not passed + * onto subsequent apps. E.g consuming the volume down key event will mean the volume + * doesn't change. + */ + abstract val consumeEvent: Boolean abstract val uid: String companion object { - fun fromEntity(entity: TriggerKeyEntity): TriggerKey { - return when (entity) { - is AssistantTriggerKeyEntity -> AssistantTriggerKey.fromEntity(entity) - is KeyCodeTriggerKeyEntity -> KeyCodeTriggerKey.fromEntity(entity) - } + fun fromEntity(entity: TriggerKeyEntity): TriggerKey = when (entity) { + is AssistantTriggerKeyEntity -> AssistantTriggerKey.fromEntity(entity) + is KeyCodeTriggerKeyEntity -> KeyCodeTriggerKey.fromEntity(entity) } - fun toEntity(key: TriggerKey): TriggerKeyEntity { - return when (key) { - is AssistantTriggerKey -> AssistantTriggerKey.toEntity(key) - is KeyCodeTriggerKey -> KeyCodeTriggerKey.toEntity(key) - } + fun toEntity(key: TriggerKey): TriggerKeyEntity = when (key) { + is AssistantTriggerKey -> AssistantTriggerKey.toEntity(key) + is KeyCodeTriggerKey -> KeyCodeTriggerKey.toEntity(key) } } + + fun setClickType(clickType: ClickType): TriggerKey = when (this) { + is AssistantTriggerKey -> copy(clickType = clickType) + is KeyCodeTriggerKey -> copy(clickType = clickType) + } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyDevice.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyDevice.kt index cb53febc84..0c303265c7 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyDevice.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyDevice.kt @@ -2,10 +2,6 @@ package io.github.sds100.keymapper.mappings.keymaps.trigger import kotlinx.serialization.Serializable -/** - * Created by sds100 on 21/02/2021. - */ - @Serializable sealed class TriggerKeyDevice { @Serializable @@ -16,4 +12,12 @@ sealed class TriggerKeyDevice { @Serializable data class External(val descriptor: String, val name: String) : TriggerKeyDevice() + + fun isSameDevice(other: TriggerKeyDevice): Boolean { + if (other is External && this is External) { + return other.descriptor == this.descriptor + } else { + return true + } + } } diff --git a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyListItem.kt b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyListItem.kt index b741580786..27f5c554b8 100644 --- a/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyListItem.kt +++ b/app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/TriggerKeyListItem.kt @@ -5,7 +5,6 @@ package io.github.sds100.keymapper.mappings.keymaps.trigger */ data class TriggerKeyListItem( val id: String, - val keyCode: Int, val name: String, /** diff --git a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/BaseAccessibilityServiceController.kt b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/BaseAccessibilityServiceController.kt index 9f8d85ab00..fb4267bae4 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/accessibility/BaseAccessibilityServiceController.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/accessibility/BaseAccessibilityServiceController.kt @@ -92,7 +92,7 @@ abstract class BaseAccessibilityServiceController( detectConstraintsUseCase, ) - private val keyMapController = KeyMapController( + val keyMapController = KeyMapController( coroutineScope, detectKeyMapsUseCase, performActionsUseCase, @@ -108,7 +108,7 @@ abstract class BaseAccessibilityServiceController( private val recordingTrigger: Boolean get() = recordingTriggerJob != null && recordingTriggerJob?.isActive == true - private val isPaused: StateFlow = pauseMappingsUseCase.isPaused + val isPaused: StateFlow = pauseMappingsUseCase.isPaused .stateIn(coroutineScope, SharingStarted.Eagerly, false) private val screenOffTriggersEnabled: StateFlow = @@ -320,7 +320,12 @@ abstract class BaseAccessibilityServiceController( return true } - if (!isPaused.value) { + if (isPaused.value) { + when (action) { + KeyEvent.ACTION_DOWN -> Timber.d("Down ${KeyEvent.keyCodeToString(keyCode)} - not filtering because paused, $detailedLogInfo") + KeyEvent.ACTION_UP -> Timber.d("Up ${KeyEvent.keyCodeToString(keyCode)} - not filtering because paused, $detailedLogInfo") + } + } else { try { var consume: Boolean @@ -351,11 +356,6 @@ abstract class BaseAccessibilityServiceController( } catch (e: Exception) { Timber.e(e) } - } else { - when (action) { - KeyEvent.ACTION_DOWN -> Timber.d("Down ${KeyEvent.keyCodeToString(keyCode)} - not filtering because paused, $detailedLogInfo") - KeyEvent.ACTION_UP -> Timber.d("Up ${KeyEvent.keyCodeToString(keyCode)} - not filtering because paused, $detailedLogInfo") - } } return false diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 20b83ce663..78b4ac2a1e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1373,4 +1373,9 @@ https://github.com/bydariogamer Translator (Spanish) + + + Any assistant + Device assistant + Voice assistant diff --git a/app/src/test/java/io/github/sds100/keymapper/ConfigKeyMapUseCaseTest.kt b/app/src/test/java/io/github/sds100/keymapper/ConfigKeyMapUseCaseTest.kt index f412bc7d8d..4a3e07767d 100644 --- a/app/src/test/java/io/github/sds100/keymapper/ConfigKeyMapUseCaseTest.kt +++ b/app/src/test/java/io/github/sds100/keymapper/ConfigKeyMapUseCaseTest.kt @@ -69,12 +69,12 @@ class ConfigKeyMapUseCaseTest { useCase.mapping.value = State.Data(KeyMap()) // WHEN - useCase.addTriggerKey(modifierKeyCode, TriggerKeyDevice.Internal) + useCase.addKeyCodeTriggerKey(modifierKeyCode, TriggerKeyDevice.Internal) // THEN val trigger = useCase.mapping.value.dataOrNull()!!.trigger - assertThat(trigger.keys[0].consumeKeyEvent, `is`(false)) + assertThat(trigger.keys[0].consumeEvent, `is`(false)) } } @@ -88,12 +88,12 @@ class ConfigKeyMapUseCaseTest { useCase.mapping.value = State.Data(KeyMap()) // WHEN - useCase.addTriggerKey(KeyEvent.KEYCODE_A, TriggerKeyDevice.Internal) + useCase.addKeyCodeTriggerKey(KeyEvent.KEYCODE_A, TriggerKeyDevice.Internal) // THEN val trigger = useCase.mapping.value.dataOrNull()!!.trigger - assertThat(trigger.keys[0].consumeKeyEvent, `is`(true)) + assertThat(trigger.keys[0].consumeEvent, `is`(true)) } /** diff --git a/app/src/test/java/io/github/sds100/keymapper/data/repositories/KeyMapRepositoryTest.kt b/app/src/test/java/io/github/sds100/keymapper/data/repositories/KeyMapRepositoryTest.kt index 4a823e6001..e9e2cd0624 100644 --- a/app/src/test/java/io/github/sds100/keymapper/data/repositories/KeyMapRepositoryTest.kt +++ b/app/src/test/java/io/github/sds100/keymapper/data/repositories/KeyMapRepositoryTest.kt @@ -65,7 +65,6 @@ class KeyMapRepositoryTest { repository = RoomKeyMapRepository( mockDao, - devicesAdapter, testScope, dispatchers = TestDispatcherProvider(testDispatcher), ) diff --git a/app/src/test/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapControllerTest.kt b/app/src/test/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapControllerTest.kt index 6121563c7b..2f4b687aef 100644 --- a/app/src/test/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapControllerTest.kt +++ b/app/src/test/java/io/github/sds100/keymapper/mappings/keymaps/KeyMapControllerTest.kt @@ -14,6 +14,7 @@ import io.github.sds100.keymapper.mappings.keymaps.detection.DetectKeyMapsUseCas import io.github.sds100.keymapper.mappings.keymaps.detection.KeyMapController import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.Trigger +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode import io.github.sds100.keymapper.system.camera.CameraLens @@ -2040,7 +2041,7 @@ class KeyMapControllerTest { listOf(KeyMap(0, trigger = trigger, actionList = listOf(TEST_ACTION))) // when - trigger.keys[1].let { + (trigger.keys[1] as KeyCodeTriggerKey).let { inputKeyEvent( it.keyCode, KeyEvent.ACTION_DOWN, @@ -2048,7 +2049,7 @@ class KeyMapControllerTest { ) } - trigger.keys[1].let { + (trigger.keys[1] as KeyCodeTriggerKey).let { val consumed = inputKeyEvent( it.keyCode, KeyEvent.ACTION_UP, @@ -2090,22 +2091,22 @@ class KeyMapControllerTest { listOf(KeyMap(0, trigger = trigger, actionList = listOf(TEST_ACTION))) // when - trigger.keys.forEach { + for (key in trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_DOWN, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) } var consumedUpCount = 0 - trigger.keys.forEach { + for (key in trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { val consumed = inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_UP, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) if (consumed) { @@ -2129,11 +2130,11 @@ class KeyMapControllerTest { listOf(KeyMap(0, trigger = trigger, actionList = listOf(TEST_ACTION))) // when - trigger.keys.forEach { + for (key in trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_DOWN, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) } @@ -2141,12 +2142,12 @@ class KeyMapControllerTest { var consumedUpCount = 0 - trigger.keys.forEach { + for (key in trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { val consumed = inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_UP, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) if (consumed) { @@ -2366,12 +2367,12 @@ class KeyMapControllerTest { // WHEN var consumedCount = 0 - keyMap.trigger.keys.forEach { + for (key in keyMap.trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { val consumed = inputKeyEvent( 999, KeyEvent.ACTION_DOWN, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) if (consumed) { @@ -2393,12 +2394,12 @@ class KeyMapControllerTest { var consumedCount = 0 - keyMap.trigger.keys.forEach { + for (key in keyMap.trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { val consumed = inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_DOWN, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) if (consumed) { @@ -2418,12 +2419,12 @@ class KeyMapControllerTest { var consumedCount = 0 - keyMap.trigger.keys.forEach { + for (key in keyMap.trigger.keys.mapNotNull { it as? KeyCodeTriggerKey }) { val consumed = inputKeyEvent( - it.keyCode, + key.keyCode, KeyEvent.ACTION_DOWN, - triggerKeyDeviceToInputDevice(it.device), + triggerKeyDeviceToInputDevice(key.device), ) if (consumed) { @@ -3212,7 +3213,11 @@ class KeyMapControllerTest { verify(performActionsUseCase, times(1)).perform(TEST_ACTION.data) } - private suspend fun mockTriggerKeyInput(key: KeyCodeTriggerKey, delay: Long? = null) { + private suspend fun mockTriggerKeyInput(key: TriggerKey, delay: Long? = null) { + if (key !is KeyCodeTriggerKey) { + return + } + val deviceDescriptor = triggerKeyDeviceToInputDevice(key.device) val pressDuration: Long = delay ?: when (key.clickType) { ClickType.LONG_PRESS -> LONG_PRESS_DELAY + 100L @@ -3263,11 +3268,16 @@ class KeyMapControllerTest { delay: Long? = null, ) { require(trigger.mode is TriggerMode.Parallel) + require(trigger.keys.all { it is KeyCodeTriggerKey }) + + for (key in trigger.keys) { + if (key !is KeyCodeTriggerKey) { + continue + } - trigger.keys.forEach { - val deviceDescriptor = triggerKeyDeviceToInputDevice(it.device) + val deviceDescriptor = triggerKeyDeviceToInputDevice(key.device) - inputKeyEvent(it.keyCode, KeyEvent.ACTION_DOWN, deviceDescriptor) + inputKeyEvent(key.keyCode, KeyEvent.ACTION_DOWN, deviceDescriptor) } if (delay != null) { @@ -3280,10 +3290,14 @@ class KeyMapControllerTest { } } - trigger.keys.forEach { - val deviceDescriptor = triggerKeyDeviceToInputDevice(it.device) + for (key in trigger.keys) { + if (key !is KeyCodeTriggerKey) { + continue + } + + val deviceDescriptor = triggerKeyDeviceToInputDevice(key.device) - inputKeyEvent(it.keyCode, KeyEvent.ACTION_UP, deviceDescriptor) + inputKeyEvent(key.keyCode, KeyEvent.ACTION_UP, deviceDescriptor) } } diff --git a/app/src/test/java/io/github/sds100/keymapper/util/KeyMapUtils.kt b/app/src/test/java/io/github/sds100/keymapper/util/KeyMapUtils.kt index 8fbd2c7a8e..fdfaf78f6e 100644 --- a/app/src/test/java/io/github/sds100/keymapper/util/KeyMapUtils.kt +++ b/app/src/test/java/io/github/sds100/keymapper/util/KeyMapUtils.kt @@ -3,6 +3,7 @@ package io.github.sds100.keymapper.util import io.github.sds100.keymapper.mappings.ClickType import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.Trigger +import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKey import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerKeyDevice import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode @@ -10,17 +11,17 @@ import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerMode * Created by sds100 on 19/04/2021. */ -fun singleKeyTrigger(key: KeyCodeTriggerKey): Trigger = Trigger( +fun singleKeyTrigger(key: TriggerKey): Trigger = Trigger( keys = listOf(key), mode = TriggerMode.Undefined, ) -fun parallelTrigger(vararg keys: KeyCodeTriggerKey): Trigger = Trigger( +fun parallelTrigger(vararg keys: TriggerKey): Trigger = Trigger( keys = keys.toList(), mode = TriggerMode.Parallel(keys[0].clickType), ) -fun sequenceTrigger(vararg keys: KeyCodeTriggerKey): Trigger = Trigger( +fun sequenceTrigger(vararg keys: TriggerKey): Trigger = Trigger( keys = keys.toList(), mode = TriggerMode.Sequence, ) @@ -34,5 +35,5 @@ fun triggerKey( keyCode = keyCode, device = device, clickType = clickType, - consumeKeyEvent = consume, + consumeEvent = consume, )