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

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

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

2016年4月25日

Bug-org 1257759 [Win] Windowed plugin shouldn't consume reserved shortcut keys of chrome
初回投稿日時: 2016年10月16日11時07分15秒
最終更新日時: 2016年10月16日11時11分26秒
カテゴリ: KeyboardEvent Mozilla Core Mozilla48 plugin Windows バグ修正
SNS: (list)

Windowsではwindowedプラグインにフォーカスがある場合、Firefoxのショートカットキーが動作しないというバグです。

Windowsのwindowedプラグインは、名前の通り、プラグインのためにネイティブウインドウが一つ用意され、このウインドウのメッセージをプラグイン自身がハンドリングしています。このため、プラグインにフォーカスがある場合、MacやWindowsでもwindowlessモードのプラグインがフォーカスを持っている場合のように、widgetからネイティブイベントをプラグインに送信してどうこう、という設計ではないのが大きな問題です。

このバグの修正では、プラグインよりも先に、プラグインが受け取るメッセージを処理しているウインドウプロシージャがCtrlキーかAltキーが押されているキーボードイベントを受け取った場合に、それをそのままプラグインに渡さず、一旦、食ってしまうようにしました(何故、全てのキーイベントをそう扱わないのかと言うと、テキスト入力時のパフォーマンスをこれ以上落としたく無かったからです)。

この時に、プラグインのプロセスから(e10sモードの場合はcontentプロセス経由で) Geckoのメインプロセスにメッセージを伝達します(これにはPostMessage()等を使わず、内部の非同期通信で渡しています)。そして、最終的にnsWindow::OnWindowedPluginKeyEvent()がこれを受け取ります。

nsWindow::OnWindowedPluginKeyEvent()MOZ_WM_KEYDOWNMOZ_WM_KEYUPという偽のメッセージを使って、NativeKeyクラス経由で通常通りにeKeyDowneKeyUpイベントを発火する処理を行います>。ただし、実際に発火されるイベントはeKeyDownOnPluginイベントとeKeyUpOnPluginイベントになります。これは、既存のイベントハンドラが意図せず動作してしまわないようにするためです。また、eKeyPressイベントに相当するものは発火しません。これはパフォーマンス対策です。

nsXBLWindowKeyHandlerは、キーコンビネーションがchromeによる予約済みのショートカットキーだった場合のみ、これを実行し、WidgetEvent::PreventDefault()を呼び出し、イベントを消費します。それ以外の場合は無視して、そのままwidgetにイベントを返します。

nsWindow::OnWindowPluginKeyEvent()にまで処理が戻ってくると、ショートカットキーに消費されたかどうかを呼び出し元に返していきます。非同期プロセス間通信で伝達されて来たところは、同様に非同期で結果を返していきます(nsIKeyEventInPluginCallback::HandledWindowedPluginKeyEvent()を利用します)。

最終的にその結果がプラグインプロセスまで戻って来て、その結果、ショートカットキーに消費されていなかった場合、そのキーメッセージや続くWM_CHARメッセージをプラグインに順次渡していきます。

ここで一つ、知っておいていただきたいのは、一旦、プラグインプロセスからメインプロセスへのキーメッセージの送信が行われると、続いて受信するキーボードイベント関連のメッセージも全て、一旦、メインプロセスへ送信されるようになります。単なる文字入力のメッセージだったとしても、です。そして、メインプロセスへ送信したメッセージの処理結果が全て返ってくると、また、CtrlAltが押されているキーメッセージが来るまで、メッセージの送信は行われなくなります。

これは、入力の順序が狂ってしまわないようにするためです。例えば、間髪入れずにCtrl + Vで貼り付けを行った後に、そのまま文字入力を続けると、文字入力が先に処理されてしまうのを防がなくてはいけません。このため、一度、ショートカットキーを利用すると、一時的に文字入力のパフォーマンスが低下する可能性はあります(各プロセスがビジー状態でなければ、今のPCのスペックなら一瞬で終わるのでこういった心配はありませんが)。

同様にIMEの入力とのイベント順序の問題も考えられます。例えば、ショートカットキーを入力した直後に未確定文字列の入力を開始した場合、ショートカットキーが後から処理されると何が起きるか分かりません。普通は、IMEの未確定文字列がある場合にショートカットキーが実行されることは無いため、プラグインがそのような状況を想定していないと考えるべきでしょう。そこで、未確定文字列入力開始時にまだメインプロセスから結果が返ってきていないキーメッセージがあった場合、これらは無かったものとして破棄するようにして対処しています。

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

bug-org 1257759を含むエントリ