Bug-org 610821 IME composition doesn't start by typing a character for searching a tab on Panorama
初回投稿日時: 2011年01月24日15時26分56秒
最終更新日時: 2011年01月24日15時44分34秒
カテゴリ: Firefox Mozilla Core バグ修正
SNS:
Tweet (list)
Panoramaで文字を入力すると自動的にタブの検索フォームが出現し、エディタに一文字が入力されますが、IMEがオンの状態でもフォーカスがエディタ外だったためにIMEが無効になっている時のキーイベントがそのままリダイレクトされるので、次の文字の入力から初めてIMEを経由することになり、意図通りに入力できない、というバグです。昔からFAYTが抱えているのと同じ問題です。
FAYTの時にも悩みましたが、Windowsの入力イベントの仕様上(Geckoの実装上?)、どうしようもないと思い、今回もUIのデザイン自体の見直しを提案していました。しかし、昨年知ったSendInput()
APIが利用可能かもしれないと気づき、実験してみたところうまく動くことが分かりました。
WindowsではメッセージループにWM_KEYDOWN
メッセージのみが送信されてきます。これをTranslateMessage()
APIに渡すと、WM_CHAR
がメッセージキューに挿入されますが、このときにIME (IMM)にも処理が渡っているようです。Geckoでは、GetMessage()
の後、直接TranslateMessage()
を呼んでいて、WM_KEYDOWN
をウインドウが受け取る時には既にIMEで処理が始まっていることになります。つまり、現在の設計ではDOMのkeydown
イベントが発生した時点で、Windowsでは既にIMEが処理を開始している、もしくは、エディタ以外のIMEが無効になっている状態ではIMEを通さずにWM_CHAR
が生成されているという状態になっています。
TranslateMessage()
をDOMのkeydown
イベントの処理結果を見てから呼べという根本的な意見もあるかとは思いますが、開発サイクルのタイミング上、不可能ですし、色々なキーボードレイアウトでテストするにも時間がかかります。そこで、前述のSendInput()
APIによってハックすることにしました。
WM_KEYDOWN
の処理時に、DOMのkeydown
イベントのハンドラがエディタにフォーカスを移動させてIMEが有効になった場合、WM_KEYDOWN
のハンドラがSendInput()
で再度、ネイティブの入力イベントを低レベルで発生させるようにしました。そして、WM_KEYDOWN
のハンドラは次に来たキー入力が期待通りのものだった場合、DOMのkeydown
イベントは再生成しません。そして、エディタ上でkeypress
イベントか、compositionstart
イベントが発生するようになっています。
そして、Panorama側ではkeydown
イベントで検索を開始し、フォーカスを移動させるだけにしました。つまり、今までのkeypress
イベントのリダイレクト処理は行わなくなっています。
この変更が具体的にWebアプリからみて、どのような影響があるのかはイベントの発生順序が見えるデモで確認してみてください。
当然のことながらIMEがオフの状態では以前と変わっていません。IMEがオンの場合、エディタ以外でキーを押すと、エディタには今までは来ていたkeypress
イベントが来なくなっているのが分かるかと思います。その代わりにcompositionstart
イベントやtext
イベントが発生するようになっています。
ちなみに、Macではもともとこの修正後の動作でした。今回の修正ではWindowsとLinuxの動作をMacにあわせた形になります。もし、この変更でなんらかの悪い影響を受けるWebアプリケーションがあったとすれば、それはMacユーザには元々そのユーザ体験を提供してしまっていたことになります。
また、プラットフォーム関わらず、keydown
イベントのpreventDefault()
を呼び出してもIMEの動作を妨げることはできません。DOMのイベントモデル的には良くありませんが、そもそもこれが好ましいことかどうかは分かりません。そのようなロジックに依存したWebアプリを書くと、IMにまっさきにネイティブのKeyPress
イベントを食われてしまうLinux (GTK2)上では動かなくなってしまうからです。