小狼毫的 TSF 移植

1,285 views
Skip to first unread message

Wish

unread,
Aug 14, 2012, 10:41:48 AM8/14/12
to rime-...@googlegroups.com
各位,

我正在实作着小狼毫的 TSF 移植,本意是为了兼容 Win8 Metro
界面,并改善程序兼容性。目前Win32应用程序的支持已经比较完善,所以请大家帮忙一起测试捉虫!

代码直接在原先空白的 WeaselTSF 项目上开发,仓库位置在 https://github.com/wishstudio/weasel
还是按照原来的方法编译,会在 output 下生成 weasel.dll(32位)和
weaselx64.dll(64位)(台湾的键盘布局还没有写)。先按照原先方法安装写入注册表信息,再开一个管理员命令行到这个目录下,运行
regsvr32 weasel.dll,regsvr32 weasel64.dll
注册。之后就应该可以在语言栏找到,为了和IMM32的区别,暂时取名 Weasel。

除此之外,还有一些编程中的思考与问题,拿出来跟大家讨论:

1. Composition
现在小狼毫的结构,相当于是在候选框中集成了显示输入序列和候选词的功能。但是在 TSF
的标准实现中,输入序列是直接在文档中显示的(类似微软拼音传统模式、系统自带仓颉那样的)。TSF 下处理这个 Composition
的功能很强大,可以进行移动光标位置、修改文本甚至修改文本的颜色和样式。于是我们可不可以提供这么一种输入的模式。
另一个考虑的原因是,由于TSF的标准输入模式是这样,导致很多控件只按照这种模式设计。我自己的实验表明,如果不开 Composition
直接拦截按键,或者开始 Composition
后没有插入过任何字符,则不少控件下会无法获取到正确的光标位置。目前我采取了一些方法来绕过这个问题(代码里搜CUAS)。如果采用标准的方式使用
Composition,我测试过的所有程序都是正常的。

2. Metro 支持
现阶段输入法会告诉Windows表示自己支持Metro,在Metro下也确实可以输入文字,但是候选框界面不能弹出,原因是在 Metro
界面上不能覆盖显示 Win32 的窗口,所以候选框必须在输入法端显示。这样在 IPC
部分至少需要增加返回当前输入序列和候选词列表,然后我们在TSF部分画出窗口。Metro下微软拼音是采用输入序列嵌入控件的形式,我们是按照Metro的规范重新写界面还是直接拿
WeaselUI?

3. 语言栏
* 语言栏图标?(Win8 的设计规范参见一下
http://msdn.microsoft.com/en-us/library/windows/apps/hh967425.aspx 中间的
IME icons 部分)
* 把 WeaselServer 的托盘图标集成到语言栏?

4. 安装
谁能帮忙补充一下安装脚本?
另外我们需要测试决定在哪些版本的系统下默认使用 TSF 框架的输入法。

谢谢!

弓辰

unread,
Aug 14, 2012, 11:21:37 AM8/14/12
to rime-...@googlegroups.com
高!實在辛苦了。TSF據說接口很複雜呢。

嵌入CompositionString,我支持在XP之後的系統上以此形式爲標準。IME輸入法把它顯示在候選窗口中,主要是因爲IME框架下不容易實現內嵌的效果。事實上Mac版本的【鼠鬚管】正是將輸入串內嵌顯示的,不過最近隨着用戶多起來、升級到新版Mac系統,發現一些兼容性問題可能與此有關,所以,兩種形式的選項都提供給用戶,是最好的。

WeaselUI支持顯示三項內容:preedit行、aux行、候選列表。這個佈局是從IBUS的介面繼承下來的。通常preedit顯示輸入碼,以及已經確認的部分文字;aux行顯示附加的提示文字(現在基本不用了)。把其中某一部分留作空值,就會使其不在介面上出現。所以上層想要改變佈局並不難。

使用語言欄,我也十分贊成,這也是我一直想做的事,只是顧不上呀!放一個圖標表示中、西文轉換狀態,再加一個菜單就好。不過爲此,後臺需要把狀態也告知TSF前端。

