Bug-org 826657 [TSF] Implement ITfMouseTrackerACP
初回投稿日時: 2014年08月30日17時09分58秒
カテゴリ: Mozilla Core Mozilla34 TSF Windows バグ修正
SNS:
Tweet (list)
TSFでは、TIPは、マウスのイベントを受け取りたい場合、ITextStore
に、マウスイベントのリスナを登録する必要があります。このバグはそれに、対応しようというバグです。
まず、イベントリスナのインターフェースである、ITfMouseSink
を受け入れるための、ITfMouseTrackerACP
インターフェースを単純に、nsTextStore
に実装しました。
ただし、実際の登録・削除処理は若干、面倒なことに、任意の個数のITfMouseSink
を同時にインストール可能です。これは、MSDNでは名言されていませんが、ITfMouseTrackerACP::AdviseSink()
で登録時にDWORD
値のCookieを返し、ITfMouseTrackerACP::UnadviseSink()
を呼び出す時には、そのCookie値のみで削除するITfMouseSink
を指定しようとしている形になっていることから、DWORDで表現できる個数程度は登録可能である必要があるということが伺えます。現に、他のオープンソースソフトウェアのソースコードを調査しましたが、やはり、複数のITfMouseSink
を同時にインストールできるようになっていました。
nsTextStore::MouseTacker
クラスを新設し、これをnsTArray
で配列として管理し、各インスタンスには、Cookie値、ITfMouseSink
の実装へのポインタ、マウスイベントを受け取りたい、文字列の範囲を保存しています。現在、Cookie値は配列のインデックスと同値ですが、将来的に、フットプリントが問題になるようなら、配列から削除しても処理が破綻しないように、二重管理する形にしています。
次に、マウスのボタンが押されたときと離された時に、その座標に文字があるかどうか調査し、無ければ無視、あれば、その文字のどの位置でイベントが発生したのかをITfMouseSink::OnMouseEvent()
に通知しなくてはいけません。
これまでの実装(IMM等)では、widgetから、NS_QUERY_CONTENT_CHARACTER_AT_POINT
イベントを送信し、カーソル位置の情報を取得していましたが、このままでは、現在開発が進んでいる、e10s(Firefoxのマルチプロセス化)には対応できません。なぜなら、ネイティブイベントは、chromeを管理する、親プロセスが受け取りますが、contentは子プロセスにあります。子プロセスの情報を取得するには、同期通信で情報を取得する必要がありますが、子プロセスが処理落ちやハングアップしている時に、chromeプロセスが巻き添えを食わないように、これは禁止されています。
そこで、全く逆のアプローチをとることにしました。content側には現在、フォーカスを持ったエディタの状態を監視し、nsIWidget::NotifyIME()
で様々なことを通知している、IMEContentObserver
が居ます。エディタ上の文字でマウスのボタンが押されたとき、もしくは、話された時に、ここから、新しい通知を同期通信で出せば、widget側でIMEにマウスイベントを通知できますし、IMEContentObserver
は、そのイベントがIMEによって消費されたかどうかを確認することもできます。
どのような通知が行われているのかは、nsIWidget::IMENotification::mMouseButtonEventData
を参照してください。
このアプローチにより、各プラットフォームのIMEイベントハンドラごとに、似たような処理を書かなくて済むようになった上に、e10sにも対応可能なので、かなり、成功した修正になったと思っています。