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

Date: Fri, 18 Feb 2000 12:13:38 +0800
From: thhsieh
To: [EMAIL PROTECTED]
Subject: xcin-2.5 & OverTheSpot
X-Mailer: Mutt 1.0pre3us

Very sorry, 本來打算昨天晚上 post 的,結果直到現在才寫好,請大家參考。

Sorry again, 這真是篇又臭又長的文件,如果您對 OverTheSpot 沒興趣,請直
[EMAIL PROTECTED]@下,這對於我們 developemnt
應該是有幫助的。 :-))

[EMAIL PROTECTED]|再 post 專文討論 GUI Request API。


T.H.Hsieh

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

本文討論 xcin 與 OverTheSpot input style, winlist 架構,以及目前遭遇
的困鞋、有待完成的部分等等。

1. 什麼是 OverTheSpot?

   [EMAIL PROTECTED] :-))
   可能寫得不好,也請大家多多指點 :-))

   在 XIM [EMAIL PROTECTED] input style 的「協定」,簡單講就是
   XIM server 與 XIM client 之間要以怎麼樣的使用者介面展現給使用者。
   XIM 支援的 input style 有很多種,但大體上可以分成 pre_edit area
   (組字區) 與 status area (輸入法狀態區) 來談: 這兩個區域可以分別
   (或同時) 在輸入法視窗上、或出現在您目前的游標附近、或 XIM client
   [EMAIL PROTECTED] .... [EMAIL PROTECTED] style? 通常都是
   當 XIM client 與 server 搭上線時,它先向 server 詢問有那些 style
   [EMAIL PROTECTED] server 說指定要使用,二者達成協議
   後即可上路。

   在 xcin-2.5.2-pre1 之前, xcin [EMAIL PROTECTED] input style, 傳統上稱之
   為 Root, 意思是 pre_edit area 與 status area 都在 xcin 視窗中:前
   者即為視窗第二行那塊紅棕色的區域 (您所敲入的字鍵碼會依續出現,等
   到敲完之後才會[EMAIL PROTECTED]) ,若遇到多重
   字選擇時還會[EMAIL PROTECTED]
   它們顯示了目前 xcin 所處的狀態。

   而自 2.5.2-pre1 起,我們嘗試替 xcin [EMAIL PROTECTED] input style,傳統上
   稱之為 OverTheSpot, 它的意思是 pre-edit area 會出現在您目前打字的
   游標附近,而且是由 XIM server (即 xcin) [EMAIL PROTECTED]
   視窗,而將 pre_edit area 中的資料顯示在那。此 input style 最大的好
   處就是 pre_edit area 是跟著游標跑的,如此當您在打字時,您就不用眼
   [EMAIL PROTECTED] 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 [EMAIL PROTECTED] style, 
   因此目前絕大部分的 XIM client 在對於使用優先順序上都是 OverTheSpot
   大於 Root (通常 Root 都是排在最後的)。因此,如果您在 xcin 啟動它之
   [EMAIL PROTECTED] XIM client 都會指定使用它。


3. 麻煩大了:

   [EMAIL PROTECTED]: 在 XFree86-3.3.X 上 xcin 似乎完全不能使用 
   OverTheSpot, [EMAIL PROTECTED] xcin 的 OverTheSpot 啟動後, XIM 
   client [EMAIL PROTECTED]@剎那 
   (client 呼叫 XCreateIC 時) , xcin 卻再也無法接收來自 client 的訊息,
   而 client 就直接 XCreateIC 失敗 (傳回 NULL)。這看起來有點像是, client
   的訊息本來是要經過 Xlib 送達 xcin, 卻在中途失敗,彈了回來,因此就無
   法使用 OverTheSpot。

   這會有什麼後遺症呢?除了不能用 OverTheSpot 以外,以 rxvt-2.7.x 為例,
   XCreateIC [EMAIL PROTECTED] xcin [EMAIL PROTECTED] Root
   style 都不會去用,也就等於完全無法輸入中文。

   當然,這也許是 rxvt [EMAIL PROTECTED]: 第
   [EMAIL PROTECTED] style 
指定失敗,就指定第二個,直到成功為止。但我擔心,可能沒有多
   少個 XIM client 有考慮到這些。例如 Netscape, 也和 rxvt [EMAIL PROTECTED] 
OverTheSpot
   [EMAIL PROTECTED] xcin 斷訊了。

   因此,就目前情況下啟動 xcin 的 OverTheSpot 反而會陷入很糟糕的問題,既
   然絕大部分的 client 預設情況下都會指定使用 OverTheSpot, 偏偏在 
   XFree86-3.3.X 下 xcin 無法使用 OverTheSpot, [EMAIL PROTECTED]
   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) 下有些地方會有
   問題 ([EMAIL PROTECTED] CLE 及 Debian 中 patch lcGen 的部分嗎)?
   如果是的話,表示 Xlib [EMAIL PROTECTED] patch, 這就必須再 trace Xlib 原始
   碼才會知道了。


4. Winlist 架構:

   因為我的機器還是跑 XFree86-3.3.6, 因此在寫 OverTheSpot 部分時,有點半
   瞎子摸象在做,故寫出來的部分可能有問題,而且沒有寫完整,這需要使用
   XFree86-3.9.X [EMAIL PROTECTED]
   好讓有興趣幫忙的朋友容易 follow。

   先前 PhantomCat 兄已寄給我許多 xcin + OverTheSpot 的修正 ([EMAIL PROTECTED]
   他 :-))[EMAIL PROTECTED] 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 [EMAIL PROTECTED]
   更新,同時要注意,如果 winmap 的值是 -1 時,請不要再對它做任何畫圖
   或 change map [EMAIL PROTECTED] window 已被 destroy, 不存在了。

   以下三個 function 分別是:

        win_draw_func:  [EMAIL PROTECTED]
                        窗時,請在此呼叫 gui_winmap_change。而用來畫視
                        窗所需的資料就在 data pointer 所指位置。
        win_attrib_func:  當此視窗接到 XConfigureEvent 時 (如視窗被滑鼠
                        拖動,視窗被放大縮小 .... 等),這個函式就會被呼
                        叫,這時我們就可以用它來設定視窗新的 pos_x, pos_y,
                        width, height, etc.
        win_destroy_func:  當此視窗被 destroy 時會被呼叫,這時我們可以用
                        [EMAIL PROTECTED]@ (如果需要的話)

        其中 win_attrib_func 與 win_destroy_func 可以設為 NULL, 則 xcin 
        會以預設的方式來處理。

   就 OverTheSpot 而言,我希望它的視窗是可以跟著輸入的游標跑,也就是說
   它必須隨時改變位置,而且完全不受 Window Manager 的控制。因此,我用了
   XChangeWindowAttributes() 來讓它擺脫 WM 的控制,如此,我們就無法用滑
   鼠來移動它的位置、改變它的大小、以及將它關閉了。

   而要讓它隨著游標移動,它必須隨時知道游標目前的位置,其位置是從 IMC 
   structer 的 spot_loc 傳入的 (見後述) ,因此,在其 win_draw_func 中,
   它必須每次都檢查 spot_loc 的值,如果發現變動了,就要做 XMoveWindow 的
   [EMAIL PROTECTED] XFree86-3.9.X 的朋友可以幫忙補足。

   [EMAIL PROTECTED] xcin [EMAIL PROTECTED]
   [EMAIL PROTECTED]: 該視窗只用來顯示組字狀態資料,因此,每當您
   [EMAIL PROTECTED]|出現該視窗,而不會出現在 xcin 主視
   [EMAIL PROTECTED]
   則這些字也不會出現在 xcin 主視窗,而是出現在 OverTheSpot 視窗。在做多
   重字選擇時,也是在 OverTheSpot 視窗中選擇。至於其他 xcin 的狀態資訊,
   如 (英數)(全形)(半形) 等,則還是留在 xcin 主視窗中。另外,在 bimsphone
   的自動選字模式下,所打出來的字不會馬上跑到 XIM client, 而會暫時留在
   xcin buffer 中,這些字我還是顯示在 xcin [EMAIL PROTECTED]@樣,
   而不顯示在 OverTheSpot 視窗中。原因是我覺得 OverTheSpot 視窗很小,而
   且在輸入過程中是「若隱若現」的,因此不適合用來顯示 cache 的字。

   事時上,在 OverTheSpot 模式中, xcin 主視窗是否存在已不重要了,重要的
   反而是 OverTheSpot [EMAIL PROTECTED] xcin 可
   [EMAIL PROTECTED] icon, 並在 icon 中顯示 (英數)(輸入法名)(全形)(半形) 等
   資訊 (我覺得這還是有必要顯示的,可以讓使用者知道目前正在中文輸入狀態)。
   但若要這樣寫的話要注意: 當游標在不同 XIM clients 間切換時, client A
   是使用 Root, client B 則使用 OverTheSpot, xcin 必須要能自動還原或變成
   icon, 這樣才能方便使用。這部分我沒去寫,我想相關的細節可以再討論。

   在進入中文輸入模式時, OverTheSpot 視窗還是不會出現,要直到您開始輸入
   [EMAIL PROTECTED]|[EMAIL PROTECTED]@個字後,它馬上又隱藏起來,
   [EMAIL PROTECTED]@個字鍵時,它才會再出現。事實上,它只是做 Map
   與 Unmap window [EMAIL PROTECTED] destroy 再重新 create。該 Window 的生
   命期是與 IMC [EMAIL PROTECTED] (見後述)。


5. IC 與 IMC:

   xcin-2.5.2 與 2.5.1 [EMAIL PROTECTED] winlist 架構 (2.5.1 無法開啟多
   重視窗)[EMAIL PROTECTED] IC 與 IMC 分離的設計了 (2.5.1 只有 IC 而已)。而這
   兩個也是我花最多心力的地方。

   IC 是指 Input Context, [EMAIL PROTECTED] XIM client [EMAIL PROTECTED] Input 
Context,
   而在 xcin 這邊就會[EMAIL PROTECTED] IC 來做服務。每個 IC 都是完全獨
   立的,這樣才能應付 clients 各 Input Contexts [EMAIL PROTECTED]

   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 都各自會[EMAIL PROTECTED] IMC, 於是各 client 
間
   的輸入法狀態就完全獨立。若 XCIN_SINGLE_IMC ON 時,所有的 IC 都會分享
   [EMAIL PROTECTED] IMC, 於是各 client [EMAIL PROTECTED]

   IC 有它的生命週期,這與 client 的 Input Context [EMAIL PROTECTED]@個
   新的 client Input Context 產生時, xcin [EMAIL PROTECTED] IC, 而當
   client 的 Input Context 結束後, xcin 這邊的 IC 也結束了。

   IMC 也有它的生命週期,但視 xcin 所處的 mode 而定。如果是 XCIN_SINGLE_IMC
   ON 時,它的生命週期就與 xcin [EMAIL PROTECTED] XCIN_SINGLE_IMC OFF
   時,它的生命週期就與 IC [EMAIL PROTECTED]

   就 OverTheSpot 而言,我認為它應該是屬於 IMC 管理的,而非 IC, 例如在
   XCIN_SINGLE_IMC ON 下,所有的 IC [EMAIL PROTECTED]
   始在 client 視窗 A 打字, OverTheSpot window 也出現在視窗 A 的游標附
   近,如果我們臨時換到視窗 B 打字時,我希望 OverTheSpot window 可以原
   封不動地移位到視窗 B 的游標位置,而非視窗 A 那個 OverTheSpot window
   消失,視窗 B [EMAIL PROTECTED] OverTheSpot window (這應該是在
   XCIN_SINGLE_IMC OFF 的情況下)。因此,我才決定將 OverTheSpot 歸於 IMC
   來管理。因此,它的生命週期要與 IMC [EMAIL PROTECTED]

   但是,我剛剛才看到,目前我的寫法是不管 xcin mode 如何, OverTheSpot
   的生命週期與 IC [EMAIL PROTECTED]|將它改過來 (見 xim_IC.c
   ic_destroy(), 當 xccore->gui.winchange |= WIN_CHANGE_OVERSPOT_END 時,
   就是通知 該 IC 底下的 IMC 底下的 OverTheSpot window 要 destroy 了)。

   [EMAIL PROTECTED] 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 視窗被滑鼠
   點選,成為前景視窗,接下來鍵盤打字就會[EMAIL PROTECTED] 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 進入中文輸入時,它才會[EMAIL PROTECTED] focus 改變,或變回英文
   輸入時,它就要隱藏起來。這就是為什麼我在 gui_overspot_draw() (見
   gui_overspot.c) [EMAIL PROTECTED] check 的原因。

   最後談到 spot location 的部分。前面有稍微提到, client 的游標若移
   動,則它會馬上將目前的游標位置傳給 xcin, 而 xcin 就會將它放在 spot
   location 中供 OverTheSpot 使用。 spot location 分別在 IC 與 IMC 中
   [EMAIL PROTECTED] (見 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 [EMAIL PROTECTED] client B 因為在前景正接受輸入中,結
   果 OverTheSpot window 就這樣在 client A B 之間快速地跳來跳去。

   因此,目前我的設計是,當 xcin [EMAIL PROTECTED] client 
新的游標位置,它就存到 IC
   的 spot location 中,若目前此 IC 正處於 focus [EMAIL PROTECTED]
   前它所使用的 IMC 的 spot location 去, 而 OverTheSpot window 永遠只參考 
   IMC 的 spot location 來移動視窗。如此,各 IC 可以隨時追蹤其 client 的
   游標位置,而 OverTheSpot window 中位隨著目前 focus 中的 client 的游標
   移動。

   啊! [EMAIL PROTECTED] bug, 我目前的程式沒有這樣寫,當 IC [EMAIL PROTECTED] 
spot
   location 時,馬上會[EMAIL PROTECTED] IMC, 結果就會[EMAIL PROTECTED] IC 這
   [EMAIL PROTECTED] flag, 以標示目前它是否處於 focus 狀態才行 (目前沒有),
   [EMAIL PROTECTED]|改過來。


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 -----

Reply via email to