Bug-org 544277 IME became unusable when switching focus on Gmail RTF Editor
初回投稿日時: 2010-04-22 13:13:00
最終更新日時: 2010-04-22 13:21:18
カテゴリ: Mozilla Core バグ修正
SNS:
Tweet (list)
GmailのリッチテキストエディタにTabでフォーカスを移動するとIMEが無効になったままになるというバグです。
HTMLエディタのフォーカス処理がぐちゃぐちゃだったことが原因でした。非常に多くのバグがコード上では連携していたので一気に修正しています。
まず、Gmailのメール作成画面ではdesignModeを利用していますが、このdesignModeはドキュメントを特殊なモードに変更してしまうというもので、一部の例外を除き、designMode上の要素ノードはフォーカスをセットされません。ドキュメントノード自体がフォーカスを得るのみ、という特殊な仕様になっています。
nsFocusManagerはフォーカス移動時にnsIMEStateManager (ISM)にこれを通知し、ISMが新しいフォーカスに基づいてIMEの状態を設定します。ですが、designModeの特殊な事情によりフォーカス移動時にfocusイベントが発生しないため、ISM的には最後のblurイベント以降、何もフォーカスを持っていない状態が継続されていた、という状況になっていました。
つまり、ISMに常に通知を送るだけで修正できそうですが、この辺のコードは非常に複雑でこれだけを修正すると他でregressionが出ました。この前段階の処理にも問題があったということです。
少し話をHTMLエディタから離れて、フォーカスの仕様について考えてみましょう。nsFocusManagerの内部処理ではひとつ例外的に、本来はフォーカスを得られないものの、内部処理ではフォーカスを得る要素が存在します。それはドキュメントのルート要素です。ルート要素がフォーカスを得られないとTabによって選択するフレームを変更し、キーボードでスクロールする、ということができなくなってしまいます。ただし、本当にフォーカス可能な要素という訳ではないので、focusイベントやblurイベントは生成しません。この条件判定時に、nsFocusManagerはルート要素であるかどうかだけをチェックしていました。
そう、nsFocusManagerはルート要素はフォーカス可能で編集可能であることはない、という前提のもとに実装されてしまっていたのです。そこでfocusイベントを編集不能かdesignModeにより編集可能なルート要素には送らない、という本来の形に変更しました。これにより、ISMは正しく機能し、フォーカス処理にも問題はなくなりました。ですが、類似サイトをいくつか検証しているとまだうまくいかないケースがありました。それは<html><body contenteditable="true"></body></html>というケースです。
親からTabによりフォーカスを移動して来た時に編集不能なルート要素(html要素)が最初にフォーカスを受け取ってしまいます。ですが、ユーザから見たらbody要素にフォーカスが移動しているべきです。もちろんもう一度Tabを押すとbody要素にフォーカスが移動するのですが、スクロールバーが無いときには意味が分かりませんし、もともとtextarea要素と同じでそのような操作ができることをユーザは求めていません。そこで、このケースにおいてはTabによるフォーカス移動ではルート要素を無視するように修正しています。
これでおおむね動作するようになりましたが、Shift+Tabが根本的に動作していなかったことや、body要素の外でクリックした時にも問題があったので、同時に修正しています。
今回の修正でも修正されていない類似のバグはまだ数多く残っていますが、現在のサイクルでできる限り修正してしまいたいと考えています。