Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 12/248: « 8 9 10 11 12 13 14 15 16 »

ツリー型タブでブックマークにツリー構造を保存できるようにしてみた - Jul 31, 2009

ツリー型タブ 0.8.2009073101/02で、「このツリーをブックマーク」や「すべてタブをブックマーク」した時に、ツリーの構造を含めてブックマークを保存するようにしてみた。だいぶ前から要望を受けてて、「確かにそうするべきだよなあ」とは思ってたんだけど、どうやって実現すればいいかで悩んでた。でもFirefox 2のサポートを切ったことによって、API経由でPlacesデータベースに色んな情報を簡単に保存できるようになったので、思い切って実装してみた。

他のアドオンからもこの機能を使えるように、APIを用意してある。複数のタブからブックマークを作成する場合、以下のように、PlacesUIUtils.showMinimalAddMultiBookmarkUI()でブックマークの追加を行う前後にツリー型タブのAPIを呼んでやると、タブのツリー構造がブックマークに保存される。

var tabs = Array.slice(gBrowser.mTabContainer.childNodes);

var isTSTBookmarksTreeStructureAvailable = (
        'TreeStyleTabBookmarksService' in window &&
        'beginAddBookmarksFromTabs' in TreeStyleTabBookmarksService &&
        'endAddBookmarksFromTabs' in TreeStyleTabBookmarksService
    );
if (isTSTBookmarksTreeStructureAvailable)
    TreeStyleTabBookmarksService.beginAddBookmarksFromTabs(tabs);
try {
    PlacesUIUtils.showMinimalAddMultiBookmarkUI(tabs.map(function(aTab) { return aTab.linkedBrowser.currentURI; }));
}
catch(e) {
}
if (isTSTBookmarksTreeStructureAvailable)
    TreeStyleTabBookmarksService.endAddBookmarksFromTabs();

このAPIはマルチプルタブハンドラでもさっそく使ってる。

やってることはどういう事かというと……

  1. まずTreeStyleTabBookmarksService.beginAddBookmarksFromTabs()の方では、ブックマークされる予定のタブのツリー構造をシリアライズして内部に保持した上で、ブックマークの監視を開始する。
  2. 次に、PlacesUIUtils.showMinimalAddMultiBookmarkUI()で複数のブックマーク項目が新たに作成される。この時、TreeStyleTabBookmarksServiceはブックマークの追加を監視していて、新しく作られたブックマークのIDを内部に保持する。
  3. 最後に、TreeStyleTabBookmarksService.endAddBookmarksFromTabs()の中で、追加されたブックマークと元になったタブとを対応させ、ツリー構造の情報(親のタブにあたるブックマーク項目はどれか、という情報)を、ブックマークのアノテーションとして保存する。この時、タブの数と作られたブックマークの数とが一致しない場合(ブックマークの追加がキャンセルされたとか、未知の機能によってタブと関係ないブックマークが同時に作成されたとか)は想定外のエラーということで、何もせず終了する。

とりあえず一番簡単なやり方で実装してみたので、保存した後のブックマークの順番や親子関係をいじくり回すとちょっと変なことになる。一応、そんなに大きな問題は起こらないで見た目上は何となく自然な形に収まるように、と工夫はしてみたんだけど……どうだろう。

保存された「どのタブが親か?」という情報は、ブックマークのプロパティから編集できるようにしてある。親を付け替えられるようにしてみたけど、横着してるのでちょっと制限が厳しい。そのうち、親を付け替えたらそれに応じてブックマーク項目自体の親フォルダ内での位置も自動的に入れ替えるようにでもしてみようかなー。

巻き戻し/早送りボタンが26日以降クラッシュする件 - Jul 27, 2009

巻き戻し/早送りボタンでSITEINFOを使うようにしてるとクラッシュする件。wedataから取得するデータの先頭の方をスキップするようにしたら落ちなくなったので、どうも正規表現が長すぎ(内部的に、すべてのSITEINFOのURLマッチング用の部分を繋げておいて「マッチするルールがあるか無いか」だけを調べるようにしてるんだけど、その正規表現が長すぎ?)なのが原因っぽい。wedataの更新履歴を見ると、この数日の間にもいくつかルールが追加されてるみたいだし。

