Home > Latest topics

Latest topics 近況報告

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

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

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

Page 8/248: « 4 5 6 7 8 9 10 11 12 »

初期化処理を書く時に注意がいるようになったみたい - Jul 03, 2010

ツリー型タブが入ってるとMinefield 4.0b2preがぶっ壊れる現象に遭遇した。

何が原因なのかちょっとずつ絞り込んでいったところ、DOMContentLoadedイベントが発火するよりも前の時点で<tabbrowser id="content"/>に触っていたのが原因ぽいという事が分かった。ツリー型タブの初期化処理の中でtabbrowser要素の属性値を取ろうとしてdocument.getElementById('content').getAttribute('...')としただけで、XBLのconstructorとかそのへんがぶっ壊れて、tabbrowser要素の初期化処理が全く行われない状態になってしまってたようだ。

ツリー型タブのインストール後にツールバーのカスタマイズ内容が失われるという話も、これが原因だったんだろうか? 状況としてはよく似てるんだけど。

この問題の発生を避けるには、初期化処理を必ずDOMContentLoadedイベントかloadイベントのタイミング以降で行うようにするのが多分一番簡単だと思う。

window.addEventListener('load', function() {
  window.removeEventListener('load', arguments.callee, false);
  // 何か初期化処理
}, false);

他にも、複数バージョンに対応したアドオンでバージョン判別のために'MozBorderImage' in element.styleとかやってる場合も危険かもしれない。とにかく、DOM要素(の属性値であるとかDOMオブジェクトのプロパティであるとか)を参照せずにメタ的な情報(XPCOMで取得できるGeckoのバージョン情報とかnsIPrefBranchで取得できる設定値とか)で判断できる場合はなるべくそっちを使った方が安全っぽい。例えばFirefox 3.5以降かどうかを調べるならこんな感じ。

var comperator = Cc['@mozilla.org/xpcom/version-comparator;1']
                   .getService(Ci.nsIVersionComparator);
var XULAppInfo = Cc['@mozilla.org/xre/app-info;1']
                   .getService(Ci.nsIXULAppInfo);
if (comparator.compare(XULAppInfo.version, '3.5') >= 0) {
  // Firefox 3.5.0およびそれ以降
}
else {
  // Firefox 3.0およびそれ以前
}

pinTab()、unpinTab()への対応 - Jun 27, 2010

このへんのパッチが投入されて、gBrowser.pinTab()gBrowser.unpinTab()というメソッドが実装された。 (実際に使った所のスクリーンショット) pinTab()にタブを渡すとそのタブが他のタブの左側に寄せられて、unpinTab()に(pinnedな)タブを渡すと元に戻る。ぶっちゃけアレですね、Chromeの似たような機能のパクリですね。

この時、タブはスクロールボタン(左向き三角のボタン)よりもさらに左に表示されるようになるんだけど、これは一体どうやって実現されてるのか。実は、CSSで非常にトリッキーなことをしている。pinTab()に渡されたタブはpinnedという属性の値にvalueが設定されるんだけど、この時、.tabbrowser-tab[pinned="true"]なタブはposition:fixedに設定されて、通常の描画フローから切り離される。その上で、スクロールボックスの左にすべてのpinnedなタブの幅の合計と同じだけのマージンを設けて、pinnedなタブ1つ1つにはネガティブマージンを設定してそれらしい位置に表示する……という感じ。moveTab()の中とかでタブの状態を見て処理を分けていて、pinnedなタブはpinnedじゃないタブの中には移動できないし、その逆も然り。原稿のコードに対する最小限の変更でそれらしい挙動を実現するようにしている。よう思いつくな、こんなの。

大抵の既存のアドオンは影響を受けないはずなんだけど、タブ周りで凝ったことをしてる奴は、下手したら全滅しそうな気がする。というかツリー型タブなんかはお話にならないのが目に見えてる。なのでちょっと頑張ってみた。

  • pinnedなタブのレイアウトの処理。改行とか。
  • pinnedになった時、自動的にツリーから解放するとか。

結果。 (スクリーンショット) 最初は単に、pinnedなタブのレイアウト処理の所のX軸とY軸を入れ換えるだけにしてみたんだけど、それだと縦置きタブバーの場合は無駄な領域がメチャメチャ増えるだけだという事が分かったから、「タブが小さくなる」という所を優先して、24×24固定サイズでアイコンを並べられるだけ並べる(1行に収まらなければ改行する)という風にした。見た目は……あんまり良くないね。すんません。

