1 GTK输入法回顾

在GTK中,每个GtkEntry对象里都有一个指向输入法上下文对象的指针(GtkIMContext *)。在初始化时,这个指针指向一个GtkIMMulticontext对象。

  entry->im_context = gtk_im_multicontext_new ();

在gtk_entry_set_visibility函数中,先解引用当前对象,然后根据visible属性,决定要创建的输入法上下文对象类型:

      if (visible)entry->im_context = gtk_im_multicontext_new ();elseentry->im_context = gtk_im_context_simple_new ();

当visible为真时创建GtkIMMulticontext对象,当visible为假时创建GtkIMContextSimple对象。 GtkIMMulticontext和GtkIMContextSimple都是GtkIMContext的派生类。 GtkIMContextSimple实现了一个简单的表映射,不能动态加载输入法模块。GtkIMMulticontext可以动态加载输入法模块。

在实验一中我们实现了一个派生自GtkIMContext的输入法模块。GtkEntry通过GtkIMMulticontext对象加载了我们的输入法模块。这个输入法模块与输入法服务器通信,使用GtkIMContext接口实现了中文输入。

如果一个编辑框不是GtkEntry对象,显然就不会加载GTK输入法模块,这时基于GTK版本的输入法就无法使用。例如在poky的浏览器中,网页上的编辑框就不是基于GtkEntry的,无法使用GTK版本的输入法。

2 基于XIM的输入法

XIM(X Input Method)是X Window的输入法协议。如果系统的GUI方案是GTK+X,那么基于XIM的输入法就有更好的兼容性。所谓“更好”也是相对的,如果系统的GUI方案是GTK+DirectFB,自然就用不着XIM。

XIM规定了输入法服务器和XIM客户程序的通信规程。只要通信双方都遵守规程,输入法就能正常运作。有一个叫IMdkit的程序库可以简化服务器的开发。基于XIM的输入法通常都会使用这个开发于1994年的程序库。

GTK里面有一个叫imxim的输入法模块。这个模块在GtkIMContext接口的基础上实现XIM客户程序。即它实现了GTK IM和XIM之间的接口转换。只要加载了这个模块,基于GtkEntry的编辑框也可以使用基于XIM的输入法。 imxim也是一个不错的XIM客户程序实例。

2.1 XIM运作机制

和基于gtk的输入法一样,要实现输入法总是要从编辑器里截获按键事件传递给服务器,服务器组字后把输入文本再送回编辑器。在gtk输入法中,gtk im模块是客户,客户与服务器的通信协议是我们自己定义的。在XIM中,客户和服务器的协议是XIM规范规定的。

上图来自谢东翰先生的《Xi18n 程式设计简介》。图中的序号标示出中文输入的典型步骤:

  1. 在基于X的系统中,键盘和显示都是X Server控制的。X Server检测到按键。
  2. X Server向客户窗口发送按键事件。
  3. 客户程序在X事件循环里用XFilterEvent函数过滤XIM服务器需要的事件。例如:
     for (;;) {XNextEvent (dpy, &event);if (XFilterEvent (&event, None) == True) {continue;}//处理X事件......}
    
  4. 如果Xlib找到了locale匹配的XIM服务器,而且服务器是激活的,XFilterEvent就会把相关事件交给XIM服务器。如果用了IMdkit库,服务器就会收到XIM_FORWARD_EVENT等XIM呼叫。
  5. 用户在服务器的输入窗口完成组字,服务器调用IMdkit库的IMCommitString函数将输入文本送回客户程序。服务器只处理自己需要的按键,其它按键可以用IMForwardEvent函数送回客户程序。

2.2 实现XIM输入法

在IMdkit库的帮助下,在服务器侧实现XIM接口还是比较简单的。用IMOpenIM创建XIM服务,登记回调函数(例如MyProtoHandler)。当服务器接收到XIM呼叫时,回调函数会被调用。下面是典型的回调函数:

static Bool MyProtoHandler (XIMS ims, IMProtocol * call_data)
{switch (call_data->major_code) {case XIM_OPEN:return MyOpenHandler ((IMOpenStruct *) call_data);case XIM_CLOSE:return MyCloseHandler ((IMOpenStruct *) call_data);break;case XIM_FORWARD_EVENT:ProcessKey (ims, (IMForwardEventStruct *) call_data);return True;// IC管理case XIM_CREATE_IC:return MyCreateICHandler ((IMChangeICStruct *) call_data);case XIM_DESTROY_IC:return MyDestroyICHandler ((IMChangeICStruct *) call_data);case XIM_GET_IC_VALUES:return MyGetICValuesHandler ((IMChangeICStruct *) call_data);case XIM_SET_IC_VALUES:return MySetICValuesHandler ((IMChangeICStruct *) call_data);break;// 焦点case XIM_SET_IC_FOCUS:return MySetFocusHandler (ims, (IMChangeFocusStruct *) call_data);case XIM_UNSET_IC_FOCUS:return MyUnsetFocusHandler (ims, (IMChangeICStruct *) call_data);;case XIM_TRIGGER_NOTIFY:return MyTriggerNotifyHandler((IMTriggerNotifyStruct *) call_data);default:DEBUGP("major_code=%d\n", call_data->major_code);break;}return True;
}

应用程序打开和关闭连接时,服务器收到XIM_OPEN和XIM_CLOSE。IC代表输入上下文,即客户程序中的一个编辑框。只有先处理好IC,服务器才能收到XIM_FORWARD_EVENT,即按键事件。 XIM呼叫的处理方法可以参照IMdkit例程或其它输入法程序。

在实验一中,我们已经实现了基于gtk的输入法。现在只要将服务器接口部分用XIM实现就可以了。服务器接口部分使用输入法引擎的以下接口:

  1. 打开和关闭输入法。

    void ime_enable(void);
    void ime_disable(void);
    

    在打开/关闭连接和获得/失去焦点时调用。在基于GTK的输入法中,我把输入法开关状态保存在gtk im模块里面。在XIM版本中,我们要在服务器用链表保存每个客户的输入法开关状态。

  2. 输入按键。

    boolean ime_mgr_input(void *user, int c);
    

    第一个参数是可以标识客户的句柄,第二个参数是输入的字符。返回值表示按键是否已经处理。如果按键需要进一步处理,该函数返回FALSE,服务器接口调用IMForwardEvent将按键事件送回客户程序。

  3. 根据光标位置移动输入窗口。

    void ime_move_input(int cursor_x, int cursor_y, int cursor_h);
    

    在XIM_SET_IC_VALUES呼叫中得到光标位置后调用ime_move_input。在gtk版本中,我们可以得到光标高度。在XIM版本,我不知道怎么获取光标高度,只好用固定值。

服务器接口部分要对外提供两个接口:

  1. 由主程序调用的初始化接口。

    int ime_svr_init(void);
    

    返回值小于0表示初始化失败,否则成功。

  2. 由输入法引擎调用的文本提交接口。

    void ime_svr_send(void *user, const char *str);
    

    输入法引擎使用这个接口提交输入文本,第一个参数是由ime_mgr_input传入的客户句柄。 ime_svr_send用IMCommitString将输入文本送到客户程序。

改写服务器接口部分后,XIM版本的输入法就可以运行了。不算IMdkit库,XIM版本服务器接口部分有539行代码。gtk版本的服务器接口部分有265行代码。相对而言,还是XIM版本麻烦一些。

3 webkit上的测试问题

在poky环境测试,GTK的编辑框里当然可以正常使用,例如:

在网页的编辑框里可以输入中文,但是光标跟随无效,例如:

poky里的浏览器是一个叫web2的小程序,只有740行代码。这个小程序使用了webkit引擎。我打开打印后发现,在连接webkit的网页编辑框时,服务器可以收到:

  • XIM_OPEN
  • XIM_CREATE_IC
  • XIM_GET_IC_VALUES
  • XIM_TRIGGER_NOTIFY
  • XIM_FORWARD_EVENT
  • XIM_SET_IC_FOCUS
  • XIM_DESTROY_IC

但是收不到

  • XIM_SET_IC_VALUES
  • XIM_UNSET_IC_FOCUS

光标跟随是根据XIM_SET_IC_VALUES呼叫中的光标位置实现的,收不到XIM_SET_IC_VALUES,自然就不会移动输入窗口。收不到XIM_UNSET_IC_FOCUS对输入法状态切换也会有影响。

前面说过,XIM是客户和服务器之间的协议,必须双方都遵守协议,输入法才能正常工作。从现象看,webkit上的输入法问题是webkit的编辑器控件没有很好地实现XIM协议引起的。

4 结束语

我重新构建poky,恢复了对XIM的支持,然后为XIM接口写了一个服务器接口,实现了基于XIM接口的输入法。 XIM版本的输入法适合于使用X的环境,它要求客户程序遵守XIM协议。从现象看,浏览器引擎webkit的编辑器控件没有很好地实现XIM协议。

Poky环境的中文输入法实验二(XIM版本)相关推荐

  1. Jetson 配置中文环境,中文输入法,安装QQ

    一.配置中文环境,中文输入法 1. 打开终端:sudo apt-get install fcitx-googlepinyin -y 2.打开设置 找到语言支持(Language Suppor) 2.1 ...

  2. 英文环境下中文输入法的设置

    英文环境下使用ibus输入法 centos安装的时候已经选择了中文支持,输入法也已经安装,但在英文环境下面竟然无法使用中文输入法,解决办法记录于此, 1.安装ibus(centos6以后已经默认安装) ...

  3. CentOS 英文版安装中文环境与中文输入法

    安装了英文版的CentOS,发现没中文的日子真是太难熬了(文件乱码,无法使用中文注释).被虐后决定还是把中文安环境安装上. 1.安装ibus,如果使用的CentOS 6 可以跳过,CentOS 6 已 ...

  4. 【jetson nano】ubuntu18.04 配置pytorch环境 安装中文输入法

    中文输入法候选框一直不显示弄了有两小时.. 以下为安装过程: sudo apt-get install fcitx-googlepinyin fcitx-configtool sudo apt ins ...

  5. 【ubuntu】中文输入法安装二三事

    本来很愉快地刷着JS程序,很有感慨啊,想写篇博客记一下学习笔记,结果忘记了博客账号,后来通过邮箱找回了之后想要开始写..发现ubuntu的中文输入法不能用啊(其实不是不能用,就是小白没搞清楚状况,双系 ...

  6. ubuntu16.04 英文环境安装中文输入法

    1. 安装语言包 System Settings–>Language Support–>Install/Remove Languages 选中chinese,点击Apply应用即可,等待下 ...

  7. Debian10 更换软件源 配置中文环境 安装中文输入法

    说明:看了一下,距离发布上篇文章都快半年了

  8. 【Ubuntu】安装中文输入法、终端不支持中文的解决方法

    一.中文输入法安装 1.安装汉语语言包 sudo apt install fcitx sudo apt install language-pack-zh-hans 2.安装google拼音输入法 su ...

  9. 蓝点中文_linux2.0 实验二 简单shell命令

    一.实验要求 1.掌握简单的shell命令:date ls cd pwd man clear cat grep call 2.中文输入法的启动与切换 3.通配符的含义与使用(*与?) 4.重定向管道( ...

最新文章

  1. Softer-NMS:CMU旷视最新论文提出定位更加精确的目标检测算法
  2. conda设置Python虚拟环境 其他配置
  3. Winsock属性 方法介绍
  4. FastGithub让Github畅通无阻
  5. python中_python中的一些用法总结
  6. SAN Inter-Fabric Routing and Vitrual Fabrics
  7. 在Linux中实现多网卡绑定
  8. 给GridView分页
  9. MySQL关键字constra_mysql总结笔记(一)
  10. 圆内接等边三角形的画法_如何画出圆的内接正三角形
  11. 笔记-Tukey Method发现outliers(离群点)
  12. 引用限定符 reference qualifiers
  13. html短期总结(至表单)
  14. PhpSpreadsheet VS Box\Spout读取excel性能对比
  15. c语言编程题大学,大学C语言程序设计(编程题).pdf
  16. 海信智慧黑板Android版本,海信智慧黑板,给老师减负,再也不用“喝”粉笔末了...
  17. 采集绿盾网的10个经典方法
  18. 编程中常见的Foo,是什么意思。。
  19. 世界上第一台超越早期经典计算机的光量子计算机诞生,世界上第一台超越早期经典计算机的光量子计算机诞生!是货真价实的“中国造”...
  20. 谷歌分布式计算框架MapReduce论文2004 中文翻译

热门文章

  1. Excel实用技巧-如何批量提取excel工作表名称
  2. H5/C3进阶(9) -- 元素的显示与隐藏
  3. Ubuntu安装及常用软件安装
  4. 软件测试:测试管理篇
  5. CentOS下查看电脑硬件设备属性命令
  6. webUploader上传demo
  7. c语言中变量加1,c语言中,指针加1的情况.指针变量详细介绍
  8. 三种最流行的商业模式解析:让顾客感觉占便宜,你才能赚更多钱
  9. maven 官方网站
  10. python复制word段落_使用python将整个word文档(包括表)复制到另一个