で、とりあえず250件ごとに区切って正規表現を作るようにしてみたところ、手元の環境では落ちなくなったみたいなので、修正版として速攻で公開してみた。

しかし念のため全部のURLマッチング用の正規表現を繋げた正規表現を使ってテストしてみたところ、これだけではクラッシュしなかった。処理が走るタイミングにも依るんだろうか? これじゃいつまた問題が再発するか分からんよ……

ともあれ、今までの「でかい正規表現にマッチするかどうか判定」→「全部のSITEINFOをループで調べる」というのに比べると、250個単位で「正規表現にマッチするかどうか判定」→「その250個の範囲のSITEINFOをループで調べる」という風に変わったので、場合によっては多少高速になったんじゃないかなーと期待している。

参考までに、テストに使った巨大な正規表現は以下の通り。

続きを表示する ...

設定を簡単に変更できるようにすること、を必ずしも重視しませんよという話 - Jul 24, 2009

掲示板で書いた事を改めてここにもまとめてみる。

  • ツリー型タブの設定ダイアログを「ツール」メニューなどから簡単に呼び出せるようにして欲しい。
  • 閉じているサブツリー内の子タブがフォーカスされた時に、ツリーを展開するのではなく、現在見えている親のタブにフォーカスする、という風なオプションが欲しい。

この2つの要望にはどちらも応えるつもりはない、というよりも、安直に応えてはいけない種類の要望だと思ってる。

あらかじめ言っておくと、過去の「タブブラウザ拡張」ではこのどちらも応えていた。いや、要望に応えたと言うよりは多分、自分から進んでそうしてしまっていた。でも今の自分の考えでは、そうするべきではなかったと考えている。なので、もうしない。

そもそもを言えば、こういう要望が出てきてしまっているということが「失敗」の何よりの証拠だと僕は考えている。「何故、そういう要望が出るのか?」「どうしてそうして欲しいと思うのか?」そこを考えないといけないと思う。

  • 設定ダイアログを簡単に開けるようにしたいのは何故?
    • →設定を頻繁に変えたいから。
    • →設定を頻繁に変えないと使い物にならないから。
    • →だったら、設定を頻繁に変えなくても十分に使いやすいと感じられるように、自動判別の部分や初期設定をよく考えた方が、ユーザはハッピーになれるんじゃないの?
  • 閉じているサブツリー内の子タブにフォーカスが移った時に、そのタブが含まれているツリーを自動展開するのではなく、閉じられていない親タブに代わりにフォーカスして欲しい、と思うのは何故?
    • →本当は閉じられたツリーの中のタブではなく、親のタブの方にフォーカスして欲しかったから。
    • →というか、そのタブ(閉じられたツリーの中のタブ)がフォーカスされるなんて思いもしてなかったから、そうなってビックリした。
    • →使っていて自然と頭の中に思い浮かべるようになった「こう動くはずだ」という予想が裏切られてしまった。
    • →そのように想像させる挙動を他の部分がしているのなら、その想像に合った挙動をするように統一するべきなんじゃないの? 無駄に選択の余地を増やすんじゃなくて、「自然と思った通りに動いてくれる」状態を目指すべきなんじゃないの?

前者の要望は、色んなアドオンがそういう項目を「ツール」メニューにどんどん加えていったらメニューが一杯になってしまう!ということを見過ごしている。絶対に、多分別の人が「ツールメニューの中の項目は使わないので、非表示にするオプションを加えて欲しい」って言ってくるだろう。そしたらまたそれに応えるの?

後者の要望は、タブの一覧のリストやサムネイル一覧などからそのタブを選んだという風な、「本当にそのタブにフォーカスしたかった場合」にはどうすればいいのか?ということを考慮に入れずに安直に対応すると、泥沼に嵌ってしまう。不用意にそのオプションをいじってしまった人が「フォーカスしたいタブにフォーカスしてくれない!」と(自分がそう設定したからだと言う事にも気づかず)「バグ報告」してくるだろうし、それにまた安直に応えて「じゃあ、そういうケースだけは特別に、閉じられたツリーの中のタブにもフォーカスできるようにしよう」なんて後手後手の対応を続けていたら、どこまでいってもきりがない。

