荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Lg (创造人生的传奇), 信区: Linux
标  题: [thhsieh: xcin-2.5 & OverTheSpot](fwd)
发信站: BBS 荔园晨风站 (Sat Feb 19 20:49:22 2000), 站内信件

【 以下文字转载自 twFreeBSDQuestion 讨论区 】
【 原文由 statue.bbs@linux.twbbs.org 所发表 】
※ 本文转录自 [cle-devel] 看板

发信人: thhsieh@linux.org.tw, 看板: cle-devel
标  题: [thhsieh: xcin-2.5 & OverTheSpot](fwd)
发信站: Taiwan Linux User Group News Server (Fri Feb 18 12:14:28 2000)
转信站: PahudBBS!tlug.sinica!cle-devel
Origin: localhost.localdomain

----- Forwarded message from thhsieh -----

Date: Fri, 18 Feb 2000 12:13:38 +0800
From: thhsieh
To: xcin@linux.org.tw
Subject: xcin-2.5 & OverTheSpot
X-Mailer: Mutt 1.0pre3us

Very sorry, 本来打算昨天晚上 post 的,结果直到现在才写好,请大家参考。

Sorry again, 这真是篇又臭又长的文件,如果您对 OverTheSpot 没兴趣,请直
接跳过好了,否则的话,我很希望您能花一点工夫看一下,这对於我们 developemnt
应该是有帮助的。 :-))

晚一点我会再 post 专文讨论 GUI Request API。


T.H.Hsieh

========================================================================

本文讨论 xcin 与 OverTheSpot input style, winlist 架构,以及目前遭遇
的困鞋、有待完成的部分等等。

1. 什麽是 OverTheSpot?

   这一段开场白是给不晓得这是什麽的朋友看的,已经知道的就直接跳过好了 :-))
   可能写得不好,也请大家多多指点 :-))

   在 XIM 的协定中,有一个称之为 input style 的「协定」,简单讲就是
   XIM server 与 XIM client 之间要以怎麽样的使用者介面展现给使用者。
   XIM 支援的 input style 有很多种,但大体上可以分成 pre_edit area
   (组字区) 与 status area (输入法状态区) 来谈: 这两个区域可以分别
   (或同时) 在输入法视窗上、或出现在您目前的游标附近、或 XIM client
   自己准备一块区域来显示 .... 等等。至於要用那一种 style? 通常都是
   当 XIM client 与 server 搭上线时,它先向 server 询问有那些 style
   可用,然後再从中挑选一种,告诉 server 说指定要使用,二者达成协议
   後即可上路。

   在 xcin-2.5.2-pre1 之前, xcin 只支援一种 input style, 传统上称之
   为 Root, 意思是 pre_edit area 与 status area 都在 xcin 视窗中:前
   者即为视窗第二行那块红棕色的区域 (您所敲入的字键码会依续出现,等
   到敲完之後才会跑出一个完整的字,这过程就是「组字」) ,若遇到多重
   字选择时还会包括视窗的第一行;而後者则为视窗第二行的左右两块区域,
   它们显示了目前 xcin 所处的状态。

   而自 2.5.2-pre1 起,我们尝试替 xcin 加入另一种 input style,传统上
   称之为 OverTheSpot, 它的意思是 pre-edit area 会出现在您目前打字的
   游标附近,而且是由 XIM server (即 xcin) 另外在那游标附近开一个小小
   视窗,而将 pre_edit area 中的资料显示在那。此 input style 最大的好
   处就是 pre_edit area 是跟著游标跑的,如此当您在打字时,您就不用眼
   睛一直移上移下看游标以及 xcin 视窗了。


2. 如何启动 OverTheSpot?

   原则上, xcin 还是以 Root input style 为主,预设是不启动其他 style
   的。如果您要启动 OverTheSpot, 必须修改 xcinrc 档:

