この日記はMozillaのプロダクトへの貢献者としての私の成果を中心に、気になったバグやWeb界隈の話題について書いていますが、 断り書きがある場合を除き、いかなる団体のオフィシャルな見解ではありません。あくまでも個人的なものです。 Mozilla Foundation、Mozilla Corporation、及び関連企業の公式情報ではないことに注意してください。

現在、XHTML 1.0 (もどき)から、HTML5なコンテンツに修正中です。古い日記は修正が完了していませんので表示が崩れます。 順次、修正していく予定ですのでしばらくお待ちください。

もずはっく日記(2007年4月)

2007年4月17日

IME制御のコードを読みたい方へ
初回投稿日時: 2007年04月17日05時27分20秒
カテゴリ: Mozilla Core
SNS: (list)

IMEの制御に関する簡単な概念を書いておきます。読む前に目を通しておいてもらえれればコード自体は非常にシンプルでプログラム書いたことのある人なら誰でも読めるようなものです。

IMEを制御する上で、具体的にXPレベルで状態を管理しているのはnsIMEStateManager(以下、ISM)です。これはstaticなメンバのみを持つクラスです。(つまり、現在のGeckoは複数のIMEのトランザクションを同時に保持することは原理的にできません。複数のインスタンスを持つことができるようにしたいと考える人も居るかもしれませんが、かなり困難な仕事になると私は思います。また、その労力に見合った改善は得られないでしょう。)

ISMはメソッド名を見れば分かるように、特定のタイミングで呼び出してもらうだけで、自動で適切な処理を行うように設計しています。しかも、これらのメソッドは大半がnsEventStateManager(以下、ESM)から呼び出されるので、ESM内に本来は包含できるものです。しかし、私はあえて現在の形を提案しました、そこには二つの理由があります。

まず、IMEのコードを他の言語圏の開発者に壊されないように、完全に分離したかったのです。Trunkでは幾度となくIMEユーザにはクリティカルなregressionが発生しています。これはテスト環境を持たない、また、テストできない開発者の修正によるもので当然のことです。(誰が悪いと言うわけではなく、仕方がないことです。)

二つ目は、ESMの構造を変化させなくてはいけないバグの修正があったとしても、ESMからは同じタイミングで呼び出してもらうだけでregressionを回避することが可能です。そのために、コマンドのようなメソッド名ではなく、イベントの名前をメソッド名に使っています。

こういった理由から、本来は分離しなくても良い小さく風変わりなクラスが存在しています。しかし、この小さなクラスがIMEの状態を常に、確実にコントロールします。つまり、このクラスを見るだけでGeckoのIME管理が一望できるというシロモノです。

ISMはフォーカスの移動のタイミングにのみ動作します(フォーカスが本当に移動したのかどうかという判断がちょっとややこしいのですが、この辺はGeckoのコードを理解しないといけないので説明は省きます)。フォーカスが移動したタイミングで、新しくフォーカスを受けたcontentでの、あるべきIMEの状態を考えます。

まず、プリントプレビュー時や、実際に走るかどうかは不明ですが、印刷時には無条件に無効とします。

次に、現在のdocumentが編集可能かどうかを調べます。編集可能な場合(HTMLエディタ)は有効にします。

しかし、それ以上は判断できないので、フォーカスを受けたcontentに問い合わせます。問い合わせはnsIContentGetDesiredIMEStateを使います。このメソッドは基本的にはIMEは無効であるべきだと返しますが、もしそのcontentがエディタを持つ場合、エディタに問い合わせが行きます。エディタはエディタの種類(通常、もしくはパスワード)から適切な状態を返します。

これで新しいIMEの状態を取得することができましたので、今度はnsIKBStateControlを使って現在のIMEの状態を取得します。そして、状態に差異がある場合にのみnsIKBStateControlを用いてIMEの状態の変更を要求します。

nsIKBStateControlはnsIWidgetと共に実装されています。これらの実装部分は各プラットフォーム依存の部分で、プラットフォームのAPIを利用してISMの要求を実行します。

nsIKBStateControlの各実装は今の形に落ち着くまでに紆余曲折ありましたが、できあがったコードはシンプルで、そのプラットフォームのことを知っている人なら簡単に読めるものになっています。各プラットフォームでコードを書く際に参考にするなら、この実装部分のみを読めば良いと言えます。

この様に、やっていることは非常にシンプルです。でもシンプルなことが簡単とは限らないということが分かりますね。

関連するかもしれないエントリ

関連するかもしれないエントリを発見できませんでしたが、無いとは限りません。