縦置きしたタブバーとpinnedなタブの相性はすこぶる悪い。結局全部ツリー型タブの方で作り直すのに近い状態になってしまった気がする。でもまあ挙動としてはそれなりに違和感のない状態に落ち着いた。

これからまた実装に仕様変更が入らないことを祈るばかりだ。実装の仕方自体が変わってしまうなら、今回のこの作業はまるっきり無駄になってしまうから。

「xpcnativewrappers=no」の廃止 - Jun 09, 2010

レガシーな仕組みが1つ廃止されたようだ。

XPCNativeWrapperについては過去に行った拡張機能のセキュリティに関するプレゼンの中でも紹介した。現在も既に、chrome権限があるコードからWebページの内容に触る時は基本的には必ずXPCNativeWrapperを介してアクセスしないといけないようになってるんだけど、そういう仕組みがまだ入ってなかった頃の書き方でも拡張機能を書けるように、敢えてこの仕組みをOFFにするための機能があった。それがchrome.manifestでのxpcnativewrappers=no指定。今回上記のbugで投入されたパッチによって、この指定がそもそも機能しないようになった。

XPCNativeWrapper越しでなく生のJavaScriptのオブジェクトにアクセスする方法としては、xpcnativewrappers=no以外にもう1つ、任意のオブジェクトの.wrappedJSObjectというプロパティを見る方法がある。今回投入されたパッチではこの機能までは削除されていないように見えるので、今までxpcnativewrappers=noを使っていた人は、Webページ内のJavaScriptのオブジェクトにアクセスしてた箇所では.wrappedJSObjectを書き加えるようにすれば一応は動くようになるんじゃないかと思う。セキュリティ的には、そもそもラップされてない生のJSObjectに触らなきゃいけないという設計自体を変えた方がいいんだけど。だいたい、XPCNativeWrapperが入ったのってFirefox 1.5がリリースされるよりも前の話だよ。今なおXPCNativeWrapperの存在を前提にしてないコードって、どんだけ古いのさ?

タブのコンテキストメニューが正常に機能しなくなった? (The context menu on tabs doesn't appear anymore?) - May 15, 2010

Q

I'm running your Tree Style Tab extension on the last Firefox, 3.4a. I installed the Menu Editor extension and the context menu on the tabs stopped to appear. Until Firefox 3.6.3 they were working together nicely.

私はツリー型タブを最新版のFirefox(3.7a4)で使っています。Menu Editorをインストールしていると、タブのコンテキストメニューが出なくなってしまいました。Firefox 3.6では両者は正常に機能していたのですが……

A

Codes of the context menu on tabs are totally restructured on the Firefox 3.7a4. See: Bug 554991 - allow tab context menu to be modified by normal XUL overlays. So, addons including codes about context menu on tabs must be updated.

TST newer than 0.10.2010040201 has been updated for the change, but I couldn't find out a version updated for Firefox 3.7a4 from all versions of the Menu Editor.

If the problem still appear with a new version of the Menu Editor updated for Minefield 3.7a4 and later, please tell me again.

タブのコンテキストメニューの実装は、Firefox 3.7a4で大きく変わりました。Bug 554991 - allow tab context menu to be modified by normal XUL overlays を参照してください。このため、タブのコンテキストメニューを触るアドオンは更新されなくてはなりません。

ツリー型タブのバージョン0.10.2010040201以降はこの変更に対応済みですが、私はMenu Editorの公開済みのバージョン一覧からMinefield 3.7a4に対応したバージョンを見つけることはできませんでした。.

もしMenu EditorのFirefox 3.7a4対応版がリリースされた後でもまだ問題が再現するようであれば、改めてご連絡ください。

一言でいえば、「Firefox 3.7a4の新仕様にきちんと対応してないアドオンと組み合わせて何が起こっても僕の責任じゃないですよ」ってことで。

「タブを閉じる」ボタンの働きの選択肢として「親のタブを閉じずに子孫のタブだけを閉じる」が欲しい(A new option to close only child tabs by "Close Tab" button) - May 14, 2010

Q

My small suggestion is to be able to configure the close button for a parent tab to just close its children. After it is child-less, the second click would close the tab itself. My feeling is that this would make for more fluid experience when you open up a flurry of child tabs to follow up on details and want to continue with the main "story" or "task" on the original parent tab. As it is now you have to right click and select close children, which I find a bit clunky.

私の希望は、親のタブの「タブを閉じる」ボタンをクリックした時の挙動として、子孫のタブだけを閉じるというオプションが欲しいというものです。そのタブに子供がいなくなった後、2度目のクリックはそのタブ自身を閉じるでしょう。これがどういうときに役立つかというと、何か作業をしている時に、詳細な情報を見るために子タブをいくつか開いた後で、それらを一気に閉じて元の作業に戻るという風な場合です。現状でこのような使い方をするには、タブを右クリックして「このタブの子タブをすべて閉じる」を選択しなくてはならないので、面倒です。

A

Sorry, I have no plan to implement the feature to Tree Style Tab. There are two reasons: 1) overriding of the behavior of "close tab" button is hard to implement. And, 2) I think it is not an instinctive behavior.

