Bug-org 376679 WM_MOUSEWHEEL and WM_MOUSEHWHEEL messages should be delivered to windowless plugins
初回投稿日時: 2015年10月31日11時22分13秒
カテゴリ: Flash Mozilla Core Mozilla44 plugin Windows バグ修正
SNS:
Tweet (list)
Windowsでは、windowlessプラグインに対してWM_MOSUEWHEEL
メッセージや、WM_MOUSEHWHEEL
メッセージが送信されていないため、windowlessプラグイン上でマウスホイールが使えないというバグです。
調べてみると、そもそも、WidgetWheelEvent
にネイティブのメッセージをそのまま挿入していませんでした。しかし、単純にこれを行えば修正できるという話でもありません。なぜならGeckoは高解像度スクロールに完全に対応しているため、WidgetWheelEvent
をWM_MOSUEWHEEL
やWM_MOUSEHWHEEL
を受信した時に必ず送信している訳ではないからです(小数の端数による問題のため)。また、Flash Playerやその他のプラグインも高解像度スクロールに完全に対応しているのか怪しいという点もあります。少なくとも昔、Logitechのエンジニアからの要請でGeckoに高解像度スクロールを実装した際にテストした時には、当時のFlash Playerは非対応でした。
そこで、今回はトリックを使って(この点に関しては)簡単に実装してしまうことにしました。
WidgetWheelEvent
には、DOMMouseScroll
イベントの発火に利用するためのlineOrPageDeltaX
とlineOrPageDeltaY
というメンバがあります。これらは、それぞれの方向へのスクロール量が整数で表現できるようになった時にだけ値がセットされます。例えばWindowsの場合、0.5行ずつのWM_MOUSEWHEEL
メッセージが連続して来た場合、最初のWidgetWheelEvent::lineOrPageDelatY
は1で、二つ目は0、三つ目は再び1、となり、delta値の合計とつじつまが合うようになっています。
これを利用し、この値からWM_MOUSEWHEEL
メッセージやWM_MOUSEHWHEEL
メッセージのwParam
を計算することで常に、整数行のスクロールが発生するデルタ値のメッセージをwindowlessプラグインに対して送信するようにし、互換性問題を低くしています(ひょっとするとWHEEL_DELTA値で送信しないとスクロールが早すぎるという古くて、当時でも間違っていた実装方法のままのプラグインもあるかもしれませんが……)。
ただし、この修正だけだと、マウスホイールでページ全体をスクロール中にwindowlessプラグインがカーソルの下へ移動してくると、全てのマウスホイールイベントをそのwindowlessプラグインに消費されてしまいます。つまり、スクロールが止まってしまうというバグが発生します。これを防ぐために、windowlessプラグインにマウスホイールのメッセージを送信するのはeWheel
イベントのデフォルトアクションという扱いにすることにしました。これにより、マウスホイールトランザクションが活用可能になりますので、直前のスクロールが優先されることになります。
ただし、マウスホイールトランザクションで救えないケース、例えばwindowlessプラグイン上でマウスホイールの操作を開始した場合には、そのwindowlessプラグインが実際にホイールを処理しているか否かに関わらず、そのプラグインに消費されてしまいます。つまり、見た目からページ全体のスクロールを期待しているとバグっているように見えます。しかし、これは別プロセスで動くwindowlessプラグインからホイールの処理が必要だったかどうか、その結果を受けとる仕組みが存在しないので解決不能な問題です。