`
saybody
  • 浏览: 917964 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

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

阅读更多

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 ();
      else
        entry->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的嵌入式Linux根文件系统的构建.pdf

    * POKY可以用于构建嵌入式Linux根文件系统,提供了快速、稳定的开发环境。 * POKY可以减少开发周期,提高开发效率。 知识点五:Linux根文件系统 * 根文件系统是Linux操作系统的起点和支撑,选择一个好的根文件系统...

    poky:git的镜子

    这意味着poky可能是一个公开的、可供下载和克隆的项目,用于开发者进行协作或构建自己的软件环境。 标签是 "Python",这意味着poky项目可能与Python编程语言有密切关系,或者是使用Python编写的,或者是为Python...

    Poky 编译器,可用于linux下C应用开发

    Poky作为Yocto项目的一部分,扮演着核心编译环境的角色。它包含了构建嵌入式Linux所需的全部工具链,包括GCC(GNU Compiler Collection)编译器、Glibc库、Binutils以及其他的开发工具。这些工具使得开发者可以编写...

    qtcreator-plugin-pokysdk:QtCreator的Poky插件

    这样,开发者可以直接在熟悉的QtCreator环境中编写、编译和调试使用Poky SDK构建的应用程序,无需手动配置复杂的环境变量和路径。 **主要功能** 1. **自动检测和导入**: 插件自动检测并加载Poky SDK,使得开发者...

    meta-debian:Poky的元层通过Debian的源代码构建嵌入式Linux环境

    meta-debian是用于poky构建系统的一组配方(元数据),它允许使用Debian源代码包交叉构建GNU / Linux映像。 通过启用meta-debian,您可以使用Debian源代码为多种体系结构交叉构建一个小的GNU / Linux映像。 meta-...

    yocto 超详细教程,看完必会搭建linux系统

    Yocto:Yocto是这个开源项目的名称,该项目旨在帮助我们自定义...此外Poky还有另外一层意思,使用Poky系统得到的默认参考 Linux 发行版也叫Poky(当然,我们可以对此发行版随意命名)。 很有用的yocto教程,看完包会

    poky:Poky Distro元数据

    4. **Yocto Project**:Poky是Yocto Project的基础,后者是一个由Linux基金会支持的开源项目,旨在为嵌入式设备提供一致且可扩展的开发环境。Yocto Project提供了工具链、构建系统(BitBake)和元数据,使得开发者...

    POKY WooCommerce - Product Importer-crx插件

    POKY WooCommerce版本允许您一键将产品从多个电子商务平台导入/复制到WooCommerce商店,这是一个节省您复制和粘贴时间的好应用程序。 您只需在商店上安装POKY扩展程序,然后在我们的应用程序支持的平台上访问产品...

    Poky - Product Importer-crx插件

    poky 允许您将多电子商务平台从多次电子商务平台导入/复制产品,只需单击一下,它是保存您的时间复制和粘贴的良好应用程序。 您只需在商店安装Poky应用程序并访问我们的应用支持的平台上的产品页面,并启动少量点击...

    mdm9607 mdm9x07编译环境安装

    ### MDM9607 MDM9X07编译环境安装 #### 一、概述 本文档将指导您如何在Ubuntu 12.04或Ubuntu 14(64位)系统上安装、更新及配置MDM9607/MDM9X07的编译环境。为了确保安装过程顺利进行,您需要具备root权限或能够...

    poky.tar.gz

    龙芯平台yocto工程

    yocto环境创建.pdf

    获取Yocto项目工具的过程包括从Yocto官网下载当前发布的版本。用户可以从发布仓库下载Yocto项目所需的所有组件。在Yocto项目中,可以通过Git克隆poky到本地目录。Poky是Yocto项目的基础发行版,包含了构建Yocto系统...

    在ubuntu虚拟机下关于缺少头文件<gnu/stubs.h>的解决办法

    - 而应该使用Poky SDK提供的环境脚本来自动设置所有的环境变量。这是因为直接指定工具链可能会忽略一些必要的编译选项,导致编译失败或缺失必要的头文件。 6. **检查编译命令**: - 确认编译命令是否正确。例如,...

    linux wifi工具hostapd编译方法.doc

    ./configure --host=arm-poky-linux-gnueabi --prefix=/opt/fsl-imx-fb/4.9.88-2.0.0/sysroots/cortexa9hf-neon-poky-linux-gnueabi/usr ``` 需要注意的是,不要加 CC 选项,否则可能会出现问题。 OpenSSL 库 ...

    Qt5.6交叉编译环境搭建.pdf

    文档提到的“基于fsl-yocto-L4.1.15_2.1.0-ga”,这里指的是使用了Freescale提供的Yocto Project构建环境版本L4.1.15_2.1.0-ga。Yocto Project是一个开源项目,用于创建定制化的Linux发行版。此版本的构建环境已经...

    Yocto Project and OpenEmbedded Training

    Yocto 编译环境是指用于构建定制化 Linux 发行版的开发环境。在这个环境中,开发者可以通过配置一系列参数来指定构建的目标平台、软件包、工具链等信息。Yocto 编译环境的核心优势在于其高度的灵活性和可定制性,...

    Yocto学习参考资料.zip

    此外,还涉及了版本管理和持续集成的概念。 7. **dev-manual.pdf**:这是针对Yocto开发者的专用手册,详细介绍了开发环境的搭建、调试工具的使用,以及如何编写和维护自己的软件包。对理解Yocto的开发流程和最佳...

    eclipse-SDK-3.1.1-linux-motif.tar.gz

    二、Eclipse SDK 3.1.1特性 1. 改进的JDT(Java Development Tools):提供了全面的Java语言支持,包括代码编辑、调试、构建和重构工具。 2. PDE(Plug-in Development Environment):用于创建、测试和部署Eclipse...

    ARM交叉编译工具链安装与配置

    文章中提到的工具链版本为arm-linux-gcc-4.4.3,这是较早的一个版本,但是安装流程对其他版本同样适用。 3. 安装步骤详解: 首先,下载工具链的压缩包arm-linux-gcc-4.4.3.tgz到指定目录,然后使用tar命令配合参数x...

Global site tag (gtag.js) - Google Analytics