そういう安直な対応を繰り返した果てにあるのが、かつてのタブブラウザ拡張であり、今のTab Mix Plusであると、僕は考えてる。「多機能で凄い、良い物だ」と人は言うけれども、今の僕にはこれらは「考えることを放棄し続けた結果、肥大化の一途を辿った末路だ」という風に見えてる。既にツリー型タブもそうなりつつあると僕は思ってるので、今後は「設定項目を減らしていく」方向にシフトしたいくらいだ。

アプリケーションを作る立場の人は、要望として口に出された言葉の裏にある本当のニーズを読み取る努力をしておかないと、最終的には自分で自分の首を絞めることになると思う。「その方が格好よさそう」とか「その方が賢そう」とかのあまり意味のない自己満足なこだわりだろ、という風に切り捨てないで、自分自身の身を守るための現実的な対策のひとつとして、実践してほしいなと思う。

そしてその結果、それをエンドユーザとして使う立場に僕がなった時に、またハッピーになれるわけだ。

つまり「情けは人のためならず」とか「自業自得」とかそういう話。

現在のタブを閉じた後のフォーカス移動を制御するオプション(A new option to control focus of tabs when the current tab is closed is required.) - Jul 22, 2009

Q

I wonder if you consider integrating Tab Mix Plus into Tree Style Tabs? Not all of Tab Mix Plus but just the opening/closing/focus behavior (under "events" options of Tab Mix Plus)?

There is a lot of interaction between Tree Style Tabs and Tab Mix Plus. Some things don't work correct because Tab Mix Plus is very slow to update. For example, "duplicate tab" used to work in firefox 3.0, but in 3.5 it doesn't work right and Tab Mix Plus had not fixed it (the error is that the duplicate tab gets stuck in middle of tree).

Also Tab Mix Plus doesn't have enough options to give good control over Tree Style Tabs. So maybe it's better if Tree Style Tabs has own options.

Could you copy Tab Mix Plus code for opening/closing/focus, then add some new options for Tree Style Tab? For example:

  • If close first child tab, focus: up/down
  • If close middle child tab, focus: up/down
  • If close last child tab, focus: up/down
  • If close only child tab, focus: up/down
  • If close sub-parent tab, focus: up/first-child/last-child
  • If close expanded root-parent tab, focus: tab-above/parent-tab-above/first-child-down/last-child-down/

Tab Mix Plusをツリー型タブに統合するつもりはないでしょうか? TMPの全機能でなくとも、単にタブを開く・閉じる・フォーカス関係の挙動(TMPの設定の「イベント」パネルにある機能)だけでもいいんですが。

ツリー型タブとTMPの間には互換性がありますが、TMPの更新が非常に遅いため、いくつかの機能は正常に機能しません。例えば、「タブの複製」はFirefox 3.0では動いていましたが、Firefox 3.5では正常に機能せず、TMPはまだその問題を解決できていません(複製されたタブがツリーの真ん中に現れてしまうという問題があります)。

また、TMPはツリー型タブの挙動を制御するのに十分な数の設定項目を備えていません。ツリー型タブ自体がそのような設定項目を備えることが望ましいのではないでしょうか。

タブを開く・閉じる・フォーカス関係のTMPのコードをコピーして、ツリー型タブに新しい設定項目を加えてもらえないでしょうか? 例えば……

  • 最初の子タブを閉じた時:上にフォーカス/下にフォーカス
  • 真ん中の子タブを閉じた時:上にフォーカス/下にフォーカス
  • 最後の子タブを閉じた時:上にフォーカス/下にフォーカス
  • 最後の子タブを閉じた時:上にフォーカス/下にフォーカス
  • 他のタブの子である親タブを閉じた時:上にフォーカス/最初の子にフォーカス/最後の子にフォーカス
  • ツリーが展開されている最上位の親タブを閉じた時:上にフォーカス/親にフォーカス/最初の子にフォーカス/最後の子にフォーカス
A

Thank you for interesting idea. To be honest, I received some similar suggestions about tab focus of Tree Style Tab. However, I couldn't agree them because I hope to keep Tree Style Tab as simple as possible.