候選窗口,在【小狼毫】最初的版本裏,是由IME繪製的。那時有  鄒旭同學專門寫了一套簡單有效的序列化機制,把preedit, aux, candidate傳遞給Weasel.ime。
後來把UI遷移到後端,是考慮到程序升級後已經加載過IME的那些程序不能立即應用新的IME前端,而後端可以隨時重啓讓用戶立即看到界面的改進。不過這種前後端分離的機制可能無法適用於(Metro)Modern UI。因爲據說Win8加強了對程序權限的控制,在一些程序裏創建進程、乃至IPC操作都被禁止了。所以對於Modern UI,不僅候選窗要由TSF創建、而且整個librime的詞庫和算法部分都無法放在獨立進程中執行,必須探索與Desktop不同的架構。

上週,我生意上的一位朋友正巧也在研究Win8上的輸入法,我將Rime編譯成一份DLL供其實驗,當真在Win8的Modern介面上跑起來了。不過其研究成果可能不便公佈,我把你的取得進展向他介紹下,看能否交流一下經驗。

Wish <wishs...@gmail.com> 於 2012年8月14日星期二寫道:
> --
>
>
>
>

Wish

unread,
Aug 14, 2012, 11:37:49 AM8/14/12
to rime-...@googlegroups.com
Metro 下 IPC 似乎没有禁止,因为我纯粹只是在注册的时候告诉 windows 表示我可以支持 Metro,结果在 metro
下就可以输入文字了,不过还要试验一下候选框怎么显示。我在Metro下也安装过会启动后台进程的程序,似乎也没见着有特殊的权限要求。

我觉得目前这样的架构还是挺好的,最起码调试起来非常方便。TSF
一旦加载似乎不把应用程序关了就不会卸载,我现在重新编译都经常要关一堆程序。采用这样架构,至少修改到librime部分,就不需要重启程序了。

Composition的部分,我这两天去读读 WeaselServer 和 WeaselUI,看能不能写出来 :)

2012/8/14 弓辰 <chen...@gmail.com>:

> --
>
>
>

弓辰

unread,
Aug 14, 2012, 12:09:56 PM8/14/12
to rime-...@googlegroups.com
找到了當年把UI挪到後臺的Revision:

http://code.google.com/p/rimeime/source/detail?r=256

之前都有把composition和candidate序列化、傳給IME。

Wish <wishs...@gmail.com> 於 2012年8月14日星期二寫道:
> --
>
>
>
>

Wish

unread,
Aug 15, 2012, 10:32:01 AM8/15/12
to rime-...@googlegroups.com
初步实现了嵌入式的Composition String。
现在librime传过来的preedit串是用">"来表示光标的,这样前端处理有点麻烦。另外感觉用空格来作分隔符,在实际使用时,至少对拼音来说感觉不如用标准的单引号看得舒服。
还有一个细节是如果我在拼音中移动光标到分隔符的位置,那个分隔符会消失。这个如果开始用真实的光标的话会感觉很奇怪。

2012/8/15 弓辰 <chen...@gmail.com>:

> --
>
>
>

弓辰

unread,
Aug 15, 2012, 11:04:51 AM8/15/12
to rime-...@googlegroups.com
答:「›」是爲了在自己繪製的地方標明插入位置,inline的話已經有真實的光標,這方面 ibus-rime 已經用了一個比較好的解法。回頭介紹一下,你也可去看看代碼。

分隔符用哪個是在輸入方案裏定義的。speller/delimiter: 這項,字符串裏第一個字符用來自動插入音節之間;其他的分隔符號也允許手動輸入。

光標位置之後的內容不做轉換,因此也就沒有切分信息。這與微軟拼音的整句編輯模式不同。

2012/8/15 Wish <wishs...@gmail.com>

Wish