1) Now there are some options for "close tab" of parent tabs, but all options are designed to work just after the parent tab was correctly closed. Because, TST listens "TabClose" event which is fired after the tab is completely closed by Firefox itself. We cannot cancel the closing of the parent tab from "TabClose" event.

2) If "close tab" button closes the tab and its collapsed children, I think it is instinctive, because it is same to the default behavior of the "close tab" button, except there are collapsed (hidden) children. And if the button closes only the parent tab (keeping children open) it is also same to the Firefox default. "When the close button is clicked, only children are closed and the tab itself is still there" -- the scenario is odd a little for me.

However, you can implement the feature with other scriptable addons (FireGestures, userChrome.js, etc.) with following codes:

var parentTab = gBrowser.selectedTab;
if (TreeStyleTab.hasChildTabs(parentTab)
  // The second argument "true" means "close only children".
  TreeStyleTabService.removeTabSubtree(parentTab, true);
else
  gBrowser.removeTab(parentTab);

すみませんが、その機能をツリー型タブ本体に取り込むつもりはありません。それには2つの理由があります。1) 「タブを閉じる」ボタンの挙動を乗っ取るのは実装が大変ですし、2) その挙動は直感的とは私には思えません。

1) 現在、親のタブの「タブを閉じる」ボタンをクリックした場合の挙動にはいくつかの選択肢を設けてありますが、そのいずれも、親のタブ自体が閉じられた後に働くことを前提にしています。これはツリー型タブが、タブが完全に閉じられた後でFirefox自身によって発行される「TabClose」イベントを監視することによってこの機能を実現しているためです。「TabClose」イベントからは、タブを閉じる操作自体をキャンセルする事はできません。

2) 「タブを閉じる」ボタンによってそのタブ自身とすべての折り畳まれた子タブが閉じられる場合、そこに折り畳まれた(見えない)子タブがあるという点を除けばFirefoxの標準的な挙動と同じなので、これは私には直感的な挙動に感じられます。また、もしそのタブだけが閉じられて子タブが残るのであれば、これはFirefoxの標準的な挙動と全く同じです。しかしながら、「タブを閉じるボタンをクリックしたら、子タブだけが閉じられて、そのタブは已然として開かれたままとなる」――この挙動は、私には違和感があります。

とはいえ、あなたはこの機能を、スクリプトでカスタマイズする機能を持った他のアドオン(FireGestures、userChrome.jsなど)と組み合わせる事で実現できます。上記のコードを参照して下さい。

