Re: ブラウザを窓から投げ捨てたくなるバグのその後2
初回投稿日時: 2010年03月23日14時08分09秒
カテゴリ: Mozilla Core
SNS:
Tweet (list)
結構貢献してくださってるのでありがたいんですが、このバグに関してはいい加減に理屈を理解してもらいたいです。開発陣は変てこりんな理屈を付けて動かなくするんだろうな
とか悪意をもって言われるのは、かなり不愉快ですし、これ以上、ずれた批判をされても時間の無駄です。ですので、ここに理屈と、Geckoの設計思想を紹介しておきます。
WindowsのGUIアプリのプログラミングはウインドウプロシージャにイベントに相当するメッセージが送られてくるので、これに対して適切なリアクションをする、という形になります。マウスホイールのメッセージである、WM_MOUSEWHEEL
、WM_MOUSEHWHEEL
メッセージは通常、フォーカスを持ったウインドウ(SDK用語で言うウインドウ)に対して送信されます。通常、というのは多くのドライバで採用されている方式であるということで、マウスドライバによってはカーソル位置を尊重することもできると思います。
Webブラウザはコンテンツに対してひとつのウインドウを生成し、その中に複数のスクロール可能な領域が生成することがあります。複数のスクロール可能な領域のうち、どれをターゲットとするかについては、各ブラウザともウインドウ内での疑似フォーカス位置を尊重するのではなく、マウスカーソルの位置を尊重してスクロール対象を決定しています(マウスドライバの多くが採用する動作とは対照的ですが、この方がより人気があるようです)。
ですが、コンテンツ内で例外的に別ウインドウを持つことのあるプラグインでは各ブラウザ、動作が異なっています。
Geckoは、コンテンツ内の存在に対しては、CSSによるスクロール可能領域なのか、プラグインなのかを区別していません。WM_MOUSEWHEEL
、WM_MOUSEHWHEEL
をGeckoが受信すると、カーソル位置の下にあるウインドウを調べます。ここでプラグインのウインドウも含め、自分以外のウインドウで、自分と同じプロセスのウインドウが発見されると、それに対して受け取ったものと同内容のメッセージを送信します。受け取った側は、そのメッセージを自分たちで処理し、消費してしまった方が良い場合は、次のウインドウプロシージャを呼び出さない、という行動をとれます。自分たちに必要ないイベントなのであれば、次のウインドウプロシージャ(通常はその親ウインドウのもの)を呼ぶことになります。
つまり、Fx3.5.x以前と、Fx3.6.2以降でプラグイン上でスクロールできなくなる、というケースはプラグインがメッセージを自分たちで消費してしまったことを意味しています。このケースにおいて、もし強引にスクロールを行ってしまうと、本当にプラグインの中身がスクロールしたり、ホイールの回転にあわせてなんらかのリアクションが行われていた場合にはプラグインの快適な利用を妨害してしまうことになります。
ちなみに、Google Chromeの挙動はすこしテストしてみると明確です。WebKitのウインドウがメッセージを受け取った場合、プラグインのウインドウに対してはメッセージを再送信していません(WebKitのウインドウ間では行っているようです)。ですから、メッセージをプラグインが不必要に消費してしまう心配がありません。ですが、この方法にはもちろん問題点もあります。それは、そのプラグインがWM_MOUSEWHEEL
とWM_MOUSEHWHEEL
を処理するものだったとしても、シームレスな操作ができないということです。
たとえば、Flash Playerのコンテンツがスクロールバーを持っていたとします。Geckoでは他のコンテンツ、textarea
やiframe
と同様に、そのコンテンツの上にカーソルを移動させるだけでスクロールができます。Google Chromeではプラグインの場合にだけ、そこをクリックしてからホイールを回転させなくてはいけません。
大多数のユーザにとってコンテンツがプラグインであるか、そうではないかは分からない、もしくは関係のないことですので、Geckoはユーザにシームレスな操作体験を提供するように設計しているのです。
ところで、実際問題よく分からない問題がひとつあります。
youtubeのビデオでよく見かけるのですが、メッセージを消費してしまうものと、そうではないものがあります。Flashのコンテンツを生成したオーサリングツールの違いによるものなのか、はたまたFlashアプリケーションの作者が自由にコントロールできるものなのかはよく分かっていません。Flashではわざわざホイールイベントをリスニングしてまでハンドリングしないと消費することもできないと思うのですが、ホイールをもともと使わないFlashアプリがそんなコーディングをしているのも不自然なように思います。