Skip to content

Commit a18161c

Browse files
authored
Merge pull request #1564 from kamilkrzyskow/fix/scancode-fallback
#1276 refactor: fallback to scanCode when keyCode unknown
2 parents 639f29b + bd85815 commit a18161c

File tree

12 files changed

+88
-15
lines changed

12 files changed

+88
-15
lines changed

.github/workflows/crowdin-actions.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ jobs:
2020

2121
- name: crowdin action
2222
uses: crowdin/github-action@v2
23+
if: github.event.repository.fork == false
2324
with:
2425
upload_sources: true
2526
upload_translations: false

.github/workflows/testing.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ jobs:
9696
ruby-version: '3.3'
9797

9898
- name: Create debug keystore
99+
if: github.event.repository.fork == false
99100
env:
100101
CI_KEYSTORE: ${{ secrets.CI_KEYSTORE }}
101102
run: |
@@ -123,14 +124,15 @@ jobs:
123124

124125
- name: Upload to Discord
125126
uses: sinshutu/[email protected]
127+
if: github.event.repository.fork == false
126128
env:
127129
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
128130
with:
129131
args: app/build/outputs/apk/free/ci/${{ env.APK_NAME }}.apk
130132

131133
- name: Report build status to Discord
132134
uses: sarisia/actions-status-discord@v1
133-
if: failure()
135+
if: github.event.repository.fork == false && failure()
134136
with:
135137
title: "Build apk"
136138
webhook: ${{ secrets.DISCORD_BUILD_STATUS_WEBHOOK }}

app/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,14 @@ android {
9898
dimension "pro"
9999

100100
File file = rootProject.file("local.properties")
101+
String keyName = "REVENUECAT_API_KEY"
101102

102103
if (file.exists()) {
103104
def localProperties = new Properties()
104105
localProperties.load(new FileInputStream(file))
105-
buildConfigField("String", "REVENUECAT_API_KEY", localProperties["REVENUECAT_API_KEY"])
106+
if (localProperties.hasProperty(keyName)) {
107+
buildConfigField("String", keyName, localProperties[keyName])
108+
}
106109
}
107110
}
108111
}

