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

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

もずはっく日記(2016年3月)

2016年3月16日

Bug-org 1137572 Add some useful methods to TextEventDispatcher for native key and IME handlers
初回投稿日時: 2016年10月15日20時55分24秒
最終更新日時: 2016年10月15日21時06分23秒
カテゴリ: Events IME KeyboardEvent Mozilla Core Mozilla48 バグ修正
SNS: (list)

widgetのコードが、OSから送信されてくる、キーボードやIMEの入力イベントから、DOMイベントのもとになる、WidgetEventを生成する部分をできる限りプラットフォーム非依存のコードに置き換えようという修正のための準備です。

自動テストでキーボードやIMEの入力をエミュレーションする際に、現在はJavascriptから、nsITextInputProcessorを利用します。nsITextInputProcessormozilla::TextInputProcessorとして実装され、内部ではmozilla::widget::TextEventDispatcherにイベントを生成しています。

順序が逆になりますが、このTextEventDispatcherが実際のユーザの入力イベントからも利用されるようになると、自動テストがより多くのコードをテストできるようになります。しかも、これまで、widgetのコードはネイティブイベントを受け取ると、他のブラウザや、策定中のUI Eventsにあわせたイベントの生成をそれぞれ固有のコードで行っていましたが、これをプラットフォーム非依存にすれば、プラットフォーム間でのGeckoの動作がより確実に均一なものになり、動作を変更する際のコストも大きく下がります。

これを実現するためには、TextEventDispatcherにいくつか、widgetから使いやすい形のメソッドを新たに追加しておく必要がありました。それを実装したのがこのバグ修正です。

まず、TextEventDispatcherは入力のトランザクションという概念を持っています。例えば、あるオブジェクトが未確定文字列を持っている際に、他のオブジェクトが新たに未確定文字列を生成しようとしたりすると、大混乱に陥ります。そのため、イベントを発生させるメソッドを呼び出す前に、トランザクションを確立する必要があります。この際に、トランザクションのタイプを指定できるようにしました。widgetがユーザからの入力イベントを処理する際にはeNativeInputTransactionを用いることで、ユーザの入力が悪意、もしくはバグのあるアドオンによって妨害されることを阻止することができるようになっています。

次に、TextEventDispatcherのインスタンスはnsIWidgetのインスタンスごとに作成されるようになり、nsIWidget::NotifyIME()TextEventDispatcher経由で、TextEventDispatcherListenerクラスの派生クラスで受け取るように変更されました。

TextEventDispatcherListenerのインスタンスは各OSのネイティブIMEのコンテキストの数だけ存在していなければならず、nsIWidget::GetNativeTextEventDispatcherListener()nsIWidgetのインスタンスに関連付いたネイティブIMEコンテキスト用のTextEventDispatcherListenerを取得できるようにしなければいけません。

この設計により、エディタから送信されてくるコンテンツの変更に関する情報や、未確定文字列の確定や破棄のリクエストを現在、トランザクションを確立しているTextEventDispatcherListenerに通知することができるようになっており、また、フォーカスの移動といった、トランザクションが確立していなくても受け取る必要のあるものを複数のTextEventDispatcherListenerインスタンスに配信できるようになっています。

さらに、keypressイベントに"key hell"に対応するために、キーの様々なモディファイアキーの状態での入力文字列を簡単に追加できるように、TextEventDispatchereKeyPressイベントの発火直前にTextEventDispatcherListener::WillDispatchKeyboardEvent()を呼び出します。この際に、WidgetKeyboardEvent::mCharCodeWidgetKeyboardEvent::mAlternativeCharCodesを上書きできるようになっています。これにより、既存のwidgetの"key hell"対応コードを単に、このメソッド内にカット・アンド・ペーストするだけで新設計に移行できます。

他にもいくつかメソッドを追加していますが、それは実際に利用される際にヘッダファイルを参照してください。

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

bug-org 1137572を含むエントリ