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

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

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

2010年3月23日

Re: ブラウザを窓から投げ捨てたくなるバグのその後2
初回投稿日時: 2010年03月23日14時08分09秒
カテゴリ: Mozilla Core
SNS: (list)

結構貢献してくださってるのでありがたいんですが、このバグに関してはいい加減に理屈を理解してもらいたいです。開発陣は変てこりんな理屈を付けて動かなくするんだろうなとか悪意をもって言われるのは、かなり不愉快ですし、これ以上、ずれた批判をされても時間の無駄です。ですので、ここに理屈と、Geckoの設計思想を紹介しておきます。

WindowsのGUIアプリのプログラミングはウインドウプロシージャにイベントに相当するメッセージが送られてくるので、これに対して適切なリアクションをする、という形になります。マウスホイールのメッセージである、WM_MOUSEWHEELWM_MOUSEHWHEELメッセージは通常、フォーカスを持ったウインドウ(SDK用語で言うウインドウ)に対して送信されます。通常、というのは多くのドライバで採用されている方式であるということで、マウスドライバによってはカーソル位置を尊重することもできると思います。

Webブラウザはコンテンツに対してひとつのウインドウを生成し、その中に複数のスクロール可能な領域が生成することがあります。複数のスクロール可能な領域のうち、どれをターゲットとするかについては、各ブラウザともウインドウ内での疑似フォーカス位置を尊重するのではなく、マウスカーソルの位置を尊重してスクロール対象を決定しています(マウスドライバの多くが採用する動作とは対照的ですが、この方がより人気があるようです)。

ですが、コンテンツ内で例外的に別ウインドウを持つことのあるプラグインでは各ブラウザ、動作が異なっています。

Geckoは、コンテンツ内の存在に対しては、CSSによるスクロール可能領域なのか、プラグインなのかを区別していません。WM_MOUSEWHEELWM_MOUSEHWHEELをGeckoが受信すると、カーソル位置の下にあるウインドウを調べます。ここでプラグインのウインドウも含め、自分以外のウインドウで、自分と同じプロセスのウインドウが発見されると、それに対して受け取ったものと同内容のメッセージを送信します。受け取った側は、そのメッセージを自分たちで処理し、消費してしまった方が良い場合は、次のウインドウプロシージャを呼び出さない、という行動をとれます。自分たちに必要ないイベントなのであれば、次のウインドウプロシージャ(通常はその親ウインドウのもの)を呼ぶことになります。

つまり、Fx3.5.x以前と、Fx3.6.2以降でプラグイン上でスクロールできなくなる、というケースはプラグインがメッセージを自分たちで消費してしまったことを意味しています。このケースにおいて、もし強引にスクロールを行ってしまうと、本当にプラグインの中身がスクロールしたり、ホイールの回転にあわせてなんらかのリアクションが行われていた場合にはプラグインの快適な利用を妨害してしまうことになります。

ちなみに、Google Chromeの挙動はすこしテストしてみると明確です。WebKitのウインドウがメッセージを受け取った場合、プラグインのウインドウに対してはメッセージを再送信していません(WebKitのウインドウ間では行っているようです)。ですから、メッセージをプラグインが不必要に消費してしまう心配がありません。ですが、この方法にはもちろん問題点もあります。それは、そのプラグインがWM_MOUSEWHEELWM_MOUSEHWHEELを処理するものだったとしても、シームレスな操作ができないということです。

たとえば、Flash Playerのコンテンツがスクロールバーを持っていたとします。Geckoでは他のコンテンツ、textareaiframeと同様に、そのコンテンツの上にカーソルを移動させるだけでスクロールができます。Google Chromeではプラグインの場合にだけ、そこをクリックしてからホイールを回転させなくてはいけません。

大多数のユーザにとってコンテンツがプラグインであるか、そうではないかは分からない、もしくは関係のないことですので、Geckoはユーザにシームレスな操作体験を提供するように設計しているのです。

ところで、実際問題よく分からない問題がひとつあります。

youtubeのビデオでよく見かけるのですが、メッセージを消費してしまうものと、そうではないものがあります。Flashのコンテンツを生成したオーサリングツールの違いによるものなのか、はたまたFlashアプリケーションの作者が自由にコントロールできるものなのかはよく分かっていません。Flashではわざわざホイールイベントをリスニングしてまでハンドリングしないと消費することもできないと思うのですが、ホイールをもともと使わないFlashアプリがそんなコーディングをしているのも不自然なように思います。

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

関連するかもしれないエントリを発見できませんでしたが、無いとは限りません。