app/src/main/java/io/github/sds100/keymapper/data/Keys.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ object Keys {
5252
booleanPreferencesKey("key_shown_parallel_trigger_order_warning")
5353
val shownSequenceTriggerExplanation =
5454
booleanPreferencesKey("key_shown_sequence_trigger_explanation_dialog")
55+
val shownKeyCodeToScanCodeTriggerExplanation =
56+
booleanPreferencesKey("key_shown_keycode_to_scancode_trigger_explanation_dialog")
5557
val lastInstalledVersionCodeHomeScreen =
5658
intPreferencesKey("last_installed_version_home_screen")
5759
val lastInstalledVersionCodeBackground =

app/src/main/java/io/github/sds100/keymapper/mappings/keymaps/trigger/BaseConfigTriggerViewModel.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,24 @@ abstract class BaseConfigTriggerViewModel(
456456
// need to be dismissed before it is added.
457457
config.addKeyCodeTriggerKey(key.keyCode, key.device, key.detectionSource)
458458

459+
if (key.keyCode >= InputEventUtils.KEYCODE_TO_SCANCODE_OFFSET || key.keyCode < 0) {
460+
if (onboarding.shownKeyCodeToScanCodeTriggerExplanation) {
461+
return
462+
}
463+
464+
val dialog = PopupUi.Dialog(
465+
title = getString(R.string.dialog_title_keycode_to_scancode_trigger_explanation),
466+
message = getString(R.string.dialog_message_keycode_to_scancode_trigger_explanation),
467+
positiveButtonText = getString(R.string.pos_understood),
468+
)
469+
470+
val response = showPopup("keycode_to_scancode_message", dialog)
471+
472+
if (response == DialogResponse.POSITIVE) {
473+
onboarding.shownKeyCodeToScanCodeTriggerExplanation = true
474+
}
475+
}
476+
459477
if (key.keyCode == KeyEvent.KEYCODE_CAPS_LOCK) {
460478
val dialog = PopupUi.Ok(
461479
message = getString(R.string.dialog_message_enable_physical_keyboard_caps_lock_a_keyboard_layout),

app/src/main/java/io/github/sds100/keymapper/onboarding/OnboardingUseCase.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class OnboardingUseCaseImpl(
6565
Keys.shownSequenceTriggerExplanation,
6666
false,
6767
)
68+
override var shownKeyCodeToScanCodeTriggerExplanation by PrefDelegate(
69+
Keys.shownKeyCodeToScanCodeTriggerExplanation,
70+
false,
71+
)
6872

6973
override val showWhatsNew = get(Keys.lastInstalledVersionCodeHomeScreen)
7074
.map { (it ?: -1) < Constants.VERSION_CODE }
@@ -167,6 +171,7 @@ interface OnboardingUseCase {
167171

168172
var shownParallelTriggerOrderExplanation: Boolean
169173
var shownSequenceTriggerExplanation: Boolean
174+
var shownKeyCodeToScanCodeTriggerExplanation: Boolean
170175

171176
val showFloatingButtonFeatureNotification: Flow<Boolean>
172177
fun showedFloatingButtonFeatureNotification()

app/src/main/java/io/github/sds100/keymapper/system/accessibility/BaseAccessibilityServiceController.kt

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyEventDetectionSour
2424
import io.github.sds100.keymapper.reroutekeyevents.RerouteKeyEventsController
2525
import io.github.sds100.keymapper.reroutekeyevents.RerouteKeyEventsUseCase
2626
import io.github.sds100.keymapper.system.devices.DevicesAdapter
27+
import io.github.sds100.keymapper.system.inputevents.InputEventUtils
2728
import io.github.sds100.keymapper.system.inputevents.MyKeyEvent
2829
import io.github.sds100.keymapper.system.inputevents.MyMotionEvent
2930
import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter
@@ -296,6 +297,29 @@ abstract class BaseAccessibilityServiceController(
296297
open fun onConfigurationChanged(newConfig: Configuration) {
297298
}
298299

300+
/**
301+
* Returns an MyKeyEvent which is either the same or more unique
302+
*/
303+
private fun getUniqueEvent(event: MyKeyEvent): MyKeyEvent {
304+
// Guard to ignore processing when not applicable
305+
if (event.keyCode != KeyEvent.KEYCODE_UNKNOWN) return event
306+
307+
// Don't offset negative values
308+
val scanCodeOffset: Int = if (event.scanCode >= 0) {
309+
InputEventUtils.KEYCODE_TO_SCANCODE_OFFSET
310+
} else {
311+
0
312+
}
313+
314+
val eventProxy = event.copy(
315+
// Fallback to scanCode when keyCode is unknown as it's typically more unique
316+
// Add offset to go past possible keyCode values
317+
keyCode = event.scanCode + scanCodeOffset,
318+
)
319+
320+
return eventProxy
321+
}
322+
299323
fun onKeyEvent(
300324
event: MyKeyEvent,
301325
detectionSource: KeyEventDetectionSource = KeyEventDetectionSource.ACCESSIBILITY_SERVICE,
@@ -305,11 +329,14 @@ abstract class BaseAccessibilityServiceController(
305329
if (recordingTrigger) {
306330
if (event.action == KeyEvent.ACTION_DOWN) {
307331
Timber.d("Recorded key ${KeyEvent.keyCodeToString(event.keyCode)}, $detailedLogInfo")
332+
333+
val uniqueEvent: MyKeyEvent = getUniqueEvent(event)
334+
308335
coroutineScope.launch {
309336
outputEvents.emit(
310337
ServiceEvent.RecordedTriggerKey(
311-
event.keyCode,
312-
event.device,
338+
uniqueEvent.keyCode,
339+
uniqueEvent.device,
313340
detectionSource,
314341
),
315342
)
@@ -327,16 +354,17 @@ abstract class BaseAccessibilityServiceController(
327354
} else {
328355
try {
329356
var consume: Boolean
357+
val uniqueEvent: MyKeyEvent = getUniqueEvent(event)
330358

331-
consume = keyMapController.onKeyEvent(event)
359+
consume = keyMapController.onKeyEvent(uniqueEvent)
332360

333361
if (!consume) {
334-
consume = rerouteKeyEventsController.onKeyEvent(event)
362+
consume = rerouteKeyEventsController.onKeyEvent(uniqueEvent)
335363
}
336364

337-
when (event.action) {
338-
KeyEvent.ACTION_DOWN -> Timber.d("Down ${KeyEvent.keyCodeToString(event.keyCode)} - consumed: $consume, $detailedLogInfo")
339-
KeyEvent.ACTION_UP -> Timber.d("Up ${KeyEvent.keyCodeToString(event.keyCode)} - consumed: $consume, $detailedLogInfo")
365+
when (uniqueEvent.action) {
366+
KeyEvent.ACTION_DOWN -> Timber.d("Down ${KeyEvent.keyCodeToString(uniqueEvent.keyCode)} - consumed: $consume, $detailedLogInfo")
367+
KeyEvent.ACTION_UP -> Timber.d("Up ${KeyEvent.keyCodeToString(uniqueEvent.keyCode)} - consumed: $consume, $detailedLogInfo")
340368
}
341369

342370
return consume

app/src/main/java/io/github/sds100/keymapper/system/inputevents/InputEventUtils.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,12 +686,22 @@ object InputEventUtils {
686686
KeyEvent.KEYCODE_FUNCTION,
687687
)
688688

689+
/**
690+
* Used for keyCode to scanCode fallback to go past possible keyCode values
691+
*/
692+
val KEYCODE_TO_SCANCODE_OFFSET: Int
693+
get() = KeyEvent.getMaxKeyCode() + 1
694+
689695
/**
690696
* Create a text representation of a key event. E.g if the control key was pressed,
691697
* "Ctrl" will be returned
692698
*/
693699
fun keyCodeToString(keyCode: Int): String = NON_CHARACTER_KEY_LABELS[keyCode].let {
694-
it ?: "unknown keycode $keyCode"
700+
if (keyCode >= KEYCODE_TO_SCANCODE_OFFSET || keyCode < 0) {
701+
"scancode $keyCode"
702+
} else {
703+
it ?: "unknown keycode $keyCode"
704+
}
695705
}
696706

697707
fun isModifierKey(keyCode: Int): Boolean = keyCode in MODIFIER_KEYCODES

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,9 @@
492492
<string name="drag_handle_for">Drag handle for %1$s</string>
493493
<string name="show_example">Show example</string>
494494

495+
<string name="dialog_title_keycode_to_scancode_trigger_explanation">Unrecognized key code</string>
496+
<string name="dialog_message_keycode_to_scancode_trigger_explanation">The pressed button was not recognized by the input system. In the past Key Mapper detected such buttons as one and the same. Currently the app tries to distinguish the button based on the scan code, which should be more unique. However, this is a makeshift incomplete solution, which doesn\'t guarantee uniqueness.</string>
497+
495498
<string name="pos_done">Done</string>
496499
<string name="pos_grant_write_secure_settings_guide">Guide</string>
497500
<string name="pos_start_service_with_adb_guide">Guide</string>
@@ -503,6 +506,7 @@
503506
<string name="pos_apply">Apply</string>
504507
<string name="pos_discard_changes">Discard changes</string>
505508
<string name="pos_save">Save</string>
509+
<string name="pos_understood">Understood</string>
506510

507511
<string name="neg_turn_off">Turn off</string>
508512
<string name="neg_cancel">Cancel</string>

docs/includes/action-type-list.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Tab | Description |
66
| [System](../user-guide/actions#system) | Choose a system operation (such as toggling Bluetooth, opening the home menu, toggling flashlight) |
77
| [Key](../user-guide/actions#key) | An alternative way to choose a key press action, by pressing the key that you want to map to. |
88
| [Tap screen (2.1.0+)](../user-guide/actions#tap-screen-210) | Emulate a screen tap at a specific location on your screen. |
9-
| [Key event (2.1.0+)](../user-guide/actions#key-event-210) | Emulate a key press from a specifc connected device. |
9+
| [Key event (2.1.0+)](../user-guide/actions#key-event-210) | Emulate a key press from a specific connected device. |
1010
| [Text](../user-guide/actions#text) | Emulate typing a string. |
1111
| [Intent (2.3.0+)](../user-guide/actions#intent-230) | See [this page.](../user-guide/actions/#intent-230) |
1212
| [Phone call (2.3.0+)](../user-guide/actions#phone-call-230) | Call a telephone number. Network and carrier rates will apply. |

0 commit comments

Comments
 (0)