(define INPUT_STYLE             '(Root OverTheSpot))

   如此当您在重新启动 xcin 时,您会见到如下的讯息:

XCIN (Chinese XIM server) version xcin 2.5.2-pre1.
(module ver: 20000110, syscin ver: 20000210).
(use "-h" option for help)

xcin: XIM server "xcin" locale "zh_TW.Big5" transport "X/"
xcin: inp_styles: Root OverTheSpot
                  ^^^^^^^^^^^^^^^^
   这样就表示成功启动了。然而,是否接下来就使用 OverTheSpot 来输入,还
   得由 XIM client 来决定 (目前 xcin 不主动为 client 决定), client 还
   是可以指定使用 Root 来输入。但由於 OverTheSpot 是较好的一个 style,
   因此目前绝大部分的 XIM client 在对於使用优先顺序上都是 OverTheSpot
   大於 Root (通常 Root 都是排在最後的)。因此,如果您在 xcin 启动它之
   後,在一般情况下 XIM client 都会指定使用它。


3. 麻烦大了:

   现在有一个很大的问题: 在 XFree86-3.3.X 上 xcin 似乎完全不能使用
   OverTheSpot, 我们做过一些测试,若将 xcin 的 OverTheSpot 启动後, XIM
   client 一见到有它可以用,就很高兴地指定要用,但就在指定的那一刹那
   (client 呼叫 XCreateIC 时) , xcin 却再也无法接收来自 client 的讯息,
   而 client 就直接 XCreateIC 失败 (传回 NULL)。这看起来有点像是, client
   的讯息本来是要经过 Xlib 送达 xcin, 却在中途失败,弹了回来,因此就无
   法使用 OverTheSpot。

   这会有什麽後遗症呢?除了不能用 OverTheSpot 以外,以 rxvt-2.7.x 为例,
   XCreateIC 一失败,它就主动与 xcin 中断连系,这样一来,就等於连 Root
   style 都不会去用,也就等於完全无法输入中文。

   当然,这也许是 rxvt 设计不够完善,如果要完善一点,也许可以设计成: 第
   一个 style 指定失败,就指定第二个,直到成功为止。但我担心,可能没有多
   少个 XIM client 有考虑到这些。例如 Netscape, 也和 rxvt 一样, OverTheSpot
   一失败就直接与 xcin 断讯了。

   因此,就目前情况下启动 xcin 的 OverTheSpot 反而会陷入很糟糕的问题,既
   然绝大部分的 client 预设情况下都会指定使用 OverTheSpot, 偏偏在
   XFree86-3.3.X 下 xcin 无法使用 OverTheSpot, 再来就是一但指定失败,那些
   client 就直接与 xcin 断讯了,这就变成了: 在预设情况下大部分的 client
   都无法接受来自 xcin 的输入。

   因此,在问题未克服之前,若您的系统跑的是 XFree86-3.3.X, 请不要启动 xcin
   的 OverTheSpot。

   然而, PhantomCat 兄曾经向我回报: 在 XFree86-3.9.X (即 XFree86-4 的
   pre-release) 下 xcin 可以使用 OverTheSpot。因此,如果您的系统是使用
   XFree86-3.9.X 的话,您不妨可以试试,看是否正常,并请您向我们回报。

   但奇怪的是,若使用其他的 XIM server (例如韩国的 ami), 它们的 OverTheSpot
   在 XFree86-3.3.X 下可以跑得很好。我也比较过它与 xcin 的程式码,发现
   在处理 XIM 的部分大同小异,因此我不禁有点怀疑是不是 XFree86-3.3.X
   的 XIM 或 Xi18n 的部分,在我们的 locale (zh_TW.Big5) 下有些地方会有
   问题 (记得前一阵子大家才在 CLE 及 Debian 中 patch lcGen 的部分吗)?
   如果是的话,表示 Xlib 还需要进一步 patch, 这就必须再 trace Xlib 原始
   码才会知道了。


4. Winlist 架构:

   因为我的机器还是跑 XFree86-3.3.6, 因此在写 OverTheSpot 部分时,有点半
   瞎子摸象在做,故写出来的部分可能有问题,而且没有写完整,这需要使用
   XFree86-3.9.X 的朋友来帮忙补齐。但我可能要先提一下目前的程式架构,
   好让有兴趣帮忙的朋友容易 follow。

   先前 PhantomCat 兄已寄给我许多 xcin + OverTheSpot 的修正 (再一次谢谢
   他 :-)),而在这一版中我参考了他的修正,将他的 code 整合到 xcin 的
   winlist 中。 xcin 处理 GUI 部分的 source 为:

        include/gui.h           (definition of GUI and winlist data structer)
        gui.c                   (GUI over all structer / tool functions)
        gui_main.c              (xcin main window)
        gui_menusel.c           (GUI Request Menu Selection window)
        gui_overspot.c          (OverTheSpot candidate window)

   就 OverTheSpot 而言,其 GUI 的部分就全部集中在 gui_overspot.c □头,
   而这也是我尚未完成的地方。 gui_overspot.c 的内容如下 (其实 gui_main.c
   与 gui_menusel.c 也是类似):

winlist_t *
gui_overspot_init(gui_t *gui, winlist_t *main_win, IM_Context_t *imc)

   它用来产生 OverTheSpot 所需的视窗,并填好 winlist 的结构 (见 gui.h):

struct winlist_s {
    Window window;                      /* The corresponding window */
    unsigned int wid, imid, reqid;
    byte_t winmap;                      /*  1: window is mapped
                                            0: window is unmapped
                                           -1: window is destoryed */
    int pos_x, pos_y;                   /* The position of the window */
    unsigned int width, height;         /* Window size: in unit of pixels */
    unsigned int c_width, c_height;     /* Window size: in unit of English
                                           characters */
    void *data;                         /* Data for window drawing */
    void (*win_draw_func)(gui_t *, winlist_t *);
                                /* Function to draw the window */
    void (*win_attrib_func)(gui_t *, winlist_t *, XConfigureEvent *, int);
                                /* Function when XConfigureEvent received */
    void (*win_destroy_func)(gui_t *, winlist_t *);
                                /* Function to destroy window */
    winlist_t *next;
};

   其中 wid 是此 Window 的 type, OverTheSpot 应设为 WID_OVERSPOT。 imid
   是目前此 window 相当应该 IMC 号码 (见後述), reqid 在这□不需要用到,
   那是给 GUI Request window 用的,故在此我们不管它。

   当您要 Map window (显示视窗) 与 Unmap window (隐藏视窗) 时,请呼叫
   gui_winmap_change() 函式 (定义在 gui.c), 它会连同 winmap 的值一起
   更新,同时要注意,如果 winmap 的值是 -1 时,请不要再对它做任何画图
   或 change map 的动作,因为那表示该 window 已被 destroy, 不存在了。

   以下三个 function 分别是:

        win_draw_func:  用来画视窗用的,如果程式运作中需要显示或隐藏视
                        窗时,请在此呼叫 gui_winmap_change。而用来画视
                        窗所需的资料就在 data pointer 所指位置。
        win_attrib_func:  当此视窗接到 XConfigureEvent 时 (如视窗被滑鼠
                        拖动,视窗被放大缩小 .... 等),这个函式就会被呼
                        叫,这时我们就可以用它来设定视窗新的 pos_x, pos_y,
                        width, height, etc.
        win_destroy_func:  当此视窗被 destroy 时会被呼叫,这时我们可以用
                        它来做一些收尾的动作 (如果需要的话)

        其中 win_attrib_func 与 win_destroy_func 可以设为 NULL, 则 xcin
        会以预设的方式来处理。

   就 OverTheSpot 而言,我希望它的视窗是可以跟著输入的游标跑,也就是说
   它必须随时改变位置,而且完全不受 Window Manager 的控制。因此,我用了
   XChangeWindowAttributes() 来让它摆脱 WM 的控制,如此,我们就无法用滑
   鼠来移动它的位置、改变它的大小、以及将它关闭了。

   而要让它随著游标移动,它必须随时知道游标目前的位置,其位置是从 IMC
   structer 的 spot_loc 传入的 (见後述) ,因此,在其 win_draw_func 中,
   它必须每次都检查 spot_loc 的值,如果发现变动了,就要做 XMoveWindow 的
   动作。而这部分我还没写。希望使用 XFree86-3.9.X 的朋友可以帮忙补足。

   至於该视窗所展现出来的样子,是一个比 xcin 主视窗还要短一些,但宽度只
   有一列的小视窗。根据定义: 该视窗只用来显示组字状态资料,因此,每当您
   输入一个字键,该字键所对应的码就会出现该视窗,而不会出现在 xcin 主视
   窗。同样的,在组字过程中,如果目前所输入的字键组刚好可以对应一些字,
   则这些字也不会出现在 xcin 主视窗,而是出现在 OverTheSpot 视窗。在做多
   重字选择时,也是在 OverTheSpot 视窗中选择。至於其他 xcin 的状态资讯,
   如 (英数)(全形)(半形) 等,则还是留在 xcin 主视窗中。另外,在 bimsphone
   的自动选字模式下,所打出来的字不会马上跑到 XIM client, 而会暂时留在
   xcin buffer 中,这些字我还是显示在 xcin 主视窗的第一行,与原来一样,
   而不显示在 OverTheSpot 视窗中。原因是我觉得 OverTheSpot 视窗很小,而
   且在输入过程中是「若隐若现」的,因此不适合用来显示 cache 的字。

   事时上,在 OverTheSpot 模式中, xcin 主视窗是否存在已不重要了,重要的
   反而是 OverTheSpot 视窗本身,因此,一个可能的改进是在此模式下 xcin 可
   以自动变成一个 icon, 并在 icon 中显示 (英数)(输入法名)(全形)(半形) 等
   资讯 (我觉得这还是有必要显示的,可以让使用者知道目前正在中文输入状态)。
   但若要这样写的话要注意: 当游标在不同 XIM clients 间切换时, client A
   是使用 Root, client B 则使用 OverTheSpot, xcin 必须要能自动还原或变成
   icon, 这样才能方便使用。这部分我没去写,我想相关的细节可以再讨论。

   在进入中文输入模式时, OverTheSpot 视窗还是不会出现,要直到您开始输入
   第一个中文字键时它才会出现,但一旦您输入好一个字後,它马上又隐藏起来,
   等您要输入下一个字的第一个字键时,它才会再出现。事实上,它只是做 Map
   与 Unmap window 的动作而已,并非 destroy 再重新 create。该 Window 的生
   命期是与 IMC 一样的 (见後述)。


