たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
Tree Style Tab 0.13.2011121401で、長年の課題だった点に対する改善を入れてみた。現実逃避です。
まず1点、ツリーの復元にすごく時間がかかるという問題。。
今まではSSTabRestoringイベントのタイミングでツリー構造を復元してたんだけど、これだとタブがちょっとずつしか復元されないせいでツリーもちょっとずつしか復元されない→ツリー全体が復元されるまで場合によってはものすごく時間がかかる、という問題があった。でもSSTabRestoringイベントが発行される前の時点ではnsISessionStoreのsetTabValue()
で保存した情報を取り出せないからどうしようもなくて、ずっと放置してた。
これが最近のバージョンのFirefoxではSSTabRestoringより前でもセッションに保存された情報を取り出せるようになってたので、じゃあってんで、真っ先にツリー構造だけ復元するようにしたという次第。
前のエントリではnsIObserverでメッセージを拾うとか何とか書いたけど、結局その方法はやめた。最終的にどうやったのか、という事を簡単に書いておく。
おさらいとして、Firefoxが備えているセッション復元機能は以下のような流れで処理を行っている。
問題は、1と2の間に割り込んで、2で使い回される事になるタブのツリー構造を一旦リセットしないといけないけど、そのためのAPIが無い(どのタブが使い回される事になるのか、を知る方法が全く無い)っていう事。
PurgeHistory()
というメソッドが呼ばれていて、nsISHistoryにはnsISHistoryListenerインターフェースを備えたリスナを登録できるようだったので、これを使えばいけるか!?と思ったけど、nsISHistoryには1個しかリスナを登録できなくてアドオンでリスナを追加するとFirefox自身が追加したリスナが失われてしまって、全体的に動作がぶっ壊れてしまった。とかなんとかああでもないこうでもないといじり回していて、もう最後の手段という事で、<browser/>
のstop()
を置き換えてフラグを立てたり下ろしたりするようにした。nsSessionStoreは1と2の間で、使い回す予定のタブをプライベートメソッドのrestoreHistoryPrecursor()
に渡してそれらの内容を初期化するという事をやってて、その中で必ずstop()
を呼んでいたので、stop()
が呼ばれた時にJavaScriptのスタックを辿って、restoreHistoryPrecursor()
から呼ばれていたら「このタブはこれから使い回されようとしている」というフラグを立てるようにした。restoreHistoryPrecursor()
は他の場所からは絶対に呼ばれないから、これが一番確実だと思う。
そうすると、
restoreHistoryPrecursor()
のタイミングで、「これからセッション情報が復元されようとしているタブ」にフラグが立つ。という具合にして、個々のタブのセッションの復元完了を待たずに一気にツリー構造を復元できるようになるわけです。
この改善は、Firefoxのセッション復元APIを使ってるSession Managerとの併用でもちゃんと活かされる。Tab Mix Plusみたいに独自のオレオレセッション復元機能を持っててそれを使ってる環境は……知らない。多分動かないだろうけど対応する気力無い(そもそも、僕自身Session Managerは使っててもTMPは使ってない)。
次、2点目。タブで開いてる内容がPDFだったりFlashだったりすると「タブバーを自動で隠す」が機能しないという問題。
ポインタの位置に応じて自動的にタブバーを表示したり隠したりという事をやるためのベタなやりかたは、Firefoxのウィンドウ(XULドキュメント)でキャプチャリングフェーズでmousemoveイベントを監視するという方法だ。ポインタがタブバーの近くに来たらタブバーを表示して、コンテンツ領域の上に載ったら(タブバーから離れたら)タブバーを隠す、という感じ。AutoHideというアドオンはそうしてたし、ツリー型タブもそうしてる。
ところが、何度か中野さんが解説されてた気がするけど、Firefoxはプラグイン(FlashとかPDFとか)の描画領域の上で発生したクリックやら何やらのイベントは全部プラグインが握りつぶすようになってる。そのため、普通にmousemoveイベントを監視してても、プラグインの領域にポインタが載ってる間は何もイベントが発生しない。ポインタがタブバーから離れた事はmouseout等で検知できても、コンテンツ領域に載ったという事を検知する事ができない。
(ちなみに、ツリー型タブではタブバーの「近く」にポインタがあるときはタブバーを隠さないで、ちょっと離れたら初めてタブバーを隠す、という風にしている。そうしないと、タブバーの幅を変えるためにスプリッタをドラッグしようとしても、ちょっとポインタがぶれただけですぐタブバーが隠れてしまってストレスが溜まってしょうがない。なので、mousemoveでポインタの座標を監視するという方法に頼らざるを得ないのです。)
同じ理由で、マウスジェスチャ系のアドオンもプラグインがあるとジェスチャがまともに動かないという事が結構あるみたい。そこをどうにかしようとすると、CとかC++とかでコンポーネントを作ってもっとプラットフォーム寄りの所でポインタの位置を拾うしかなくて、「プラグインの上でもジェスチャできる」が売りのMonkey Gesturesは実際そのようにしてたと思う。
ネイティブなコンポーネントを書くというのは嫌っていうかそんな手間かけたくなかったので代わりにどうやったかっていうと、すごく単純な話で、background: rgba(0,0,0,0.01) !important; -moz-appearance: none !important;
にした<panel/>
をコンテンツ領域の上に重ねて開くようにした。たったそれだけ。そうするとXULの要素の上だから普通にmousemoveイベントが発生して、ポインタの正確な位置を取れるようになった。
透明なポップアップを表示する時には、セオリーというか注意点がいくつかある。
background: transparent !important;
で完全な透明にしてはだめ。完全に透明な<panel/>
は何のイベントも拾ってくれない。なので、rgba(0,0,0,0.01)
(ものすごく薄い半透明の黒)のように、何かとにかく色を付けておく必要がある。background: transparent !important;
で完全透明にしつつborder
でちょっとだけ線を表示して、<panel/>
の中に不透明な部分を作ってやる。
<panel/>
の左右にだけ枠線を付けるという風にして、領域が矩形にならないようにする。透明な<panel/>
を使う方法にはいくつか弊害があって、今まではそれを気にして採用を避けてた。が、今回のアップデートではそれぞれ「できる所までは頑張ろう、どうしても無理な所はもう知らん」というスタンスで割り切ることにした。
<panel/>
がクリックされてしまうと、「クリックしたのに何も起こらない」という状況が発生してしまう。
<panel/>
を使うようにした。タブバーが隠れて<panel/>
が閉じられた後でなら普通にクリックできるので、タブバーが隠れる前にコンテンツ領域をクリックするようなせっかちな人の事はもう諦める事にした。<panel/>
以外の部分(ツールバーボタンなど)をクリックすると、環境によっては、透明な<panel/>
が閉じられるだけで終わってしまう。
popupBoxObject.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_NO_CONSUME)
である程度は抑制できるっぽい(Ubuntu 10.04LTSのcompizだと、Firefoxのウィンドウの中に対してはclick-throughが通用するようになったが、他のアプリケーションのウィンドウをいきなりクリックした時は相変わらずだった)。どうしても駄目な時については、もう、諦める。なんで方針を変えた(安全に完璧に提供できない弊害の多い方法は使いたくない→弊害があっても使う)かというと、「同じ要望がもう数えるのも嫌になるくらいしょっちゅう来ててウンザリしたから」っていうのが最大の理由だ。
いや、つまり「PDFとか表示してるとタブバーが隠れてくれない」問題は、割と誰でもぶち当たってしまう問題なわけですよ。それに対して、実際に調べたわけではないけど、多分上に挙げたような「弊害」が実際に致命的な問題になるような人は多分そんなに多くないだろうと思うわけですよ。どっちの人を大事にしたらいいかっていう事で天秤にかけて、前者を救う事にした。という話なのです。
そういう意味では、TMPの独自のセッション復元機能を使ってる人を見捨てるってどうなんっていう言い方もあるだろうけど、あんなもん(TMP独自のセッション復元機能)ぶっちゃけ捨てていいですよ。Firefox本体のセッション復元機能に勝ってる部分、ありますか? ないですよね? いやよく調べないまま書いてるんだけどさ。
I got a mail from Tab Mix Plus developers team. So I updated compatibility codes in Tree Style Tab for the latest dev-build of TMP. After that I got another mail again, and he said that the latest TST doesn't work with the last public release of TMP. This is the reply:
Hello, onemen.
First, I really think TMP helps very huge people from poor tabbed browsing features of Firefox itself. It is a great thing. So, I hope my addons including TST work with TMP correctly.
However, I'm afraid I can't support both versions of TMP (the latest dev-build and the last public version) anymore, because I believe that they are too different to support simple hacks. I already removed many codes based on the latest dev-build of TMP by this commit, so I can't believe TST works with the last public release only with minor changes only about symbols (function names). And, if I restore codes for old TMP, then both old and latest TMP will override them again and re-introduce many unexpected problems. That is too terrible.
To be honest, it was very painful to read dynamic-eval codes in TMP and TST itself because they are many tree-times eval-ed codes (defined by TMP => overridden by TST => overridden by TMP again). So I don't want to do such a painful work again for the last public release...
Yes, I apologize that I'm also using many eval() to hack TMP. So I believe that both addons TMP and TST should remove all eval-based hacks for each other and make themselves plaggable via their public APIs. TST already defines some public APIs. I agree that they are too less APIs to make compatible TMP with TST now. I'll add new APIs to do it if they are really required for high compatibility. I'll make efforts to keep stable those APIs in future versions. I don't know what APIs are required for TMP, so, I hope to listen your idea.
On the other hand, I hope that TMP provides some public (and stable) APIs for addon developers, like:
- An API to add extra properties for TabmixSessionData
- Custom DOM events for TMP specific features
If there is any public document already, could you tell me the URI?
regards,
I can't believe that I keep the current method (eval-based dirty hacks) to make them compatible.
With BOTH Tree Style Tab AND Tab Utilities enabled at the same time, the ColorfulTabs extension makes no difference - no tabs get colored. I have reported this to the author of Tab Utilities since it has worked properly in all previous versions of Tab Utilities. But here's his answer:
TU hacks the ColorfulTabs code to reduce its use of "!important", but Tree Style Tab still uses "!important" for tab background-color. I may revert TU's changes, but IMO it's Tree Style Tab who behaves improperly. It uses too many unnecessary "!important" modifiers in CSS rules, which also leads to the conflict with TU for the pinned tabs' position.
Can you fix this please?
ツリー型タブとTab Utilitiesが同時に有効になっている時、ColorfulTabsは何の変化ももたらしません──つまり、タブに色が付きません。Tab Utilitesの以前のバージョンは正しく動いていたため、私はこの件をTab Utilitiesの作者に連絡しました。しかし彼はこう言っています:
Tab Utilitiesは「!important」の使用を減らすようにColorfulTabsのコードに手を加えていますが、ツリー型タブはまだ多くの「!important」指定をタブの背景色に指定しています。私はTab Utilitiesに加えた変更を取り消すかもしれませんが、しかし私の考えでは、ツリー型タブのやり方の方が間違っています。ツリー型タブはあまりに多くの不必要な「!important」指定をCSSの中で使っており、これはTab Utilitiesの「ピン留めされたタブ」の配置を壊す原因にもなっています。
この件について修正してもらえませんか?
Those "!important" are surely required, because appearance of tabs can be modified by third-parties' theme. For example, if a theme defines black background with white text, then partially applied styles from TST possibly make lighter background with white text -- yes, it is very hard to be read. To avoid these cases, I decided to use "!important" rules. Actually I got some "bug reports" like this. If I remove those "!important", I'll get similar bug reports again -- I'm very sorry but I don't want that.
Instead, I made an option for "highly compatibile for other addons". See the configuration dialog of TST, "Appearance" panel. There is an option "Default (Specified by the Theme)" in built-in themes. If you choose the option, TST doesn't apply any "!important" rule for tabs. I believe that the option makes TST compatible with Tab Utilities and ColorfulTabs.
それらの「!important」指定は必要な物なのです。タブの外観がサードパーティ製のテーマによって変更される事があるのがその理由です。例えば、あるテーマが背景色を黒に、文字色を白に設定していた時、ツリー型タブのスタイル指定が部分的に適用されてしまうと、明るい背景色と白い文字の組み合わせになってしまうことがあります──これはとても読みにくいですよね。こういったケースの発生を防ぐために、私は「!important」指定を使う事を決めました。実際、私はそういう「バグ報告」を受け取った事があります。もしこれらの「!important」指定を削除したら、私は再びそういった報告を受け取る事になるでしょう──申し訳ありませんが、私はそれを望んでいません。
その代わりに、私は「他のアドオンとの互換性を高く保つ」選択肢を設けました。ツリー型タブの設定ダイアログの「外観」パネルを参照してください。ここでタブバーの表示スタイルとして「なし(テーマ本来の表示スタイル)」を選択すると、ツリー型タブは「!important」指定が付いたスタイル指定を適用しなくなります。これを選択する事で、ツリー型タブとTab UtilitiesやColorfulTabsの衝突は回避できるものと私は考えています。
It would be nice if you could search the tabs.
タブを検索できるといいんですが……
Tab Filter or Search Tabs will help you.
Tab FilterかSearch Tabsを使ってみるとよいでしょう。
Tree Style TabとMultiple Tab Handlerのドラッグ&ドロップ周りのコードを色々書き直した。
発端は、「Tab Utilitiesと一緒に使うとタブのドラッグ&ドロップが期待通りに動かない」という報告だった。しかし、「また衝突かよー」と思いながらメールの内容を読むと、想像していたのとはちょっと状況が違った。
僕はてっきり、Tab Utilitiesのイベント処理とツリー型タブのイベント処理がかちあって変な事になってるんだとばかり思ってたんだけど、そうではなくて、Tab Utilitiesが提供する「複数のタブを選択してまとめてドラッグ&ドロップする」機能で複数のタブを1つのタブの上にドロップしても、選択されていたタブのうち1つしかドロップ先のタブの子タブにならない、という状況だった。その人はすでにTab Utilitiesの作者にも問い合わせていたようで、Tab Utilitiesの作者の回答に「ツリー型タブにマルチプルタブハンドラのためのコードしか含まれていないのがそもそもの問題だ。ツリー型タブの方で修正してもらってくれ。」みたいなコメントがあったそうだ。
それでTab Utilitiesを見てみたら、確かに複数のタブを選択する機能があったんだけど、その時のタブの情報の受け渡しにHTML5のドラッグ&ドロップのイベントの複数のデータの指定の仕組みが使われているようだった。
という事情があって、マルチプルタブハンドラではドラッグ操作のイベントそのものには介入しないようにしてたんだけど、Tab Utilitiesがそういう事をやってるんだったら、「複数タブのドラッグ操作」に特化したアドオンであるマルチプルタブハンドラが黙って見てるわけにはいかない。なので、マルチプルタブハンドラではバージョン0.6から、ついでにツリー型タブもバージョン0.11.2010120101から、タブをドラッグ&ドロップするときはドラッグしようとしているすべてのタブをデータトランスファーに渡すようにした。ついでにドラッグフィードバックイメージも自前で生成するようにして、複数タブのドラッグ時はドラッグ中のすべてのタブのサムネイルを重ねて表示するようにしてみた。
それで「ああやっと時代に追いつけたわ」と安心してたんだけど、Windowsでテストしてみたら、せっかく生成したドラッグフィードバックイメージがぜんぜん表示されないんでやんの。どうも、Windows版のFirefox 3.6以前は、mozSetDataAt()
で複数のデータを指定するとドラッグフィードバックイメージが表示されないというバグがあるようだ。Ubuntu上のFirefox 3.6や、Windows上でもMinefieldでは問題なかったんだけど。頑張りの報われなさに切なくなった。
ツリー型タブの場合は、タブのドラッグ&ドロップでツリーを編集する場合があるから、マルチプルタブハンドラみたいにTabMoveイベントをトリガーとして後から必要な処理を行うということはできなかった。なので、Firefox自身のドラッグ&ドロップの処理に介入する形の設計にせざるを得なかった。
その後HTML5のドラッグ&ドロップのAPIが実装されて、Firefox 3.5ではFirefoxのタブのドラッグ&ドロップのためのコード自体もそれをベースに書き直された。これはまだFirefox 3.0と同じようなやり方でドラッグ&ドロップの処理に介入できる余地があった。
しかしFirefox 4ではタブのドロップとかドラッグオーバーとかの処理がXBLのイベントハンドラの中にベタ書きされるようになってしまって、メソッドの中に処理を注入するやり方ではドラッグ&ドロップの操作に介入できなくなってしまった。なので、仕方ないからdragstartとかdropとかのイベントにキャプチャリングフェーズで割り込んでツリー型タブの側で全部自分で処理するようにした。
という経緯があって、結果的にツリー型タブのドラッグ&ドロップ周りの処理はFirefox 3.0向けとFirefox 3.5~3.6向けとFirefox 4向けとで3種類の方法が同居してかなりシッチャカメッチャカな状態になっていた。あとタブバー自体のドラッグ&ドロップの処理もあって、それぞれがあちこちに散らばっててだいぶ訳のわからんことになってた。
そんな状態だったから、昨日のリリースでは案の定リグレッションしてドラッグ&ドロップが盛大にぶっ壊れてた。これはもう駄目かもわからんねと思ったので、Firefox 3.0向けのコードを全廃したついでにFirefox 3.5~3.6に対してもFirefox 4向けのやり方を使うようにして、ドラッグ&ドロップのコードを専用のクラスに集めて整理することにした。
安定性とメンテナンス性を取った結果、タブのドラッグ&ドロップのイベント処理はFirefox本体のものを完全に無視する形になっているので、他のアドオンとの機能の両立という点では残念なことになっているかもしれない。タブのドラッグ&ドロップに介入するためのきちんとしたAPIが整理されていれば、こんな思いをしなくて済むのになあ。
今まではTree Style Tabでタブバーを横置き(上または下にタブバーを配置するモード)にした時特有の機能というのは特に設けていなかった、というか横置きで階層化されたグループ化なんて全然使いにくいし誰も使わないだろと思って割となおざりにしてたら、案外使われてるみたいで時々このモード特有のバグ報告を貰ってたわけですが、Opera 11でタブスタッキングとかいう機能が加わるとかで「そんなんXULでもできるわい!!! つうかもっと前からやっとるわい!!!」とカッとなって、タブが重なってるっぽく表示するようにしてみた。
種を明かしてしまうと、元々「折り畳まれたタブ」はvisibility: collapseで見えないようにしてたのを、collapseにせずにvisibleのままで親のタブの下にz-indexを調整して重ねるようにしたというだけ。諸々の事情でMinefieldでしかこの表示にはならないようになってる(Firefox 3.6だと今まで通り)。
このようにしたおかげで、
というメリットを図らずも得られてしまった。
しかしIDEA*IDEAの記事の小さいスクリーンショットと動画だけ見てこういう表示にしたんだけど、もっと大きなスクリーンショットだと、実際は全然違う形だった。まあ、今更だからこのままいくけどさ……
あと、このリリースから「リンクをクリックした時にそれを自動的にタブで開く」系の機能と「ロケーションバーからの入力で常にタブを開く」系の機能を別のアドオンに分割することにした。
既にあったOpen Bookmarks in New Tabと並べて「新しくタブを開く系3兄弟」的な。
といった理由があっての決定です。多機能なのがいい人はツリー型タブを捨ててTab Kitあたりに乗り換えるといいと思います。
ツリー型タブのGoogle Chrome版は作らないの?という問い合わせを一時期よくもらってたんだけど、とうとう出た。Google Chrome版Tree Style Tab。といっても僕が作ったんじゃなくて、ジェバンニが一晩でやってくれました。的な。
ただ、やはり僕が懸念していたように、形態としては「ツールバーのボタンをクリックしたらポップアップでツリーが出る」という物のようで、実際試してみても違和感があった…… 僕は「ツリーが常に見えている事」がTSTの常用には欠かせないと思っているので、この形の物はやはり辛い。
Side Tabs(起動オプション --enable-vertical-tabs で有効になる)が入っている最近のChromeでなら、あともうちょっと頑張ればなんとかなりそうな気がしなくもない。ページのタイトルの頭にスペースを挿入して擬似的にタブをインデント表示するとか。
It is nice if I can switch between tabs on the top and side. I know you can drag it but if the top gets filled up, then its hard to drag it. Then I have to open the prefs to move it. Be nice if it was easier to move the tab bar to different sides quickly.
タブバーの位置を上と左(または右)の間で簡単に切り替えられると便利だと思います。タブバーをドラッグすれば場所を移動できるのは知っていますが、タブバーが上にありタブが沢山開かれていて余白がない場合、タブバーをドラッグするのは難しいです。そういう時は仕方がないので設定ダイアログを使うほかありません。タブバーを異なる位置に簡単に移動できる方法があるといいのですが……
I have no plan about (re-)adding the feature to the Tree Style Tab. I think an answer for another question possibly help you: A new option to switch the position of the tab bar by the number of tabs.
By the way, you can start to drag the tab bar without blank spaces in the tab bar. Try to drag something in the tab bar not a tab. (ex. "New Tab" button, "<" button, ">" button, or "List All Tabs" button)
その機能を(再び)ツリー型タブに加える予定はありません。ただ、他の質問に対する回答があなたにとって何らかの助けになるかもしれません。タブバーの縦置き・横置きをタブの数に応じて自動で切り替えたいを参照して下さい。
それはさておき、タブバーのドラッグ&ドロップは、タブバーに余白が無くても行う事ができます。タブバーの中のタブ以外の任意の位置(例えば「新しいタブ」ボタン、スクロールボタン、「タブの一覧」ボタンなど)をドラッグしてみて下さい。
If I open a new tab they always open on bottom. I have alway many tabs open and I need to scroll always down to see new tab. That's for me not very comfortable. Is possible that new tab open on top?
新しいタブを開く時、タブは常にタブバーの一番下に開かれます。私はいつも非常に多くのタブを開いているため、開いた新しいタブを見るためにはいつも一番下までタブバーをスクロールしないといけません。これは非常に面倒です。新しいタブをタブバーの上の端に開く方法はありませんか?
Now TST doesn't provide such a feature to control new tab position. I think TST should not implement features not related to "tree of tabs", but it should be done by another addon designed for the purpose, for example, Tab Control does it.
現在、ツリー型タブはそのための機能を提供していません。私は、「タブのツリー」とは関係ない機能はツリー型タブには含めず、そういう目的のために開発された他のアドオンで解決するべきと考えています。例えばTab Controlがそういう機能を持っています。
When I Ctrl+click a link, I want a new tab opened without focus, but when I set Automatic New Tab Level for Links to Lv. 2 and Ctrl+click a link, I get the same tab opened with focus. That's really annoying!
リンクをCtrl-クリックした時にバックグラウンドでタブを開いて欲しいと思っているのですが、「リンクから自動的にタブを開くレベル」を「Lv.2」に設定していると、Ctrl-クリックした時にリンクが現在のタブに読み込まれてしまいます。これ、なんとかならないんでしょうか?
TST has a secret preference for the problem. Please go to "about:config" and set "extensions.treestyletab.link.invertDefaultBehavior" to "false".
The behavior you saw is not a bug, but a designed behavior. By default behavior of Firefox, simple click does "load into the current tab" and ctrl-click does "open new tab". In the "lv.2" Tree Style Tab inverts the behavior, so, ctrl-click now loads the link into the current tab. If you set "extensions.treestyletab.link.invertDefaultBehavior" to "false", TST doesn't invert the behavior but simply opens any link in new tab.
TSTにはこの問題のための隠し設定があります。about:configを開いて、「extensions.treestyletab.link.invertDefaultBehavior」を「false」に設定して下さい。
あなたが遭遇している現象は、バグではなく意図された挙動です。通常、Firefoxはリンクをクリックすると現在のタブでそれを開き、Ctrl-クリックするとリンク先を新しいタブで開きます。「Lv.2」ではツリー型タブはこの挙動を反転するため、リンクをクリックするとリンク先を新しいタブで開き、Ctrl-クリックで現在のタブで開くようになります。隠し設定の「extensions.treestyletab.link.invertDefaultBehavior」を「false」に設定すると、ツリー型タブはFirefoxの挙動を反転する代わりに、単純にリンクを常に新しいタブで開くようになります。