Skip to content

Commit bad3059

Browse files
committed
refactor: clean up handling of key events
- Remove `count` param of `sendDownUpKeyEvent` in TrimeInputMethodService.kt - Distinguish unhandled virtual and physical key events - Make NumLock state can be recognized - Eliminate hacky processes for unhandled virtual key events
1 parent 40f02fd commit bad3059

File tree

6 files changed

+92
-105
lines changed

6 files changed

+92
-105
lines changed

app/src/main/java/com/osfans/trime/core/KeyModifier.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ value class KeyModifiers(
6363
val ctrl get() = has(KeyModifier.Control)
6464
val shift get() = has(KeyModifier.Shift)
6565
val meta get() = has(KeyModifier.Meta)
66+
val numLock get() = has(KeyModifier.Mod2) // NumLock
6667
val capsLock get() = has(KeyModifier.Lock)
6768

6869
val release get() = has(KeyModifier.Release)
@@ -73,6 +74,7 @@ value class KeyModifiers(
7374
if (ctrl) metaState = metaState or KeyEvent.META_CTRL_ON or KeyEvent.META_CTRL_LEFT_ON
7475
if (shift) metaState = metaState or KeyEvent.META_SHIFT_ON or KeyEvent.META_SHIFT_LEFT_ON
7576
if (meta) metaState = metaState or KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON
77+
if (numLock) metaState = metaState or KeyEvent.META_NUM_LOCK_ON
7678
if (capsLock) metaState = metaState or KeyEvent.META_CAPS_LOCK_ON
7779
return metaState
7880
}
@@ -91,6 +93,7 @@ value class KeyModifiers(
9193
if (isCtrlPressed) states += KeyModifier.Control
9294
if (isShiftPressed) states += KeyModifier.Shift
9395
if (isCapsLockOn) states += KeyModifier.Lock
96+
if (isNumLockOn) states += KeyModifier.Mod2 // NumLock
9497
if (isMetaPressed) states += KeyModifier.Meta
9598
if (action == KeyEvent.ACTION_UP) states += KeyModifier.Release
9699
}
@@ -102,8 +105,9 @@ value class KeyModifiers(
102105
if (metaState.hasFlag(KeyEvent.META_ALT_ON)) states += KeyModifier.Alt
103106
if (metaState.hasFlag(KeyEvent.META_CTRL_ON)) states += KeyModifier.Control
104107
if (metaState.hasFlag(KeyEvent.META_SHIFT_ON)) states += KeyModifier.Shift
108+
if (metaState.hasFlag(KeyEvent.META_NUM_LOCK_ON)) states += KeyModifier.Mod2 // NumLock
105109
if (metaState.hasFlag(KeyEvent.META_CAPS_LOCK_ON)) states += KeyModifier.Lock
106-
if (metaState.hasFlag(KeyEvent.META_META_ON)) states + KeyModifier.Meta
110+
if (metaState.hasFlag(KeyEvent.META_META_ON)) states += KeyModifier.Meta
107111
return KeyModifiers(states)
108112
}
109113

app/src/main/java/com/osfans/trime/core/Rime.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,25 +101,27 @@ class Rime :
101101
override suspend fun processKey(
102102
value: Int,
103103
modifiers: UInt,
104+
isVirtual: Boolean,
104105
): Boolean = withRimeContext {
105106
processRimeKey(value, modifiers.toInt()).also {
106107
if (it) {
107108
emitResponse()
108109
} else {
109-
emitKeyEvent(value, modifiers.toInt())
110+
emitKeyEvent(value, modifiers.toInt(), isVirtual)
110111
}
111112
}
112113
}
113114

114115
override suspend fun processKey(
115116
value: KeyValue,
116117
modifiers: KeyModifiers,
118+
isVirtual: Boolean,
117119
): Boolean = withRimeContext {
118120
processRimeKey(value.value, modifiers.toInt()).also {
119121
if (it) {
120122
emitResponse()
121123
} else {
122-
emitKeyEvent(value.value, modifiers.toInt())
124+
emitKeyEvent(value.value, modifiers.toInt(), isVirtual)
123125
}
124126
}
125127
}
@@ -415,10 +417,11 @@ class Rime :
415417
private fun emitKeyEvent(
416418
value: Int,
417419
modifiers: Int,
420+
isVirtual: Boolean,
418421
) {
419422
handleRimeMessage(
420423
9, // RimeMessage.MessageType.Key,
421-
arrayOf(value, modifiers),
424+
arrayOf(value, modifiers, isVirtual),
422425
)
423426
}
424427

app/src/main/java/com/osfans/trime/core/RimeApi.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ interface RimeApi {
3434
suspend fun processKey(
3535
value: Int,
3636
modifiers: UInt = 0u,
37+
isVirtual: Boolean = true,
3738
): Boolean
3839

3940
suspend fun processKey(
4041
value: KeyValue,
4142
modifiers: KeyModifiers,
43+
isVirtual: Boolean = true,
4244
): Boolean
4345

4446
suspend fun selectCandidate(idx: Int): Boolean

app/src/main/java/com/osfans/trime/core/RimeMessage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ sealed class RimeMessage<T>(
129129
data class Data(
130130
val value: KeyValue,
131131
val modifiers: KeyModifiers,
132+
val isVirtual: Boolean,
132133
)
133134
}
134135

@@ -189,6 +190,7 @@ sealed class RimeMessage<T>(
189190
KeyMessage.Data(
190191
KeyValue(params[0] as Int),
191192
KeyModifiers.of(params[1] as Int),
193+
params[2] as Boolean,
192194
),
193195
)
194196
else -> UnknownMessage(params)

app/src/main/java/com/osfans/trime/ime/core/TrimeInputMethodService.kt

Lines changed: 70 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -212,42 +212,55 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
212212
KeyboardSwitcher.currentKeyboardView?.invalidateAllKeys()
213213
}
214214
is RimeMessage.KeyMessage ->
215-
it.data.let event@{
216-
val keyCode = it.value.keyCode
217-
if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
218-
when {
219-
!it.modifiers.release && it.value.value > 0 -> {
220-
runCatching {
221-
commitText("${Char(it.value.value)}")
215+
it.data.let msg@{
216+
if (it.isVirtual) {
217+
when (it.value.value) {
218+
RimeKeyMapping.RimeKey_Return -> handleReturnKey()
219+
else -> {
220+
val keyCode = it.value.keyCode
221+
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
222+
// recognized keyCode
223+
sendDownUpKeyEvent(
224+
keyCode,
225+
it.modifiers.metaState or meta(
226+
alt = it.modifiers.alt,
227+
shift = it.modifiers.shift,
228+
ctrl = it.modifiers.ctrl,
229+
meta = it.modifiers.meta,
230+
),
231+
)
232+
if (it.modifiers.ctrl && keyCode == KeyEvent.KEYCODE_C) clearTextSelection()
233+
} else {
234+
if (it.value.value > 0) {
235+
runCatching {
236+
commitText(Character.toString(it.value.value))
237+
}.getOrElse { t -> Timber.w(t, "Unhandled Virtual KeyEvent: $it") }
238+
} else {
239+
Timber.w("Unhandled Virtual KeyEvent: $it")
240+
}
222241
}
223242
}
224-
else -> Timber.w("Unhandled Rime KeyEvent: $it")
225243
}
226-
return
227-
}
228-
229-
val eventTime = SystemClock.uptimeMillis()
230-
if (it.modifiers.release) {
231-
sendUpKeyEvent(eventTime, keyCode, it.modifiers.metaState)
232-
return
233-
}
234-
235-
// TODO: look for better workaround for this
236-
if (keyCode == KeyEvent.KEYCODE_ENTER) {
237-
handleReturnKey()
238-
return
239-
}
240-
241-
if (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_EQUALS) {
242-
// ignore KP_X keys, which is handled in `CommonKeyboardActionListener`.
243-
// Requires this empty body becoz Kotlin request it
244-
return
244+
} else {
245+
val keyCode = it.value.keyCode
246+
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
247+
// recognized keyCode
248+
val eventTime = SystemClock.uptimeMillis()
249+
if (it.modifiers.release) {
250+
sendUpKeyEvent(eventTime, keyCode, it.modifiers.metaState)
251+
} else {
252+
sendDownKeyEvent(eventTime, keyCode, it.modifiers.metaState)
253+
}
254+
} else {
255+
if (!it.modifiers.release && it.value.value > 0) {
256+
runCatching {
257+
commitText(Character.toString(it.value.value))
258+
}.getOrElse { t -> Timber.w(t, "Unhandled Rime KeyEvent: $it") }
259+
} else {
260+
Timber.w("Unhandled Rime KeyEvent: $it")
261+
}
262+
}
245263
}
246-
247-
if (it.modifiers.shift) sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
248-
sendDownKeyEvent(eventTime, keyCode, it.modifiers.metaState)
249-
if (it.modifiers.shift) sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
250-
if (it.modifiers.ctrl && keyCode == KeyEvent.KEYCODE_C) clearTextSelection()
251264
}
252265
else -> {}
253266
}
@@ -635,29 +648,18 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
635648
* @return An integer containing all meta flags passed and formatted for use in a [KeyEvent].
636649
*/
637650
fun meta(
638-
ctrl: Boolean = false,
639651
alt: Boolean = false,
652+
ctrl: Boolean = false,
640653
shift: Boolean = false,
641654
meta: Boolean = false,
642655
sym: Boolean = false,
643656
): Int {
644657
var metaState = 0
645-
if (ctrl) {
646-
metaState = metaState or KeyEvent.META_CTRL_ON or KeyEvent.META_CTRL_LEFT_ON
647-
}
648-
if (alt) {
649-
metaState = metaState or KeyEvent.META_ALT_ON or KeyEvent.META_ALT_LEFT_ON
650-
}
651-
if (shift) {
652-
metaState = metaState or KeyEvent.META_SHIFT_ON or KeyEvent.META_SHIFT_LEFT_ON
653-
}
654-
if (meta) {
655-
metaState = metaState or KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON
656-
}
657-
if (sym) {
658-
metaState = metaState or KeyEvent.META_SYM_ON
659-
}
660-
658+
if (alt) metaState = KeyEvent.META_ALT_ON or KeyEvent.META_ALT_LEFT_ON
659+
if (ctrl) metaState = metaState or KeyEvent.META_CTRL_ON or KeyEvent.META_CTRL_LEFT_ON
660+
if (shift) metaState = metaState or KeyEvent.META_SHIFT_ON or KeyEvent.META_SHIFT_LEFT_ON
661+
if (meta) metaState = metaState or KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON
662+
if (sym) metaState = metaState or KeyEvent.META_SYM_ON
661663
return metaState
662664
}
663665

@@ -710,84 +712,66 @@ open class TrimeInputMethodService : LifecycleInputMethodService() {
710712
*
711713
* @param keyEventCode The key code to send, use a key code defined in Android's [KeyEvent].
712714
* @param metaState Flags indicating which meta keys are currently pressed.
713-
* @param count How often the key is pressed while the meta keys passed are down. Must be greater than or equal to
714-
* `1`, else this method will immediately return false.
715715
*
716716
* @return True on success, false if an error occurred or the input connection is invalid.
717717
*/
718718
fun sendDownUpKeyEvent(
719719
keyEventCode: Int,
720720
metaState: Int = meta(),
721-
count: Int = 1,
722721
): Boolean {
723-
if (count < 1) return false
724-
val ic = currentInputConnection ?: return false
725-
ic.clearMetaKeyStates(
726-
KeyEvent.META_FUNCTION_ON
727-
or KeyEvent.META_SHIFT_MASK
728-
or KeyEvent.META_ALT_MASK
729-
or KeyEvent.META_CTRL_MASK
730-
or KeyEvent.META_META_MASK
731-
or KeyEvent.META_SYM_ON,
732-
)
733-
ic.beginBatchEdit()
734722
val eventTime = SystemClock.uptimeMillis()
735-
if (metaState and KeyEvent.META_CTRL_ON != 0) {
736-
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_CTRL_LEFT)
737-
}
738723
if (metaState and KeyEvent.META_ALT_ON != 0) {
739724
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_ALT_LEFT)
740725
}
726+
if (metaState and KeyEvent.META_CTRL_ON != 0) {
727+
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_CTRL_LEFT)
728+
}
741729
if (metaState and KeyEvent.META_SHIFT_ON != 0) {
742730
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
743731
}
744732
if (metaState and KeyEvent.META_META_ON != 0) {
745733
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_META_LEFT)
746734
}
747-
748735
if (metaState and KeyEvent.META_SYM_ON != 0) {
749736
sendDownKeyEvent(eventTime, KeyEvent.KEYCODE_SYM)
750737
}
751-
752-
for (n in 0 until count) {
753-
sendDownKeyEvent(eventTime, keyEventCode, metaState)
754-
sendUpKeyEvent(eventTime, keyEventCode, metaState)
738+
sendDownKeyEvent(eventTime, keyEventCode, metaState)
739+
sendUpKeyEvent(eventTime, keyEventCode, metaState)
740+
if (metaState and KeyEvent.META_SYM_ON != 0) {
741+
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SYM)
742+
}
743+
if (metaState and KeyEvent.META_META_ON != 0) {
744+
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_META_LEFT)
755745
}
756746
if (metaState and KeyEvent.META_SHIFT_ON != 0) {
757747
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SHIFT_LEFT)
758748
}
759-
if (metaState and KeyEvent.META_ALT_ON != 0) {
760-
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_ALT_LEFT)
761-
}
762749
if (metaState and KeyEvent.META_CTRL_ON != 0) {
763750
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_CTRL_LEFT)
764751
}
765-
766-
if (metaState and KeyEvent.META_META_ON != 0) {
767-
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_META_LEFT)
768-
}
769-
770-
if (metaState and KeyEvent.META_SYM_ON != 0) {
771-
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_SYM)
752+
if (metaState and KeyEvent.META_ALT_ON != 0) {
753+
sendUpKeyEvent(eventTime, KeyEvent.KEYCODE_ALT_LEFT)
772754
}
773-
774-
ic.endBatchEdit()
775755
return true
776756
}
777757

778758
private fun forwardKeyEvent(event: KeyEvent): Boolean {
779759
val modifiers = KeyModifiers.fromKeyEvent(event)
780760
val charCode = event.unicodeChar
781-
if (charCode > 0 && charCode != '\t'.code && charCode != '\n'.code) {
761+
if (charCode > 0 && charCode != '\t'.code && charCode != '\n'.code && charCode != ' '.code) {
762+
// drop modifier state when using combination keys to input number/symbol on some phones
763+
// because rime doesn't recognize selection key with modifiers (eg. Alt+Q for 1)
764+
// in which case event.getNumber().toInt() == event.getUnicodeChar()
765+
val m = if (event.number.code == charCode) KeyModifiers.Empty else modifiers
782766
postRimeJob {
783-
processKey(charCode, modifiers.modifiers)
767+
processKey(charCode, m.modifiers, isVirtual = false)
784768
}
785769
return true
786770
}
787771
val keyVal = KeyValue.fromKeyEvent(event)
788772
if (keyVal.value != RimeKeyMapping.RimeKey_VoidSymbol) {
789773
postRimeJob {
790-
processKey(keyVal, modifiers)
774+
processKey(keyVal, modifiers, isVirtual = false)
791775
}
792776
return true
793777
}

app/src/main/java/com/osfans/trime/ime/keyboard/CommonKeyboardActionListener.kt

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,14 @@ class CommonKeyboardActionListener(
288288
.keyCodeToVal(keyEventCode)
289289
.takeIf { it != RimeKeyMapping.RimeKey_VoidSymbol }
290290
?: RimeKeyEvent.getKeycodeByName(Keycode.keyNameOf(keyEventCode))
291-
val modifiers = KeyModifiers.fromMetaState(metaState).modifiers
291+
val m = if (keyEventCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_EQUALS) {
292+
metaState or KeyEvent.META_NUM_LOCK_ON
293+
} else {
294+
metaState
295+
}
296+
val modifiers = KeyModifiers.fromMetaState(m).modifiers
292297
service.postRimeJob {
293-
if (service.hookKeyboard(keyEventCode, metaState)) {
298+
if (service.hookKeyboard(keyEventCode, m)) {
294299
Timber.d("handleKey: hook")
295300
return@postRimeJob
296301
}
@@ -304,19 +309,6 @@ class CommonKeyboardActionListener(
304309
return@postRimeJob
305310
}
306311
shouldReleaseKey = false
307-
308-
when (keyEventCode) {
309-
KeyEvent.KEYCODE_BACK -> service.requestHideSelf(0)
310-
else -> {
311-
// 小键盘自动增加锁定
312-
if (keyEventCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_EQUALS) {
313-
service.sendDownUpKeyEvent(
314-
keyEventCode,
315-
metaState or KeyEvent.META_NUM_LOCK_ON,
316-
)
317-
}
318-
}
319-
}
320312
}
321313
}
322314

0 commit comments

Comments
 (0)