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

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

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

2009年8月27日

Bug-org 511534 Poor interaction with the software keyboard
初回投稿日時: 2009年08月27日14時49分46秒
最終更新日時: 2009年08月27日18時14分26秒
カテゴリ: Mozilla Core バグ修正
SNS: (list)

Dougから昨日、直接GTK2 widget部分のログが送られてきて、なんか変な動作になるんだが心当たりあるのかと聞かれました。

1073790592[40338110]: IM_commit_cb
1073790592[40338110]: OnContainerFocusInEvent [4038a600]
1073790592[40338110]:   SetFocus [40fb2e00]
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e540)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e540)
1073790592[40338110]:   widget now has focus in SetFocus() [40fb2e00]
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e500)
1073790592[40338110]: [40fb2e00] Opening Hildon Keyboard (4357e500)
1073790592[40338110]: Events sent from focus in event [4038a600]
1073790592[40338110]: OnContainerFocusOutEvent [4038a600]
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e500)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e500)
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e540)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e540)
1073790592[40338110]: [40fb2e00] Closing Hildon Keyboard (4357e540)
1073790592[40338110]: Done with container focus out [4038a600]
1073790592[40338110]: OnContainerFocusInEvent [4038a600]
1073790592[40338110]:   SetFocus [40fb2e00]
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e540)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e540)
1073790592[40338110]:   widget now has focus in SetFocus() [40fb2e00]
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e500)
1073790592[40338110]: [40fb2e00] Opening Hildon Keyboard (4357e500)
1073790592[40338110]: Events sent from focus in event [4038a600]
1073790592[40338110]: OnContainerFocusOutEvent [4038a600]
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e500)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e500)
1073790592[40338110]: IMESetFocus 40fb2e00 (4357e540)
1073790592[40338110]: IMELoseFocus 40fb2e00 (4357e540)
1073790592[40338110]: [40fb2e00] Closing Hildon Keyboard (4357e540)
1073790592[40338110]: Done with container focus out [4038a600]
1073790592[40338110]: IM_commit_cb 

時系列は上が古く、下が新しいものです。これを見ると、フォーカスがセットされたり、奪われたりしていることが分かりますが、Doug曰く、Closing Hildon Keyboardは呼ばれるべきではない、とのこと(Hildon KeyboardとあるログはDougがローカルで追加したもので、実際のコードには入っていません)。

コードとログとを照らし合わせてみると、元々の私の設計とは明らかに異なる部分があることが分かりました。それはOpening/Closing Hildon Keyboard直前のIMESetFocus/IMELoseFocusの呼び出し履歴です。

これらはコードを見る限り、明らかにSetIMEEnabledからの呼び出しです(他からの呼び出しならこの直前の行に呼び出しもとのログが残るようになっています)。ですが、Dougのテストはあくまで、ひとつのフィールド上にフォーカスを当ててのものですので、ネイティブなフォーカスイベントが発生していたとしても、Gecko上でのフォーカスの移動は無い(DOMで言うと、activeElementに変化はない)はずです。ですので、SetIMEEnabledが呼び出されること自体がバグです。また、例え呼び出されたとしても、安全策が取り入れられていて、activeElementに対応したIMEの状態を送られているのであればSetIMEEnabledは直ちにその呼び出しを無視して、何も行わないのでバグは抑制されているはずです。

つまり、SetIMEEnabledが間違えたタイミングで、間違えた状態と共に呼び出されていることになります。

ここでさらに、Closing Hildon Keyboard直前の、IMELoseFocusに注目してみると、その間違えた状態というのは、IsIMEEditableState()trueを返す時だと分かります。そう、つまり間違えて送られてきている状態は、nsIWidget::IME_STATUS_DISABLEDであると分かります。

もちろん、実際にはフォーカスが移動していないのですが、nsIWidget::IME_STATUS_DISABLEDが設定される、ということはフォーカスを持った要素が無くなった、という意味ですので、ログから察するに、ウインドウがdeactiveになるときに誤って、これを呼んでいる可能性が高いと言えます。

で、ここ数ヶ月、こんな変化が何で起きたか推測してみると、focus refactoringしか思い当たりません。ここでは、SetIMEEnabledを呼び出す、nsIMEStateManager::OnChangeFocus()の呼び出しコードをnsEventStateManagerからnsFocusManagerに移動し、集中管理するようにしたからです。するとやはり、ウインドウがdeactiveになる時にもnsIMEStateManager::OnChangeFocus()が呼び出されていることが分かったので、リンク先のバグでのレビュー結果となっています。

ちなみにこのバグ、Fennecで発見されましたが、Window ManagerによってはLinuxでも発生しているはずです。片貝さんが以前、これの実装をするときのレビューで教えてくれたのですが、一部のWindow ManagerはIMEの候補ウインドウ等にフォーカスを移してしまって、Fx自体がdeactiveになってしまう可能性があるそうです。もしそうなった場合、trunkでは強制的に確定されるようになってしまっていました。そう、かなり重大なバグであったにも関わらず、ここまでバグ報告が無かったのは、そういったマイナーな環境をテストできるほど、テスタの確保(確認する目を増やす、というもともとの理念)が、IMEに関してはまだまだできていないと言えるでしょう。

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

bug-org 511534を含むエントリ