ロケーションバーからAlt-Enterでタブを開けない?(ALT-Enter in the location bar doesn't open new tab?) - May 14, 2010

Q

In plain Firefox, ALT-Enter in the address bar opens a new tab. This doesn't happen with Tree Style Tab activated.

素のFirefoxでは、ロケーションバーでAlt-Enterと入力すると新しいタブが開かれます。ツリー型タブが有効な状態だと、この機能が働きません。

A

I think it is a designed behavior of TST. TST includes a feature to open new tabs from the location bar without the ALT key, and the effect of the ALT key is inverted by the feature (Enter => new tab, ALT-Enter => current tab).

To get back Firefox's default behavior (Enter => current tab, ALT-Enter => new tab), go to TST's configuration dialog => "New Tabs" => "Location Bar".

If you don't want any loading into the current tab from the location bar (Enter => new tab, ALT-Enter => new tab), then, go to about:config and turn "extensions.treestyletab.urlbar.invertDefaultBehavior" to "false".

この挙動はツリー型タブの仕様であると思われます。ツリー型タブはロケーションバーでAltキーを押さずに新しいタブを開くための機能を含んでおり、この影響によって、Altキーの働きは反転される事になります。(Enter→新しいタブ、Alt-Enter→現在のタブ)

Firefoxの既定の挙動(Enter→現在のタブ、Alt-Enter→新しいタブ)に戻すには、ツリー型タブの設定ダイアログで「新しいタブ」→「ロケーションバー」を参照して下さい。

もし常に新しいタブを開くようにしたい(Enter→新しいタブ、Alt-Enter→新しいタブ)場合は、about:configを開いて extensions.treestyletab.urlbar.invertDefaultBehavior を false に設定して下さい。

Windows 7のAeroPeek(タスクバーのプレビュー)にアドオンから手を出してみる - May 13, 2010

Windows 7では、特定のアプリケーションのウィンドウが複数開かれている状態でタスクバー上のボタンをポイントすると、各ウィンドウのプレビューが一覧表示されるようになっている。これはAero Peekという機能だ。Firefox 3.6以降ではこのAero Peekのためのコードが入ってて、about:configでbrowser.taskbar.previews.enableをtrueに変更して機能を有効にすると、ウィンドウごとではなくタブごとのプレビューが表示されるようになる。Trunkではデフォルトで有効になってるので、次のメジャーリリースでもそうなるんだろう。

この機能について、ツリー型タブで対応してくれという要望が何件か来ていたので、0.10.2010043001以降では折り畳まれたツリーの中にあるタブのプレビューは表示しないようにしてみた。これを実現するにあたって調べたことを書き記しておく。

FirefoxでウィンドウごとではなくタブごとのプレビューをAero Peekに表示させるためのコードのうち、アドオンから簡単に触れるのはWindowsPreviewPerTab.jsmにあるコードだ。以下のようにするとプレビューのマネージャにアクセスすることができる。

Components.utils.import('resource://gre/modules/WindowsPreviewPerTab.jsm');
alert(AeroPeek); // "[object Object]"

ツリー型タブの新機能(?)の「折り畳まれたタブに対応するプレビューを隠す」は、ここからどうやれば実現できるのか。

まずAeroPeek.windowsの中から、処理対象のウィンドウに対応する項目を探す。このプロパティは各ウィンドウに対応するオブジェクトの配列になっていて、オブジェクトのwinプロパティにFirefoxのブラウザウィンドウのDOMWindowオブジェクトがそのまま入ってる。なので、以下のようにすれば今のウィンドウに対応するオブジェクトを見つけられる。

AeroPeek.windows.some(function(aTabWindow) {
  if (aTabWindow.win == window) {
    // 現在のウィンドウに対する操作
    return true;
  }
  return false;
});

また、このオブジェクトはpreviewsというプロパティの中に各タブのプレビューに対応するオブジェクトを持っている。以下のようにすれば、プレビューからタブのDOMElementを辿ることができる。

aTabWindow.previews.forEach(function(aPreview) {
  var tab = aPreview.controller.wrappedJSObject.tab;
  // タブに応じた操作
});

プレビューのオブジェクトはvisibleという真偽値のプロパティを持っていて、これの値がtrueだとAero Peekのプレビューが表示され、falseだと非表示になる。ツリー型タブの場合、タブが折り畳まれているかどうかによってこの値を上書きするようにしている。

var tab = aPreview.controller.wrappedJSObject.tab;
aPreview.visible = !TreeStyleTabService.isCollapsed(tab);

初期状態では、visibleの値はbrowser.taskbar.previews.enableの値と同じになっている。アドオンでvisibletrueにするとユーザがAero Peekを設定で無効化してても問答無用でプレビューが表示されてしまうので、誤ってtrueにしてしまわないように気をつけないといけない。僕はうっかりこれをやってしまった。

で、プレビューの表示・非表示を切り替えた後は、表示されるプレビューの総数が変わったことをマネージャに通知してやる。

AeroPeek.checkPreviewCount();

Firefoxは、プレビューの数が多すぎる時は強制的にプレビューを非表示にするようになってる。その切り替えの判断は、このメソッドが呼ばれた時に行われている。

以上をまとめると、こうなる。

AeroPeek.windows.some(function(aTabWindow) {
  if (aTabWindow.win == window) {
    aTabWindow.previews.forEach(function(aPreview) {
      var tab = aPreview.controller.wrappedJSObject.tab;
      aPreview.visible = !TreeStyleTabService.isCollapsed(tab);
    });
    AeroPeek.checkPreviewCount();
    return true;
  }
  return false;
});

ツリー型タブでは、これをツリーの開閉が行われる度に実行している。開閉の捕捉はカスタムイベントで行ってる。

プレビューの並び順とかも変えれそうな気がなんとなくしてるので、やる気が出てきたらまたいじってみようと思ってる。ただ、他のアドオンもここに手を出すと衝突しまくりそうではある。

タブバーの縦置き・横置きをタブの数に応じて自動で切り替えたい(A new option to switch the position of the tab bar by the number of tabs.) - May 06, 2010

Q

I have a feature request for Tree Style Tab.

I'd like to use horizontal tabs when I have 5 or less tabs open and then have Firefox automatically switch to vertical tabs when I have 6 or more tabs open. These numbers could obviously be variables in the settings, and the feature could just be toggled from the settings as well.

ツリー型タブへの機能追加の要望です。

タブの数が5つかそれより少ない時はタブを横置きにして、タブの数が6個以上になったらFirefoxが自動的にタブを縦置きに切り替える、という機能が欲しいです。また、タブの位置を切り替える基準のタブの数は簡単に設定できるようになっていて欲しいです。

A

I have no plan to implement the feature to Tree Style Tab itself, however, you can do it by a tiny script using TST's APIs like:

(function() {
  var MAX_HORIZONTAL_TABS = 5;
  var onTabModified = function() {
    var newPosition;
    if (gBrowser.tabContainer.childNodes.length > MAX_HORIZONTAL_TABS)
      newPosition = 'left';
    else
      newPosition = 'top';
    if (TreeStyleTabService.currentTabbarPosition != newPosition)
      TreeStyleTabService.currentTabbarPosition = newPosition;
  };
  gBrowser.tabContainer
    .addEventListener('TabOpen', onTabModified, false);
  gBrowser.tabContainer
    .addEventListener('TabClose', onTabModified, false);
  onTabModified();
  window.addEventListener('unload', function() {
    window.removeEventListener('unload', arguments.callee, false);
    gBrowser.tabContainer
      .removeEventListener('TabOpen', onTabModified, false);
    gBrowser.tabContainer
      .removeEventListener('TabClose', onTabModified, false);
  }, false);
})();

For example, you can use this script for the userChrome.js. Steps to do it:

  1. Install userChrome.js from the official website.
  2. After installation, copy the codes above and paste to the file "userChrome.js" in your profile folder. (ex. C:\Users\username\AppData\Roaming\Mozila\Firefox\Profiles\***.default\chrome\userChrome.js )

そういう機能をツリー型タブ自体に付ける予定はないですが、ツリー型タブのAPIを使うと、上記のような小さいスクリプトでその機能を実現する事ができます。

例えば、このスクリプトはuserChrome.jsでそのまま利用できます。手順は以下の通りです:

  1. userChrome.jsをオフィシャルサイトからインストールする。
  2. インストールが完了したら、前述のコードをコピーして、プロファイルフォルダ内にある「userChrome.js」というファイルに貼り付ける。(例: C:\Users\username\AppData\Roaming\Mozila\Firefox\Profiles\***.default\chrome\userChrome.js )

Why I don't roll Tree Style Tab back to the version which have the option "hide new tab button"? - Mar 31, 2010

I got some requests to add an option "hide new tab button" again.

Excuse me, but I say "no". There are two reasons.

First, by adding too many options, users consider Tree Style Tab as an all-in-one/versatile addon, and novice users who don't understand what is the purpose of TST will also install it. I don't hope that future. Actually, I received some requests like "please add an option to disable tree features, I want only a vertical tab bar." -- I just ignored it.

Yes, currently TST has some features not related to tree, but they are anguished decisions. When I find out other addons which provide those futures, I'll readily remove them from TST itself, and make TST work with those addons together. (Actually I removed "open selected links in tabs" and some features.) I hope that only users who want to use "tree of tabs" install TST.

By the way, in old days I developed an all-in-one style addon "Tabbrowser Extensions" which was well-known before the Tab Mix Plus became major. It had very various options about tabs, it had huge codes, I received too many requests, and I gave up to continue to develop it. I don't want to repeat stupid thing like that.

Second, hiding the "new tab" button is a choice of an user who use another addon to do it. TST is designed to work with visible"new tab" button, and not designed to work without the button. If you decide to hide the button at your own risk, you also have to care the result, especially when you hide the button by customizing of userChrome.css.

Nonetheless, If you hide the button by an option of an existing addon, then I should add some hack to TST for compatibility with the addon, because I said "and make TST work with those addons together." Which addon do you use, Tab Mix Plus? TMP Lite CE? Tab Utilities? If you tell me which is installed, then I can write hack for the addon promptly.

regards,

ツリー型タブにツリーと関係ない機能を加えてくれという要求は尽きない。何度でも言うけど、ツリー型タブを多機能アドオンにするつもりは全く無いし、現状でツリーと関係ない機能が含まれているのは実装上の都合とかそういう理由による苦渋の選択だし、そういう機能を取り除けるものならどんどん取り除いていくつもりだし実際そうしてきたし、とにかくそこを譲るつもりは全くこれっぽっちもありません。特に、アドオンを自分で作ってないエンドユーザの立場から物を言っている人に対しては。自分で作ってる人にはもちろんこう返しますよ、「じゃあそのためのアドオンをあなたが作って下さい。なるべく連携できるようにこっちも頑張るから。」と。

Minefield 3.7a4preのタブバーの仕様変更に対してツリー型タブで取った対応方法 - Mar 29, 2010

タブバーがtabbrowser要素の中から取り出されて1つのツールバーになったということで、タブ関係の挙動を変える系のアドオンが死屍累々なんじゃないかと不謹慎にもwktkしてるわけですけれども。特に影響が大きくて話としても「あーそりゃそうなるわな」ってのが分かりやすいのは、やはりタブバーの表示位置の変更機能ですよね。

今まで

今までは、Firefoxのメインウィンドウの中身は簡単に言えばこんな要素構造になってた。

<toolbox>
  <toolbar/>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

XULのレイアウトは主にMozillaの関係者からCSS3に提案中のflexible box layoutに基づいてるんだけど、

  • -moz-box-orient: horizontal(XUL要素の属性指定だとorient="horizontal")だとボックスの中身が横に並ぶ。
  • -moz-box-orient: vertical(XUL要素の属性指定だとorient="vertical")だとボックスの中身が縦に並ぶ。
  • -moz-box-ordinal-groupの値(XUL要素の属性指定だとordinalの値)の順にボックスが並べ替えられて表示される。

これだけの事を組み合わせれば、タブバーの位置を上下左右好きな位置に移動できた。

  • 初期状態では、tabboxのorientがverticalで、tabsにもtabpanelsにもordinalは指定されていないので、タブバーは上に来る。
  • tabboxのorientをhorizontalにしてtabsのorientをverticalにすれば、タブバーが左に来る。
  • tabsのordinalを2、tabpanelsのordinalを1にすれば、タブバーが下に来る。
  • 両方を同時に指定すれば、タブバーが右に来る。

という具合。

これから

ところが、bug 347930のパッチで要素構造が以下のようにガラッと変わった。

<toolbox>
  <toolbar/>
  <toolbar id="TabsToolbar">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
  </toolbar>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

こうなると、単純にボックスの並び順やら並べる方向やらを変えただけではタブバーの位置を動かせない。

  • toolboxの中にtabsがあるので、ordinalではtabbrowserより下にtabsを持って来れない。無理に持ってこようとするとtoolbox全体がtabbrowserの下に来てしまう。
  • toolboxの中にtabsがあるので、orientではtabbrowserの横にtabsを持って来れない。無理に持ってこようとするとtoolbox全体がtabbrowserの左に来てしまう。

ドン詰まりですね。

他のタブ関係のアドオンが採用した方法

alice0775さんの調べによると、タブバーの位置を変える機能を持ってる他のアドオンでは、tabsを一旦DOMツリーから取り外して別の位置に挿入し直すという方法で、タブバーの表示位置変更を実現しているらしい。

しかしこのやり方だと、tabsがDOMツリーから取り外されるより前に他のアドオンが行った初期化処理の効果がリセットされてしまう場合がある。リンク先のエントリでいくつか挙げられてる懸念がそれ。

本当だったらFirefox本体の方でなんとか面倒を見て欲しい(タブバーの位置変更を行う機能を持たせて、位置が変わる前と後でイベントを発行するようにするとか)所なんだけど、責任者の人達をIRCで英語で説得する自信は全く無いチキンでTOEICスコアめためたで英語音痴な僕は、アドオン側でなんとかする方法を考えないといけない。しかし、最も単純なやり方(DOMツリーの改変)だと他のアドオンとの競合という点で弊害が大きすぎる。

そういうわけで、ちょっと考えてみました。DOMツリーをいじらずにタブバーの位置を変える方法を。

ツリー型タブが採用した方法

ヒントになったのは、XUL/Migemoの「タブバーの下に検索バーを移動する」機能や、Unified Sidebarの「サイドバーを縦型タブバーの下半分に表示する」機能の実装方法。

これらのアドオンでは「検索バーやサイドバーを表示したい位置にmarginやpaddingでスペースを設けて、検索バーやサイドバーをCSS2のポジショニングでその位置に重ねる」という方法で、DOMツリーを改変することなく要素の表示位置だけを変更している。また、ウィンドウの大きさなどが変わった時には、resizeイベントを捕捉して表示位置や要素の表示サイズを自動調整するようにしている。

ツリー型タブのMinefield 3.7a4pre対応でも、基本的にはそれと同じ方法を使う事にした。ただ、タブバーの幅をリサイズできるようにするsplitterを、ポジショニングで表示位置を変えられた状態向けにゼロから作りなおすのは面倒だったので、tabboxの中にダミーのhbox要素を挿入して、splitterは普通にXULのsplitterを使い続ける事にした。

<toolbox>
  <toolbar/>
  <toolbar id="TabsToolbar">
    <tabs orient="horizontal">
      <tab/>
      <tab/>
    </tabs>
  </toolbar>
</toolbox>
<tabbrowser>
  <tabbox orient="vertical">
    <hbox/>
    <splitter/>
    <tabpanels>
      <browser/>
      <browser/>
    </tabpanels>
  </tabbox>
</tabbrowser>

このようにした上で、

  • hboxを含むtabboxの内容を、Firefox 3.6までの手法でレイアウトして、tabsの表示用のスペースを確保する。
  • hboxの上に同じ大きさでtabsを重ねる。
  • splitterによってhboxがリサイズされた時は、tabsの位置や大きさを自動的に更新する。

とする事で、ぱっと見は今までと同じような挙動を実現しつつ、タブ周りのDOMツリーは一切破壊しないという実装になった。

どっちのやり方の方がいいのか

ツリー型タブのやり方とTab Mix Plus等のやり方のどっちがいいかは、一概には言えない。どちらにもメリットとデメリットがある。

ただ僕は、ツリー型タブで採用したやり方の方が「他のアドオンが全く動かなくなってしまうような衝突の仕方はしなくて、仮に衝突しても最小限の労力でなんとか回避できる可能性が高い」と信じている。

現在Firefox本体の側には、3.6以前のバージョンのFirefox向けに書かれたアドオンについて、Minefield 3.7a4pre以降でもそのまま動くようにするためのパッチも取り込まれている。ちょっとアドオンの作り方に気をつけさえすれば、タブをダブルクリックした時の挙動を変えるとか、リンクから開いたタブの位置を制御するとかいった単機能のアドオンは、ほとんど何も手を加えずにMinefield 3.7a4pre以降に対応できるようになってる。

しかしながら、Tab Mix Plusが現在採用している(らしい)DOMノードを切り貼りするやり方では、「ほっといても他のアドオンがちゃんと動いてくれる」ようにはなりにくい。「DOMノードの切り貼りでタブバーの位置が変更された事」を検知して何らかの特別な初期化処理を行うようなコード、を他のアドオンの側に加えてもらわないと互換性を保てない。僕は、僕のアドオンと競合しないで使えるようにするために、他のアドオンの作者がわざわざ気を使ってくれるとは思えない。僕が作ってる物が、そこまで他のアドオン作者から特別視してもらえる存在だとは、思えない。

なので、僕がアドオンを作る時はなるべく、他のアドオンの側に変更が必要になるような作りにはしないでおこうと思ってる。どうしてもそうなる時は、APIを提供してAPI経由でスッキリと連携できるようにしようと思ってる。そういう謙虚というか悲観的な姿勢が、「ユーザがどんなアドオンと組み合わせて使うかは全く分からない」アドオンを作る上では必要なんじゃないかと思ってる。

Page 8/248: « 4 5 6 7 8 9 10 11 12 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき