MIUI 13 如何关闭系统的 compose key

5 天前
 bczhc

在我的小米平板 5 ( MIUI 13.0.9 )上,当外接键盘时,Alt 键会被系统作为 compose key ,如按下“alt+s”时会输出“ß”,按下“alt+u u”时会上屏“ü”。使用 Gboard 和“CodeBoard”测试过了,都是如此,可以判断是系统行为,不是输入法的。

感觉小米总喜欢瞎搞些这种东西。手头四五个安卓设备里就它有问题,不过手机 HyperOS 也是正常的。我并不需要这个功能,设置里也没找到哪个能关。这直接导致了开发 IME 时无法处理任何 Alt 组合键( onKeyDown 里完全接收不到按下 Alt 时的字母事件)。

765 次点击
所在节点    Android
3 条回复
kuanat
4 天前
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 来处理。
bczhc
3 天前
@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 看不到一点。
kuanat
3 天前
@bczhc #2

看你这个回复基本上就是系统的 bug 了。小米的软件 bug 多到离谱,而且大多数时候管杀不管埋……

关键是从这个表现来看,在进入到 InputMethodService 之前就被拦截了,连拯救一下的机会都没有。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://ex.noerr.eu.org/t/1170484

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX