openKylin论坛

 找回密码

开源聚力,共创未来——麒麟虚拟键盘开发记 [复制链接]

本帖最后由 幽燕落雨 于 2022-12-27 11:19 编辑

1. 前言

    由于历史原因,Linux上面一直都没有好用易用的虚拟键盘输入法。在桌面环境中,有物理键盘输入法确实就够用了。但是,随着Linux在平板设备的应用,没有好用易用的虚拟键盘输入法的矛盾就显得越来越突出。因此,开发一款好用易用的虚拟键盘输入法就显得势在必行。

    在中文Linux系统中,最新常用的输入法框架是fcitx5。虽然还没有对虚拟键盘提供支持,但是它对物理键盘输入法提供了良好支持。因此,如果能够在这个基础上对fcitx5进行扩展使其支持虚拟键盘输入法,那么,不但可以降低虚拟键盘输入法的开发难度和工作量还能利用fcitx5对应用程序的良好兼容性。

    就这样,基于fcitx5开发麒麟虚拟键盘输入法的思路就确定了。

2. 虚拟键盘输入法的特殊性

    对待开源项目应该抱着取之于开源回馈于开源的观点并且应该尽量减少不必要的重复工作。为此,在启动麒麟虚拟键盘输入法开发之前,输入法SIG组先跟fcitx5作者取得了联系,分析讨论了fcitx5当前对于虚拟键盘的支持情况。得到的答案是,fcitx5确实没有对虚拟键盘提供任何基本的支持。为了避免重复工作,双方讨论决定由输入法SIG组开发相关功能并回馈于社区。

    说干就干。

    很快,输入法SIG组启动了fcitx5输入法框架提供虚拟键盘支持机制的工作。不过,在fcitx5提供虚拟键盘支持机制还是存在一些困难的。困难主要在于以下几点:一是虚拟键盘的按键事件与物理键盘的按键事件存在的本质区别;二是fcitx5既要允许虚拟键盘使用已有的物理键盘输入法引擎也要允许虚拟键盘使用未来专门的虚拟键盘输入法引擎;三是fcitx5输入法框架不能引入QtGtk这种重量级UI框架;四是虚拟键盘需要考虑多语言输入法;五是虚拟键盘存在多种按键:字母键、数字键、开关键、控制键、功能键等。

3. fcitx社区的分析讨论

    经过与fcitx社区反复的分析和讨论,为了解决上面存在的几个困难,输入法SIG组决定采用分阶段各个击破的方式。

    一是分两个阶段实现虚拟键盘和fcitx5输入法框架对虚拟键盘的支持。在第一期中虚拟键盘先实现跟物理键盘布局等价的UIfcitx5输入法框架则增加相应的虚拟键盘UI代理模块用来跟虚拟键盘UI进行通信。在第二期中虚拟键盘UI服务实现根据输入法引擎的请求显示输入法引擎自定义虚拟键盘UIfcitx5输入法则增加相应的虚拟键盘UI自定义模块来允许输入法引擎请求自定义的虚拟键盘UI

    二是虚拟键盘UI的事件不需要走传统的fcitx5 frontend进行通信,而是跟fcitx5中专门的虚拟键盘UI代理模块进行通信。该虚拟键盘UI代码模块的功能类似于fcitx5中已有的kimpanel模块。

    三是在fcitx5输入法框架中增加新的虚拟键盘输入法引擎接口类以及虚拟键盘按键事件处理函数。在该接口中,通过动态检测当前的输入法引擎是虚拟键盘输入法引擎还是物理键盘输入法引擎来决定将虚拟键盘的按键事件发给送哪个按键事件处理函数。

    四是虚拟键盘UI作为一个单独的服务存在,专门用于跟fcitx5输入法框架中的虚拟键盘UI代理模块进行IPC通信。

    后续的实际开发工作证明这么划分是明智的,因为后面还有更大的坑在等着我们去填。

4. fcitx5支持虚拟键盘

    在确定好总体思路之后,剩下的就是细化需求、书写开发方案并进行实际开发了。在整个开发过程中,最耗费时间的阶段是细化需求和书写开发技术方案。真正写代码的时间也就短短几天。在88号,我们向fcitx5仓库提交了第一个PR,由此开启了fcitx5开始提供虚拟键盘支持机制的新阶段。经过我们和fcitx5作者的反复沟通,以及fcitx5作者自己对提交的代码的修改和优化,在810号的时候,我们提交的PR终于合并到了dev分支。PR截图如下所示:

    这次提交的代码主要是在fcitx5中实现了虚拟键盘UI代理模块以及打通了从dbus frontend和虚拟键盘UI代理模块之间的联系。主要实现了如下的功能:一是应用程序可以通过dbus frontend提供的接口控制虚拟键盘的显示和隐藏;二是fcitx5在收到focus in消息后自动显示虚拟键盘以及focus out消息后自动隐藏虚拟键盘;三是虚拟键盘UI代理模块可以将虚拟键盘按键事件发送给物理键盘输入法引擎以及发送模拟按键。

    不过,这次提交还缺少一个重要的功能没有实现,就是让虚拟键盘的按键事件能够跟物理键盘按键事件区分出来并且能够让虚拟键盘不仅仅使用已有的物理键盘输入法引擎,还可以使用新的专用的虚拟键盘输入法引擎。在812日,我们向fcitx5仓库提交了另一个PR。在这次提交之后,fcitx5输入法框架实现了基本的虚拟键盘支持机制。PR截图如下所示:


5. 开发麒麟虚拟键盘

    在fcitx5支持虚拟键盘机制的基础之上,输入法SIG组采用QMLC++混合编程的方式实现了虚拟键盘UI服务。其中,C++负责提供DBus服务并实现了fcitx5中的虚拟键盘代理模块进行双向通信的接口;QML负责虚拟键盘UI服务的界面。下面来亲眼目睹一下麒麟虚拟键盘的模样。

    5.1 弹出输入法列表菜单
    5.2 拼音输入
    5.3 五笔输入
    5.4 英文小写键盘
    5.5 英文大写键盘
    5.6 启用功能键
6. 攻坚克难

    兼容性问题是输入法开发中最大的问题。兼容性问题处理的不好,那么,输入法可能就不好用。

    这次开发麒麟虚拟键盘的过程也充分印证了这个观点。麒麟虚拟键盘在第一版出来之后,主要有以下几个让人感到疑惑的问题:一是虚拟键盘乱弹,总是在用户不希望它出来的时候弹出来;二是在Qt程序中用户使用虚拟键盘输入法输入文字后,如果文本编辑框下面弹出了一个列表窗口,那么,虚拟键盘会自动被隐藏;三是在奇安信浏览器和Chrome浏览器中,虚拟键盘在第一次显示后,无法使用虚拟键盘输入英文字母。四是输入法禁用后无法使用虚拟键盘进行输入的问题。

    针对第一个问题,经过分析发现是因为fcitx5输入法框架中最开始的设计就定义了获得焦点显示虚拟键盘丢失焦点隐藏虚拟键盘的行为。之所以这样定义,是因为GTK框架没有提供对控制虚拟键盘可见性的原生支持而Qt则提供了相应的支持。为了保证Qt程序和GTK程序在处理虚拟键盘可见性时具有一致的行为,最开始的设计采用了比较简单直接的做法。其结果就是用户体验不好。为了解决这个问题,在fcitx5输入法框架中增加了一个标志位,可以由IM module设置这个标志位来告诉fcitx5输入法框架是否使用默认的虚拟键盘可见性控制逻辑。这样做之后,Qt程序可以符合预期的显示虚拟键盘,却不能符合预期的隐藏虚拟键盘!又踩到了一个大坑!其结果是,fcitx5输入法框架中为了控制虚拟键盘的可见性,提供了两个标志位:一个用来告诉fcitx5输入法框架是否使用默认的虚拟键盘显示行为;另一个是用来告诉fcitx5输入法框架是否使用默认的虚拟键盘隐藏行为。Qt5IM module会告诉fcitx5输入法框架禁用默认的虚拟键盘显示行为,它自己会处理好虚拟键盘的显示行为;还会告诉fcitx5输入法框架启用默认的虚拟键盘隐藏行为,它自己无法做到丢失焦点隐藏虚拟键盘。最终,Qt应用程序取得了较好的符合用户预期的虚拟键盘可见性的行为。

    Gtk框架由于自身没有提供对虚拟键盘的支持,因此,只能使用fcitx5输入法框架提供的默认的虚拟键盘可见性的行为。后续,需要通过向GTK框架提交相关代码来提供对虚拟键盘的原生支持。

    针对第二个问题,经过跟fcitx社区的反复沟通、讨论和测试,可以确认这是Qt5/Qt6QCompleter中长期存在的一个bug,并且已经向Qt社区提交了bug报告。这个bug会导致虚拟键盘在文本编辑框输入了某些文字然后弹出了匹配列表之后,虚拟键盘会被隐藏。这也是不符合用户预期的。为了给用户提供良好的体验,fcitx5作者在Qt IM module中提供了规避代码并且已经合并到了主线。

    针对第三个问题,经过分析发现是奇安信浏览器和Chrome浏览器在使用GTK框架的时候的特殊行为造成的。奇安信浏览器和Chrome浏览器只有在收到物理键盘按键之后才会创建GTK IM module需要的GdkWidget对象,而这个对象是GTK IM module用来向GTK窗口发送按键消息必须使用的对象。也就是说,如果没有这个GdkWidget对象,那么,fcitx5输入法框架无法通过GTK IM moduleGTK应用程序发送任何按键消息。最终的结果就是浏览器第一次启动虚拟键盘输入法后无法使用虚拟键盘向浏览器输入英文字母等。为此,针对这种特殊情况,我们在GTK IM module中进行的针对性的处理。也就是在不存在可用的GdkWidget对象的时候,使用XXTestFakeKeyEvent函数发送模拟按键消息;否则,仍然使用GdkWidget对象发送模拟按键消息。

    针对最后一个问题,经过跟fcitx社区的反复讨论和分析,明确了fcitx5输入法框架需要对禁用输入法的情况提供相应的支持并且IM module应该向应用程序查询是否要禁用输入法并将相关结果通知给fcitx5输入法框架。fcitx5输入法框架在输入法被禁用的情况下,会使用默认的键盘布局来响应相关输入。

7. 展望未来

    生态建设,道阻且长。唯有开源聚力,方能行稳致远。当前第一阶段的麒麟虚拟键盘输入法的开发已经完成,我们向fcitx社区的4个项目提交了20多个PR1200行代码。麒麟软件为开源社区的繁荣和发展做出了自己的贡献。

    在接下来的规划中,首先要做的是实现输入法引擎自定义虚拟键盘UI。有这个机制,虚拟键盘就很容易支持多语言输入法了。这样的话,fcitx5输入法框架就提供了比较完整的虚拟键盘支持。

    当然,为了提供一个好用易用的虚拟键盘输入法,还有许多事情要做。包括但不限于KWin窗管、GTK框架、输入法引擎等等。

    总之,前途是光明的,道路是曲折的。我们的目标是提供一个好用易用的多模多形态多语言的麒麟输入法,为麒麟操作系统生态建设添砖加瓦,让麒麟操作系统生态更加繁荣。


PR1.PNG (217.37 KB, 下载次数: 24)

PR1.PNG

启用功能键.png (76.2 KB, 下载次数: 18)

启用功能键.png

英文大写键盘.png (76.68 KB, 下载次数: 20)

英文大写键盘.png

英文小写键盘.png (74.46 KB, 下载次数: 20)

英文小写键盘.png

五笔输入.png (113.75 KB, 下载次数: 21)

五笔输入.png

弹出输入法列表菜单.PNG (71 KB, 下载次数: 22)

弹出输入法列表菜单.PNG

拼音输入.PNG (94.52 KB, 下载次数: 20)

拼音输入.PNG

PR2.PNG (197.47 KB, 下载次数: 22)

PR2.PNG

英文大写键盘.png (76.68 KB, 下载次数: 20)

英文大写键盘.png

启用功能键.png (76.2 KB, 下载次数: 19)

启用功能键.png
楼主
发表于 2022-12-26 11:52:51
回复

使用道具 举报

openKylin

GMT+8, 2024-4-24 11:38 , Processed in 0.084669 second(s), 21 queries , Gzip On.

Copyright ©2022 openKylin. All Rights Reserved .

ICP No. 15002470-12 Tianjin

快速回复 返回顶部 返回列表