在我的小米平板 5 ( MIUI 13.0.9 )上,当外接键盘时,Alt 键会被系统作为 compose key ,如按下“alt+s”时会输出“ß”,按下“alt+u u”时会上屏“ü”。使用 Gboard 和“CodeBoard”测试过了,都是如此,可以判断是系统行为,不是输入法的。
感觉小米总喜欢瞎搞些这种东西。手头四五个安卓设备里就它有问题,不过手机 HyperOS 也是正常的。我并不需要这个功能,设置里也没找到哪个能关。这直接导致了开发 IME 时无法处理任何 Alt 组合键( onKeyDown 里完全接收不到按下 Alt 时的字母事件)。
1
kuanat 3 天前
Android 系统在语言和输入法相关设置里有个物理键盘的设定,可以点进去看看是否有切换键盘布局的选项,如果有的话切换到不使用 AltGr/Compose 的布局。印象 aosp 中有过,但我不是很确定。
这个问题说起来比较复杂。Android 系统的输入栈在内核部分和 Linux 是没有区别的,但之后就完全不一样了。因为是针对移动平台设计的,关于键盘布局的设定是和输入法、语言强绑定的。从底层修改这个按键和功能的映射是可行的,可以参考一下 https://github.com/keymapperorg/KeyMapper 这个应用。 简单说 Android 输入栈有两层,最底层和 Linux 处理输入设备一样,在内核态完成 scan code 到名义按键的映射,比如 scan code 1 代表 esc 按键。上面一层是按键和具体功能的映射,比如 A 按键的效果是 a 字符,有 shift 修饰的时候产生 A 字符。 如果你的系统可以获得 root 的话,可以看一下 /system/usr/keylayout/ 和 /system/usr/keychars/ 两个路径的文件。前者包含不同设备的 .kl 定义,代表 scan code 到名义按键的映射,后者包含 .kcm 定义,即名义按键到实际功能的映射,也就是一般所说的布局。可以检查一下是否正常。 如果你可以用 onKeyDown 获得 COMPOSE 事件的话,可以在编写的代码里强行当作 alt 来处理。 |
2
bczhc OP @kuanat 感谢回复。又测试了手上的 MIUI 13 和 HyperOS ,发现两者对此有不同行为。我做了一些测试。
当按下 Alt 时 onKeyDown 中可以接收到 Alt 事件(如果长按了还会有一连串),但对于 HyperOS ,当按下后续字母时,会有那个字母按键的事件,但对于 MIUI 13 ,则是表现为那串 Alt 事件戛然而止,无后续的字母按键。 另外,才发现 HyperOS 其实同样是处理 compose key 的,以 Alt+S 为例,当系统接收到 Alt+S 时就会上屏`ß`,但尽管如此,不影响 IME 中获取到 Alt 后续的 S 事件,且只有在 IME 不拦截( onKeyDown 返回`false`)时才会上屏`ß`。反之,HyperOS 中无论 IME 是否拦截,则都会上屏`ß`。拦截无效,显然可以合理怀疑这是 MIUI 13 的 bug 。 在 MIUI 13 中是能找到“实体键盘布局”一选项,但当我选到了其他的布局时,compose key 倒没了(比如按 Alt+S 不会上屏`ß`了),但 IME 中仍然接收不到 Alt 修饰的按键。 那两个文件不需要 root 也可以由 adb 拉取,我看了下内容,左 ALT 的处理正常,如下: ```console ~/keyboard/miui13/keylayout ❯ rg -i 'KEY 56' 17:55:17 qwerty.kl 97:key 56 ALT_LEFT Vendor_046d_Product_c532.kl 81:key 56 ALT_RIGHT Vendor_22b8_Product_093d.kl 73:key 56 ALT_LEFT Vendor_05ac_Product_0239.kl 78:key 56 ALT_LEFT Vendor_18d1_Product_5018.kl 78:key 56 ALT_LEFT Generic.kl 78:key 56 ALT_LEFT ``` 对于“S”键的处理则都有在被 Alt 修饰时上屏`ß`(`\u00df`): ```console ~/keyboard/miui13/keychars ❯ rg -i 'KEY S ' --after-context=5 17:57:07 qwerty2.kcm 183:key S { 184- label: 'S' 185- number: '7' 186- base: 's' 187- shift, capslock: 'S' 188- alt: '\u00df' qwerty.kcm 186:key S { 187- label: 'S' 188- number: '7' 189- base: 's' 190- shift, capslock: 'S' 191- alt: '4' Generic.kcm 140:key S { 141- label: 'S' 142- base: 's' 143- shift, capslock: 'S' 144- alt: '\u00df' 145-} Vendor_18d1_Product_5018.kcm 140:key S { 141- label: 'S' 142- base: 's' 143- shift, capslock: 'S' 144- alt: '\u00df' 145-} Virtual.kcm 137:key S { 138- label: 'S' 139- base: 's' 140- shift, capslock: 'S' 141- alt: '\u00df' 142-} ``` MIUI 13 和 HyperOS 对于这些定义大差不差。没看出有什么大的不妥。顺便说下,MIUI 13 对于 Ctrl 在 IME 中也是获取不到后续按键的。似乎是 MIUI 13 直接一整个把至少这俩修饰键的处理全放在系统中拦截了(哪怕 Alt+某个 key 是完全没有 compose 行为的),就导致了 IME 看不到一点。 |