There are three reasons why I implemented only minimal options about tab focus.

  1. "Focus last selected" behavior is available with other existing addons.
  2. "Focus to upper (left) tab" hebavior was made obsolete by an old bugfix of Mozilla.
  3. Options dialog will become too complex.

1) Very special behavior, "focus to last selected tab when the current tab is closed" is available with known tiny addon, "Focus Last Selected Tab". So I'm recommending people to use the addon with TST. (BTW, Focus Last Selected Tab 0.9.x doesn't work with TST correctly, so I'll update TST as soon.)

2) For other cases, I don't agree to add "focus to upper (left) tab" option, because it was the default behavior of old Mozilla and it was "fixed" by usability reason. See bug 123563.

3) As you know, too many options for detailed cases will confuse people including me. So I have to make effort to reduce checkboxes, radiobuttons, and so on. Then, TST already have options to customize behavior of re-structuring tree after the current "parent" tab. I'm using the choice "raise the first child up to the new parent", but people can use others. How to unify options for two features, re-structuring and focusing? I cannot imagine to do it in the small dialog...

Anyway, this is only my policy, not the best answer. If people really want options for the feature, I hope that TST is extended by other developers like Tab Mix Plus born from Tab Mix.

興味深い意見をありがとうございます。正直に言うと、この手の提案は他にもたくさん受けています。しかし、私はツリー型タブを可能な限りシンプルに保ちたいので、これらの提案には同意できません。

タブのフォーカスに関して最小限の設定項目だけしか設けていないのには、以下の3つの理由があります。

  1. 「現在のタブを閉じた時、最後に選択されていたタブにフォーカスする」という挙動は、他の既存のアドオンで実現できる。
  2. 「現在のタブを閉じた時、上(左)のタブにフォーカスする」という挙動は、Mozillaの過去のバグ修正によって廃止された物である。
  3. 設定ダイアログが非常に複雑になってしまう。

1) 「現在のタブを閉じた時に、最後に選択されていたタブにフォーカスする」という非常に特殊な挙動は、既存のよく知られたアドオンFocus Last Selected Tabで実現できます。なので私は、それとツリー型タブを使うことをお勧めしています。(ちなみに、Focus Last Selected Tab 0.9.xはツリー型タブと組み合わせると期待通りには動きません。この点についてはなるべく早くツリー型タブを更新するつもりです。)

2) それ以外の挙動について、私は「現在のタブを閉じた時に、上(左)のタブにフォーカスする」という設定項目を設けることには同意しません。なぜなら、その挙動は古いMozillaの既定の挙動であったものの、利便性の観点から「(問題であるという認識の上で)修正された」からです。詳しくはbug 123563を見て下さい。

3) 言うまでもなく、詳細な場合ごとの過剰な数の設定項目は、私を含めてユーザを混乱させます。なので私は、チェックボックスやラジオボタンなどの数を減らす努力をしないといけません。ツリー型タブはすでに、親タブを閉じた後のツリーの再構築についての設定項目を備えています。私は「最初の子を新しい親にする」という選択肢を使っていますが、他の人は別の選択肢を使っているかもしれません。これら2つの機能(親タブを閉じた時のツリーの再構築と、現在のタブを閉じた時のフォーカスの移動)の設定項目をどのように統合すればいいでしょうか? 私には、それを小さなダイアログの中でやってのける様子が想像できません。

ともかく、これはあくまで私のポリシーであって、最良の答えというわけではありません。もしみんなが本当にその機能のための設定項目を必要としているのなら、Tab MixからTab Mix Plusが生まれたように、他の開発者の人がツリー型タブをさらに拡張してくれることに、私は期待します。

英語でどう書けばいいのか分からなかったんでこういう書き方になったけど、ぶっちゃけ、「カスタマイズのためのチェックボックスやドロップダウンリストは多ければ多いほどいい」という発想には反吐が出る。そういうことは隠し設定で十分だろ、と。about:configでやりゃいいだろ、と。何でもかんでもダイアログの中に詰め込むという発想は、僕がかつて取り憑かれそして我が身を滅ぼすに至った忌むべき考え方だ、と僕は認識している。

nsIZipWriterを使ってFirefoxでZIPアーカイブを作る - Jul 16, 2009