unread,
Aug 15, 2012, 11:15:23 AM8/15/12
to rime-...@googlegroups.com
好,我去读读ibus-rime。
另:我大概了解metro下应该怎么做了。要下决心把界面再移到前端嘛?
TSF之下因为输入法就是个COM组件,只要还有程序用着没有完全关掉,就会一直占着DLL,所以之前你说的更新问题根本不可能出现,我们想做的更好只能研究怎么在更新的时候通知所有的TSF自动关闭、重启。

2012/8/15 弓辰 <chen...@gmail.com>:

> --
>
>
>

弓辰

unread,
Aug 15, 2012, 11:39:22 AM8/15/12
to rime-...@googlegroups.com
難道是METRO下IPC確有限制?我只是聽說如此,好像和應用所具有的權限相關。
更新的問題,就是加載後的DLL無法換成新版本。因爲不能強行關閉用戶的程序。

另外,OnTestKeyDown() 和 OnKeyDown() 的問題我之前提出一個解法給用RIME做實驗的朋友:

因爲RIME把判斷和處理在RimeProcessKey()裏面一起做完,而以上兩函數需要其返回值,系統可能兩者各調用一次,也可能只調用一個。於是:
將 RimeProcessKey() 看作生產者,返回的值提供給 OnTestKeyDown() 和 OnKeyDown() 各一;
無論二者誰先被TSF調用,因無儲備值可用,該測試函數發起調用 RimeProcessKey() 使兩者各獲得一個返回值,調用者立即消費該值;(就同一按鍵)另一測試函數若也被TSF調用,則直接返回剛剛獲得的儲備值。處理將結束時,RimeProcessKey() 已經調用過,所以真正的處理已經完成,只需RimeGetXXX()、更新介面;但最後要清除未用的儲備值,以免下次按鍵誤用了。

2012/8/15 Wish <wishs...@gmail.com>

Wish

unread,
Aug 15, 2012, 11:57:12 AM8/15/12
to rime-...@googlegroups.com
IPC暂未发现限制。但是Desktop下的窗口不能覆盖在Metro界面之上,所以导致候选窗口不能显示出来。我目前查到的微软给的显示候选窗口的方法是把候选窗口的父窗口(owner)设置为他给你的窗口。我还不太清楚目前架构下能不能实现。

权限相关的比如说网络,可能输入法有在线同步的功能,但当前运行的程序可能没有网络权限,不过微软的文档里有提到可以用IPC来绕过。

2012/8/15 弓辰 <chen...@gmail.com>:

> --
>
>
>

Wish

unread,
Aug 15, 2012, 2:14:08 PM8/15/12
to rime-...@googlegroups.com
非常抱歉,更正一下之前的说法。我之前说的IPC不受限制仅仅是在Win8开始界面的搜索界面下测试。现在发现这个搜索界面下并不完全属于Metro,而还可算作explorer的一部分,所以是可以IPC的,除了界面显示不出来。
但是我找了一个真正的Metro程序里面就完全不一样了。经过我试验,加载输入法的情况和IE9保护模式非常类似,一旦有任何被禁止的操作出现,会导致输入法完全无法调出。
我又去网上查了一下,Metro程序和Win32程序的IPC在任何情况下都是被完全禁止的(http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/0005b94f-8409-4804-88c5-e2f5fcce460a/)。
只找到一个概念性的东西(http://forum.xda-developers.com/showthread.php?t=1541924)表示Metro程序可以与系统服务通信。也就是说如果我们把Server做成service,还是有可能实现IPC的。

2012/8/15 Wish <wishs...@gmail.com>:

弓辰

unread,
Aug 15, 2012, 8:16:19 PM8/15/12
to rime-...@googlegroups.com
如果backend service可行,那最好了。不然的話:
只有在Metro介面直接加載一份輸入引擎(可以製作一份rime.dll,TSF檢測到是Metro應用就加載進來),當然讀寫方式打開的文件如用戶詞典必須禁用。現在Metro是否推得開還不好說,先刪減一些功能也無所謂呀。

2012/8/16 Wish <wishs...@gmail.com>
--




Reply all
Reply to author
Forward
0 new messages