5. IC 与 IMC:

   xcin-2.5.2 与 2.5.1 最大的不同,一个是 winlist 架构 (2.5.1 无法开启多
   重视窗),另一个就是 IC 与 IMC 分离的设计了 (2.5.1 只有 IC 而已)。而这
   两个也是我花最多心力的地方。

   IC 是指 Input Context, 每一个 XIM client 视窗都是一个 Input Context,
   而在 xcin 这边就会为它们分别指定一个 IC 来做服务。每个 IC 都是完全独
   立的,这样才能应付 clients 各 Input Contexts 独立的运作。

   IMC 是指 Input Method Context, 它就是输入法的实际资料结构。以前 IMC
   的部分是直接写在 IC □头的,如此当您在用滑鼠切换 client 视窗时,xcin
   视窗内容 (也就是各 IC 的输入法目前状态) 也跟著变。

   然而,在某些情况下,我们不希望这样,特别是在 bimsphone 输入法上,我
   们往往希望在切换 clients 时,输入法的状态不要改变,尤其是刚刚已输入
   到 xcin buffer □头的那对字。为了达到此要求,才将 IMC 部分自 IC 中分
   离。

   现在 xcin 有两种 mode: XCIN_SINGLE_IMC ON 及 XCIN_SINGLE_IMC OFF。在
   XCIN_SINGLE_IMC OFF 时,每个 IC 都各自会有一个 IMC, 於是各 client 间
   的输入法状态就完全独立。若 XCIN_SINGLE_IMC ON 时,所有的 IC 都会分享
   同一个 IMC, 於是各 client 间的输入法状态就完全一致。

   IC 有它的生命周期,这与 client 的 Input Context 周期是一样的。当一个
   新的 client Input Context 产生时, xcin 这边就产生一个新的 IC, 而当
   client 的 Input Context 结束後, xcin 这边的 IC 也结束了。

   IMC 也有它的生命周期,但视 xcin 所处的 mode 而定。如果是 XCIN_SINGLE_IMC
   ON 时,它的生命周期就与 xcin 主程式一样长。如果是 XCIN_SINGLE_IMC OFF
   时,它的生命周期就与 IC 一样长。

   就 OverTheSpot 而言,我认为它应该是属於 IMC 管理的,而非 IC, 例如在
   XCIN_SINGLE_IMC ON 下,所有的 IC 的输入法状态都一样,则假设我们已开
   始在 client 视窗 A 打字, OverTheSpot window 也出现在视窗 A 的游标附
   近,如果我们临时换到视窗 B 打字时,我希望 OverTheSpot window 可以原
   封不动地移位到视窗 B 的游标位置,而非视窗 A 那个 OverTheSpot window
   消失,视窗 B 这边另外跑出一个 OverTheSpot window (这应该是在
   XCIN_SINGLE_IMC OFF 的情况下)。因此,我才决定将 OverTheSpot 归於 IMC
   来管理。因此,它的生命周期要与 IMC 一样。

   但是,我刚刚才看到,目前我的写法是不管 xcin mode 如何, OverTheSpot
   的生命周期与 IC 都一样,这不是我所预期的,我会将它改过来 (见 xim_IC.c
   ic_destroy(), 当 xccore->gui.winchange |= WIN_CHANGE_OVERSPOT_END 时,
   就是通知 该 IC 底下的 IMC 底下的 OverTheSpot window 要 destroy 了)。

   这□还要提一下 IMC 的状态: inp_state (见 include/IC.h), 这□要很小心
   处理。它可以有如下几个状态:

        IM_CINPUT ON:   此 IMC 进入中文输入模式
        IM_CINPUT OFF:  此 IMC 处於英文输入模式
        IM_2BYTES ON:   此 IMC 进入全形输入模式
        IM_2BYTES OFF:  此 IMC 处於半形输入模式
        IM_XIMFOCUS ON: 此 IMC 所处 IC 进入 focus 状态
        IM_XIMFOCUS OFF:此 IMC 所处 IC 离开 focus 状态

   这□讨论 IM_CINPUT 与 IM_XIMFOCUS 就好,IM_2BYTES 原理与 IM_CINPUT 类
   似。所谓 IC 进入 focus 状态,是指该 IC 所对应的 XIM client 视窗被滑鼠
   点选,成为前景视窗,接下来键盘打字就会直接作用在该 client 视窗上。因此:

        client 为前景视窗时但处於英文输入时,则它的 IMC 状态就是
                IM_CINPUT OFF, IM_XIMFOCUS ON
        client 为前景视窗时但处於中文输入时,则它的 IMC 状态就是
                IM_CINPUT ON, IM_XIMFOCUS ON
        client 不是前景视窗时但处於中文输入时,则它的 IMC 状态就是
                IM_CINPUT ON, IM_XIMFOCUS OFF

   就 OverTheSpot 视窗而言,我希望在它所属的 IC 是在 focus 状态,而
   且其 IMC 进入中文输入时,它才会出现。一旦 focus 改变,或变回英文
   输入时,它就要隐藏起来。这就是为什麽我在 gui_overspot_draw() (见
   gui_overspot.c) 中一开始时做那麽多 check 的原因。

   最後谈到 spot location 的部分。前面有稍微提到, client 的游标若移
   动,则它会马上将目前的游标位置传给 xcin, 而 xcin 就会将它放在 spot
   location 中供 OverTheSpot 使用。 spot location 分别在 IC 与 IMC 中
   各有一份 (见 include/IC.h):

        IC->pre_attr.spot_location
        IMC->spot_loc

   事实上,我觉得 spot location 只要存在 IMC □头就好了,但之所以这样
   做的考量如下: 在 XCIN_SINGLE_IMC ON 状态下,我本来是 focus 在 client A,
   现在改 focus 在 client B,然而 client B 在进入 focus 时并没有通知 xcin
   它目前的游标位置 (它可能认为先前已通知过了),会发生什麽事呢?结果我猜
   是,该 OverTheSpot 可能还会留在 client A 的游标位置,甚至可能是: client
   A 虽在背景,但游标因故一直在动,而 client B 因为在前景正接受输入中,结
   果 OverTheSpot window 就这样在 client A B 之间快速地跳来跳去。

   因此,目前我的设计是,当 xcin 一接到 client 新的游标位置,它就存到 IC
   的 spot location 中,若目前此 IC 正处於 focus 状态时,它再拷备一份给目
   前它所使用的 IMC 的 spot location 去, 而 OverTheSpot window 永远只参考
   IMC 的 spot location 来移动视窗。如此,各 IC 可以随时追踪其 client 的
   游标位置,而 OverTheSpot window 中位随著目前 focus 中的 client 的游标
   移动。

   啊! 又被我见到一个 bug, 我目前的程式没有这样写,当 IC 接到一个新的 spot
   location 时,马上会拷一份给 IMC, 结果就会造成上头一样的问题。我想 IC 这
   边还需要增加一个 flag, 以标示目前它是否处於 focus 状态才行 (目前没有),
   我晚一点就会改过来。


6. 结语:

   我在写 OverTheSpot 部分时,是在 Root input style 底下做的,由於 spot
   location 永远都固定,所以 OverTheSpot window 自然不会随著游标跑,也难
   以鉴别各 client 间 focus 切换对 OverTheSpot window 的影响,所以等於是
   瞎子模象在写程式。我希望使用 XFree86-3.9.X 的朋友可以帮忙完成我未完成
   的部分,并帮忙测试。

   同时,我也欢迎高手们帮忙追查 XFree86-3.3.X 无法使用 xcin OverTheSpot
   的真正原因,必竟目前绝大部分的 GNU/Linux 与 FreeBSD 系统都还在跑
   XFree86-3.3.X, 如果它不 work, 我们现在做这 OverTheSpot 也是枉然的。
   我很希望大家都能轻易使用它,享受它所带来的便利。


T.H.Hsieh

----- End forwarded message -----
--
※ 转载:·BBS 荔园晨风站 bbs.szu.edu.cn·[FROM: 210.39.3.97]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店