Now browsing the archives for the 'Tab Flick' category.

タブ切り替えパネル風の半透明ポップアップ

modest に投稿した記事と同内容です。

Tab Flick 拡張機能 のポップアップは、 Firefox 3.6 以降の Ctrl+Tab によるタブ切り替えパネルのような半透明の見た目となっています。

ここでは、そこに至るまでの実装の経緯を記しました。なお、簡単のためコードの一部は実際とは異なるものとなっています。

第1段階

まず、 browser.xul にオーバーレイし、 #mainPopupSet をマージポイントとして新しい xul:panel 要素を追加します。

<popupset id="mainPopupSet">
    <panel id="tabFlickPanel" style="width: 200px; height: 200px;" />
</popupset>

openPopup あるいは openPopupAtScreen メソッドでこの xul:panel 要素を開くと、当然見た目はシンプルなポップアップとなります。

第2段階

次に、 xul:panel 要素に対して KUI-panel クラスを指定します。 KUI-panel クラスは browser.xul にて読み込まれているスタイルシート (browser.css) にて定義されています。したがって、 browser.xul へオーバーレイした XUL 内であれば、特にスタイルを定義することなく利用可能となります。

    <panel id="tabFlickPanel" class="KUI-panel" style="width: 200px; height: 200px;" />

これで Windows XP などでの Ctrl+Tab によるタブ切り替えパネルと同じ、黒い半透明の角丸ポップアップとなります。
KUI-panel クラスのスタイルは Firefox 3.5 に同梱されたスタイルシート (browser.css) でも定義済みですので、 Firefox 3.5 でも有効となります。

第3段階

さらに、 xul:panel 要素へ以下のような内容のスタイルシートを適用します。

#tabFlickPanel:-moz-system-metric(windows-compositor) {
    background: transparent;
    -moz-appearance: -moz-win-glass;
    -moz-border-radius: 0;
    border: none;
}

すると、 Windows Vista または Windows 7 で Windows Aero が有効な場合、Aero Glass 効果のある半透明のポップアップとなります。

第4段階

しかし、ここでひとつ問題が生じます。詳しい理由はわかりませんが、ポップアップの右下角に余計な枠線が表示されてしまいます。
これを解決するには、なぜか xul:panel 要素の collapsed を以下のようにして切り替えてあげる必要があります。

    <panel id="tabFlickPanel" class="KUI-panel" style="width: 200px; height: 200px;"
          collapsed="true"
          onpopupshown="this.collapsed = false;"
          onpopuphiding="this.collapsed = true;" />

これでようやく解決しました。

この方法は裏技的なものですので、拡張機能などでご利用の際はご注意ください。

TOP

ブラウザウィンドウのサムネイルを描画する

modest に投稿した記事と同内容です。

タブカタログ拡張機能のようにWebページのサムネイル画像を表示する拡張機能の多くは、 html:canvas 要素の二次元描画コンテクストの drawWindow メソッドへWebページの window オブジェクトなどを引数で渡してサムネイルの描画を行っています(canvas を使って図形を描く – MDC)。

この drawWindow メソッドの引数にWebページの window オブジェクトではなく、ブラウザウィンドウの ChromeWindow オブジェクトを渡すことで、ブラウザウィンドウのサムネイル画像を描画することも可能です。しかし、以下のようにブラウザタブ内に表示されたWebページまでは描画されず、背景色で塗りつぶされたようになってしまいます。

この問題を解決するには、ブラウザウィンドウのサムネイルの上に、Web ページのサムネイルを重ねて描画する必要があります。この記事では、その方式を紹介します。

XUL

ブラウザウィンドウのサムネイル描画用の html:canvas 要素を生成します。

<html:canvas id="testCanvas" />

JavaScript

最初にサムネイルの拡大/縮小率を定めておきます。ここでは50%に縮小することとします。

const scale = 0.5;

サムネイル描画の対象とするブラウザウィンドウとして、 nsIWindowMediator を使って直近のブラウザウィンドウの ChromeWindow オブジェクトを取得します。

var win = Components.classes["@mozilla.org/appshell/window-mediator;1"].
          getService(Components.interfaces.nsIWindowMediator).
          getMostRecentWindow("navigator:browser");

簡便のため、 html:canvas 要素への参照を取得しておきます。

var canvas = document.getElementById("testCanvas");

ブラウザウィンドウのサイズに合わせ、 html:canvas 要素のサイズを調整します。

var w = win.innerWidth;
var h = win.innerHeight;
canvas.width  = w * scale;
canvas.height = h * scale;

二次元描画コンテクストを取得し、ブラウザウィンドウのサムネイルを描画します。

var ctx = canvas.getContext("2d");
ctx.save();
ctx.scale(scale, scale);
ctx.drawWindow(win, 0, 0, w, h, "rgb(255,255,255)");

引き続き、Webページのサムネイルを描画しますが、その前に原点を左上(座標0, 0)から移動させる必要があります。原点を移動させるためには、二次元描画コンテクストの translate メソッドを使います。移動量は、ブラウザウィンドウに対する現在のブラウザ(xul:browser 要素)の位置から算出します。

var rect = win.gBrowser.mCurrentBrowser.getBoundingClientRect();
ctx.translate(rect.left, rect.top);

最後にWebページのサムネイルを重ねて描画します。なお、 win.contentwin に対応するブラウザウィンドウの現在のタブに表示されたWebページの window オブジェクトを表します。

w = win.content.innerWidth  || win.content.document.documentElement.clientWidth;
h = win.content.innerHeight || win.content.document.documentElement.clientHeight;
ctx.drawWindow(win.content, win.content.scrollX, win.content.scrollY, w, h, "rgb(255,255,255)");
ctx.restore();

以上のコードに適当に肉付けして実行してみると、以下のようにブラウザタブ内のWebページも含めてブラウザウィンドウのサムネイルが描画されます。

注意

今回はブラウザウィンドウ内の現在のブラウザタブのWebページだけが見えている前提となっていますが、分割ブラウザ (Split Browser)を使っている場合、この限りではありません。そのような場合にも対応させるには、さらなる工夫が必要となります。

補足

元々筆者はブラウザウィンドウのサムネイルを描画するために、ブラウザウィンドウ用とWebページ用の2つの html:canvas 要素を xul:stack 要素で重ねる方式を考え付きましたが、Piroさんのアドバイスにより、この記事で紹介したように原点を移動させつつ1個の html:canvas 要素に対して2回 drawWindow メソッドを使用する方式が可能なことがわかりました。

TOP