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

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

もずはっく日記(2010年8月)

2010年8月9日

Bug-org 569023 IME composition is committed unexpectedly when the focused window is hanging up on Vista and later
初回投稿日時: 2010年08月09日14時38分22秒
最終更新日時: 2010年08月10日11時40分11秒
カテゴリ: Mozilla Core バグ修正
SNS: (list)

Windows Vista以降ではウインドウになんらかの入力を行おうとした時に、そのプロセスがビジー状態だと、ウインドウ全体を白っぽく描画するようになっています。この時に、内部ではWM_IME_SETCONTEXTが送信され、一度IMEのコンテキストをdeactiveにしようとします(プロセスがビジー状態なのだから、この意義はよく分かりませんが)。Geckoはこのメッセージをフォーカスの移動だという前提で無条件に強制確定を行ってたため、なんらかの処理でFxがビジー状態に陥ると入力中の文字が確定され、辞書にも悪影響を及ぼしているかもしれない、という状況でした。

この修正では、まず、Geckoには直接関係のない、トップレベルウインドウへのWM_IME_SETCONTEXTは無視するようにしました。Deactiveなウインドウ内の子ウインドウがフォーカスを取得すると、最初にウインドウをアクティブにするためにトップレベルウインドウにフォーカスを与える処理が行われ、WM_IME_CONTEXTが送信されてしまいます。当然、このメッセージを処理する必要性はありません。

次に、wParamが非ゼロで、変換中のウインドウが他にあれば、これを強制確定するようにしました。GeckoはすべてのウインドウでひとつのIMEコンテキストを共有しているため、未確定文字列が他のウインドウで処理されるのを防ぐ必要があるためです(様々な理由から未確定文字列の持ち越しは行っていません)。つまり、wParamがゼロの場合には強制確定を行わなくなりました。

これにより、IMEの変換途中にFxのすべてのウインドウがdeactiveになっても強制的に確定されることはなくなりました。例えば、未確定文字列を適当に入力し、別のアプリケーションに切り替えて、再度、編集中のFxのウインドウをアクティブにすると、変換作業を継続できるようになりました(ただし、タイトルバー等の非クライアント領域以外をクリックしてアクティブにすると強制確定されてしまうので注意してください)。

さて、話はここで終わるはずだったのですが、パッチのテスト中によりややこしい話を見つけてしまいました。windowlessプラグインはフォーカスを失う際に強制確定を行ってくれません。これはWindowsアプリとしては正しいというか、より好ましい動作ではあるのですが、Geckoのローカルルールとの相性がすこぶる悪いのです。

対策として、windowlessプラグインのメッセージの中継処理のうち、IMEやキー入力に関連するものを丸ごとnsWindowからnsIMM32Handlerに移動し、windowlessプラグイン上でIMEの編集処理が完結しないままフォーカスの移動が発生した場合には強制確定を行うようにしました。

ところが、これだけでは新たにフォーカスを取得したウインドウ上に文字が入力されるというバグが発生してしまいました。Flash PlayerではWM_IME_COMPOSITIONWM_IME_CHARをきちんと処理していないようで、強制確定により、WM_CHARが生成されてしまい、これが新しいフォーカスウインドウで受信されていたのです。

これに対抗するために、WM_IME_CHARをプラグインに渡した後、処理されていない場合にはメッセージの内容を保存し、その後にWM_CHARを受信した時に同内容のものなら無視するようにしています。ただし、安全策として、もし内容の異なるWM_CHARを受信するとそれ以降のWM_CHARは無視しなくなるので、入力ができなくなる、といった問題は発生しないはずです。

今回の修正で、windowlessプラグインのIMEの状態もある程度はnsIMM32Handlerで監視するようになりました。このため、変換中かどうかの状態管理の変数が二重化されています。変換中かどうかの判定のためにstaticメソッドを用意しているので、変数を直接見ることとの意味の違いを知っておかないとバグを作り込んでしまうことになるので注意が必要です。

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

bug-org 569023を含むエントリ