nsIZipWriterを使えばアドオンでZIPアーカイブを作れるということを割と最近になってやっと知ったので、アドオンのXPIへのパッケージングまで全部アドオンでできるやん!と思ったんだけど、使い方がよく分からんかったので、実験と練習もかねてコンテキストメニュー拡張の短縮構文で使える汎用的な処理を書いてみた。

要点だけ抜き出すとこんな感じ。

// aSources = nsIFileの配列
// aZipFile = 作るZIPアーカイブのnsIFile
// aCompressionLevel = 圧縮率(0で無圧縮、9で最大圧縮、デフォルトは6)
zipFilesAs : function(aSources, aZipFile, aCompressionLevel) 
{
    // Firefox 3以降じゃないと動かないよ!
    if (!('nsIZipWriter' in Components.interfaces))
        throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

    if (!aSources || !aSources.length || !aZipFile) return;

    if (aZipFile.exists() && !this.isZipFile(aZipFile))
        aZipFile.remove(true);

    const PR_RDWR        = 0x04;
    const PR_CREATE_FILE = 0x08;
    const PR_APPEND      = 0x10;
    const PR_TRUNCATE    = 0x20;

    var writer = Components
                    .classes['@mozilla.org/zipwriter;1']
                    .createInstance(Components.interfaces.nsIZipWriter);

    if (aCompressionLevel === void(0))
        aCompressionLevel = writer.COMPRESSION_DEFAULT;

    // 新規ZIPアーカイブと既存のZIPアーカイブではフラグが違う
    var flags = aZipFile.exists() ?
                    PR_RDWR | PR_APPEND :
                    PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE ;
    writer.open(aZipFile, flags);

    aSources.forEach(function(aFile) {
        var entry = this+aFile.leafName;
        // フォルダに対応するエントリの有無を調べる時は、
        // エントリ名の末尾に「/」が必要
        var entryForCheck = aFile.isDirectory() ? entry+'/' : entry ;

        // すでにあるエントリで、フォルダではない物は削除。
        // (フォルダを削除しないのは、内容をマージするため)
        if (!aFile.isDirectory() && writer.hasEntry(entryForCheck))
            writer.removeEntry(entry, false);

        // 新しいエントリを追加
        if (!writer.hasEntry(entryForCheck))
            writer.addEntryFile(entry, aCompressionLevel, aFile, false);

        if (aFile.isDirectory()) {
            var files = aFile.directoryEntries;
            while (files.hasMoreElements())
            {
                arguments.callee.call(
                    entry+'/',
                    files.getNext().QueryInterface(Components.interfaces.nsILocalFile)
                );
            }
        }
    }, '');

    writer.close();
},

// ファイルの内容を実際にZIPアーカイブとして読んでみて、ZIPアーカイブかどうか調べる
isZipFile : function(aFile)
{
    var isZip = false;

    if (!aFile || !aFile.exists()) return isZip;

    var reader = Components
                    .classes['@mozilla.org/libjar/zip-reader;1']
                    .createInstance(Components.interfaces.nsIZipReader);
    try {
        reader.open(aFile);
        try {
            var entries = reader.findEntries('*');
            while (entries.hasMore())
            {
                entries.getNext();
                isZip = true;
                break;
            }
            if (!isZip) {
                entries = reader.findEntries('*/');
                while (entries.hasMore())
                {
                    entries.getNext();
                    isZip = true;
                    break;
                }
            }
        }
        catch(e) {
        }
        reader.close();
    }
    catch(e) {
    }

    return isZip;
},

タブをグループ化するためのダミーのタブ(How to open a custom dummy tab to put tabs in a group?) - Jul 10, 2009

Q

I noticed that you have added support for dummy tabs to group tabs when opening multiple links from the bookmarks menu. This is very close to a feature that I've wanted since I began using this extension a few months ago: to have general dummy tabs available so that I can create and name a dummy tab from the tab bar context menu.

Is it possible to implement this?

ブックマークメニューから複数のページをタブで開く時に、それらをグループ化するための物として、ダミーのタブがサポートされましたよね。これは、私がこのアドオンを使い始める前に求めていた機能にとても近いです。その機能とは、タブバーのコンテキストメニューから任意にこのようなダミーのタブを開き、自由に名前を付ける事ができるというものです。このような機能を実装してくれませんか?

A

