Jun 19, 2009

Fennecの構造

Fennecのどんなところがマズいわけ?という話の中で、canvasがどうしてそこででてくるのか、Fennecって実際どんな作りになってるんだ、というツッコミを受けた。なので簡単に解説してみる。

しばらくソースを見るとだんだん分かってくるんだけど、要約するとこんな風になってる。

<window>
  <html:canvas id="browser-canvas"/>
  <box id="browsers" hidden="true">
    <browser/>
    <browser/>
    ...
  </box>
</window>

Firefoxのtabbrowser要素に相当する物は主にJavaScriptで実装されている。canvasは現在フォーカスされているタブに対応するbrowser要素の内容を描画するための物で、1つだけしか存在しない。パンスクロールやズームは全てこのcanvasの再描画でまかなわれてる。ユーザの目に見えているのはこのcanvas要素で、実際のページの内容は画面外の非表示のbrowser要素の中に置かれている。

  • ページの読み込みが完了した時→browser要素の内容をdrawWindow()でcanvasに描画する。
  • パンスクロールする時→canvasを制御するコントローラにあたるJavaScriptオブジェクトが保持している座標情報を変更して、canvasに描画する範囲を変更する。
  • ズームする時→canvasに描画する内容のズーム率を変える。
  • ユーザがリンクをクリックした時→canvas上の座標、パンスクロールの位置、ズーム率の3つから、browser要素内の実際のページにおけるクリック位置を算出して、nsIDOMWindowUtilsの機能でマウスイベントを実際のページに送出する。
  • アニメーション等で再描画が発生した時→browser要素の中にあるページ上で、再描画された箇所の座標情報を持ったMozAfterPaintイベントが発行される。それをFennecのイベントハンドラが検知して、パンスクロールの位置とズーム率を元に「再描画された箇所に対応するcanvas上の座標」を計算し、必要最低限の領域だけ再描画を行う。

何故こうなっているかというと、ズームとスクロールのパフォーマンスの問題かららしい。具体的には、Firefox 3以降のフルズームを使った場合、ズーム率を変えるごとにreflow(ボックスの位置等の計算)が発生してしまうなどのせいでパフォーマンスが落ちてしまうため、使い物にならない。そこで、高速な再描画ができるcanvasが使われることになったということのようだ。

だから現状では、FirefoxでcanvasとdrawWindow()を使った時に起こる問題が全部未解決のまま積み上がってる。例えばFlashなどのプラグインによって描画される箇所はスッポリ抜けるし、select要素のように独自の「ウィンドウ」を形成する物は見当違いの場所にポップアップが出る。そういった問題は当然解決されるべきだ(そして実際、Gecko 1.9.2以降で修正することを目指しているらしい)けれども、それって却って遠回りなんじゃないの? というのが、自分の率直な感想。

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能