On Tree Style Tab 0.7.2009071001, I made dummy tabs customizable. To change the name of an existing dummy tab, switch to the tab and click the label in the content area (or double-click on any position in the content area). It possibly helps you that you create a bookmark for "about:treestyletab-group?(new group)" and put it in the bookmark toolbar.

ツリー型タブ0.7.2009071001において、ダミーのタブをカスタマイズできるようにしました。既にあるダミーのタブの名前を変えるには、そのタブに切り替えて、内容領域のラベル文字列部分をクリックしてください(または、内容領域のどこか適当な所でダブルクリックしてください)。「about:treestyletab-group?(new group)」というURIのブックマークを作成してブックマークツールバーに置いておくと、あなたの助けになるのではないでしょうか。

ツリー絡みの機能ではないので、「ダミーのタブを開くための機能」は付けない予定。なのでブックマーク等で代用してもらう必要がある。

実装の仕方は、「about:treestyletab-group」というabout: URLを使えるようにするためのコードと、表示する内容の実体と、スタイル定義を見ると分かると思う。XHTMLの名前空間のlink要素を埋め込んでfaviconを変えるとかの姑息なテクニックを使ってます。Firefox 3.5でサポートされた-moz-transformは今回初めて使った。

en-USでは定義されてて他のロケールで定義されてないエンティティ参照の有無を調べるスクリプトを書いてみた - Jul 09, 2009

機能を追加した時にen-USに追加したエンティティを他のロケールに追加し忘れて「○○語の環境で設定画面が動かねえぞゴラァ!!!」という風なバグ報告を貰うことがあまりに多いので(そして自分で気づけないので)、そういうミスを事前に防ぐためのスクリプトを書いてみた。

find_missing_entries_from_locales.js

コンテキストメニュー拡張などの、任意のスクリプトをXPConnect特権付きで実行できるツールでこのスクリプトを実行すると、以下のように動作する。はず。

  1. フォルダ選択のダイアログが開かれる。
  2. localeフォルダ、またはその上位の任意のフォルダを選択する。
  3. その中にある*.dtdなファイルがすべて読み込まれる。
  4. en-USロケールでは定義されていて他のロケールで定義されていない、というエンティティの一覧が表示される。

バイナリをBase64エンコードする - Jul 07, 2009

var file = Cc['@mozilla.org/file/local;1']
            .createInstance(Ci.nsILocalFile);
file.initWithPath('C:\\temp\\target.jpg');

var fileStream = Cc['@mozilla.org/network/file-input-stream;1']
                  .createInstance(Ci.nsIFileInputStream);
fileStream.init(file, 1, 0, false);
var binaryStream = Cc['@mozilla.org/binaryinputstream;1']
                    .createInstance(Ci.nsIBinaryInputStream);
binaryStream.setInputStream(fileStream);
var bytes = binaryStream.readBytes(fileStream.available());
binaryStream.close();
fileStream.close();

var base64 = btoa(bytes);

Bug 364586 - nsXmlRpcCLient.js conversion to base64 is slowで「JavaScriptでBase64エンコードするの遅いから組み込みの関数使えやゴラァ」と提出されていたパッチを見て知った。バイナリファイルの内容をバイト列の配列として読んでゴニョゴニョしなくても、単純に、バイナリのインプットストリームからreadBytes()でバイト列を文字列として取得してbtoa()にかければOK、だそうだ。試してみたら確かにちゃんといけた。

Fennecの構造 - Jun 19, 2009

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以降で修正することを目指しているらしい)けれども、それって却って遠回りなんじゃないの? というのが、自分の率直な感想。

DOM周りの根っこの所に変更が入ったみたい - Jun 10, 2009

The Burning Edge見てたら、こんなバグがFIXEDになっていた。

text/htmlなHTMLドキュメントをXMLとして扱うにあたって、HTML5の仕様に合わせる形になるという事のようだ。namespaceURInullから"http://www.w3.org/1999/xhtml"へ、localNameがすべて大文字からすべて小文字へ、それぞれ変わる、と。

以前の挙動は以前の挙動で古い仕様には合致していたはずなので、時代の移り変わりをしみじみと感じる。

Page 12/248: « 8 9 10 11 12 13 14 15 16 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき