Home > Latest topics

Latest topics 近況報告

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

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

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

Page 32/248: « 28 29 30 31 32 33 34 35 36 »

Jetpack作った - Oct 11, 2010

今のFirefox用アドオンの開発にかかる手間を省いて、インストールやアンインストールの際にFirefoxを再起動しなくても済むようにする、Firefox 4向けの新しいアドオンの仕組みであるところのJetpack(サイトのトップページのスクリーンショット) 最初はGreasemonkeyとuserChrome.jsの合いの子みたいな感じでスタートしてたみたいですが、いつの間にかRebootedになって、SDKを使って開発するという形の物に変わってしまっていました。Rebootedになってからの情報はGomitaさんが色々と記事を書いて下さっています。

Rebooted前に僕もちょっとだけJetpack用にテキストリンククリップボード監視を書き直してみたりしたんですが、Rebootedになってからは全くフォローできていませんでした。

で、この度改めてちょっと本腰入れてJetpack作ってみようと思ったんです。

はい、できました。

(Jetpackの写真)

うん。どこから見てもJetpack。

(Jetpackの写真:裏側)

SDKベースになっても作るのは簡単でした。Jetpack素晴らしいですね。

そういうわけでリアルJetpackです。制作期間は大体1.5週間くらいでしょうか。夏コミの時にふぉくす子コスで手伝ってもらったhknさんがはやぶさで有名秋の『』さん会場で偶然遭遇したそうで、背負い物イイナー!ということで面白そうだから冬までには作ってみようと思っていたのですが、去る10月10日に開催された痛Gふぇすた2010にふぉくす子の参加要請があったため、それに合わせて突貫作業で作ってみました。

芯にペットボトルを使い、先端部分とノズル周りと背負うためのベルトさえ作れば簡単にできるんじゃね? と思ってやってみたんですが、リアル工作なんてものすげー久しぶりだったので少々苦労しました。ちゃんとした設計図を作らないまま現物合わせで切ったり貼ったりしたのであちこち微妙に歪んでいますが、遠目に見たら分からないので気にしないことにします。

制作は先端部分から取りかかりました。芯にしたのはペプシコーラのペットボトルで、口をノズル側にした(今回はやらないけど、いつかチャンスがあったらペットボトルロケット的なギミックを仕込んだバージョンを作る事を想定して、そのようにしています)ので先端側にはペットボトルの尻が来たわけですが、5角形というか星形というかそういう変な形をした尻だったので、先端の断面の形に切った厚紙5枚を組み合わせてガムテープでぐるぐる巻にして大まかな形を作った後、普通の紙粘土で覆って表面を丸っこくしました。

(Jetpackの写真:先端のアップ)

乾燥させて紙ヤスリで表面をなめらかにして色を塗ればそれで十分かなーと思ってたんですが、この紙粘土が乾燥してもメチャメチャ脆くて、塗装中も段ボールに先っぽをぶつけただけでボロッと崩れるとか、掃除機で表面の削りカスを吸い取ろうとしたら芯への食いつきが悪いせいで端の方からベリッとはがれるとか、こいつのせいで手間がだいぶ増した気がします。とにかくこんなに脆いんじゃそのまま使うとヤバイと思ったので、塗装した後で透明ニスを何回も重ね塗りして補強しておきました。ニスを塗る工程は当初は想定してませんでしたが、小さい頃に紙粘土工作をした後に必ずニスを塗らされたのはこういう事だったのだなあと、今更になって当時やった事の意味をを思い知らされました。

あと、形を出した後で思い出しましたが、確かハンズにこういう形の発泡スチロールの塊が売られていた気がしますので、最初からそれを使えばよかったなあと後悔しました。紙粘土は表面だけに使ったといっても、大きさが大きさだったので結局ここだけで500グラム以上になってたみたいですし。軽く作る工夫は大事です。

胴体は元のデザインにあるスリットを開けておいたボール紙をペットボトルに巻き付けただけです。 (Jetpackの写真:胴体のアップ)

ノズル部分は、戦闘機のベクタードスラストノズルみたいなデザインだと思い込んでいたためにその前提でプランを考えていたのですが、胴体のスリットを開口するために元のデザインを確認したら、全然違ってました。でも先すぼまりな形を継ぎ目無しに作るのはボール紙じゃキツいわと思ったので、元デザイン無視でやはりベクタードスラストっぽいデザインを意識した物にしてみました(配色もそれを意識してます)。 (Jetpackの写真:ノズルのアップ) あと、先端を紙粘土にしたことによってすごいトップヘビーになってしまったので、バランスを取るために、外からは見えませんがペットボトルの口の周りに紙粘土を重りとして巻いてあります。これで結局、全体で1kg以上はある感じの重たい装備になってしまいました。

胴体のボール紙の継ぎ目とか先端と胴体の間の所とかをごまかすために細切りのボール紙を巻いて、隙間をホットボンドで埋め、形としては完成しました。

着色は、スプレーで先端とノズルに色を付けた後、先端とノズルをマスキングして胴体のシルバーをスプレーで塗るつもりだったのですが、前述した通り紙粘土部分がメチャメチャ脆くて、これじゃマスキングテープで確実に表面がボロボロはがれるわと思ったので、先に先端(とノズル)だけニスでコーティングすることにしました。2時間以上乾燥→重ね塗り、で2~3重に塗ったので、結構頑丈になったと思います。あと、塗装は缶スプレーだけでいいかなと思ってましたが、実際やってみると赤色は結構下地のアラが目立ってしまいましたので、先にサーフェイサーで灰色一色にしてから赤や茶色を塗りました。胴体は、銀色の隠蔽力の高さに期待して特にそういう事はせず、ボール紙に銀色のスプレーを吹いてニスを塗っただけです。ニスが乾いた後で、ノズルがテカテカ光ってるのは変かなーと思ったので、最後に胴体をマスキングしてノズルの部分だけつや消しクリアーを吹いてあります。

左右の胴体の連結やベルトの固定方法については、当初は何も考えていなかったのですが、いい材料はないかと思ってホームセンターの商品を眺めていたら簡単に曲げられそうな穴あきの金属の板があったので、それを曲げて形を作って左右の部品をネジ留めしてからタッピングビスで胴体に固定することにしました。 (Jetpackの写真:連結部分のアップ)

ベルトは100円ショップで買った物を適当に切って使ってます。しかし実際に背負ってみるとベルトが肩に食い込んで痛かったので、そのうちクッション材(カバンの肩紐にあるようなやつ)を付けたいとは思っています。

表面がガタガタであまり見れたものではありませんが、大きな写真をFlickrに置いてありますふぉくす子が背負っている様子の写真はもえじらブログの方にあります

Firefox 4: jar jar jar - Oct 06, 2010

この間悩まされたばかりのomnijarの話である、Taras’ Blog » Blog Archive » Firefox 4: jar jar jarの勝手翻訳です。分からない所が多かったので創作的意訳が多めですが気にしません。


ファイルを開く処理というものは、システムコールのための小さなオーバーヘッドや、ディスクからのデータの先読みによる大きなオーバーヘッドがある、比較的重たい処理です。データの物理的な配置の状態やディスクの種類によっては、この処理は今時の高速なCPUに対して、複数の異なるファイルそれぞれの全ての断片を先読みするためにディスク上をヘッドが激しく行き来する間、長々と無駄に暇をもてあまさせる事にもなり得ます。

最適化その1:裸のファイルをより少なくする

約2年前、私(訳注:元エントリの著者のTaras Glek)はディスク上にある裸のファイルを収集してjarファイルに詰め込む作業を始めました(例:bug 508421)。また、コードのクリーンアップやmmapへの移行などを通じて、私達はjarファイルの読み込み処理の効率も可能な限り改善しました。そして最終的には、通常の起動時にディスクから読み込まれていた、アプリケーションを構成するデータファイルの全てが、jarファイルの中に格納されるようになりました。しかし残念ながら、私達は4つのjarファイル(toolkit、chrome、そして2つのロケール用jarファイル)に構成ファイルをまとめる所までしか至れませんでした−−何ともマヌケな事ですけれども。またXPCOMの制限により、多数の裸のファイルがまだ、Firefoxのアップデートや拡張機能のインストールの度にディスクから読み込まれる状態となっていました。

最適化その2:全てを統べる1つのjarファイル

最近、Michael Wuがomnijarという<ruby><rb>滅茶苦茶にヤバい物を解き放ち</rb><rp>(</rp><rt>非常に影響範囲の大きな変更を導入し</rt><rp>)</rp></ruby>ました。これはAndroid用パッケージ作成での必要に迫られて行われた非常に大きな取り組みです。今や、アプリケーション起動時に必要なデータは常に単一のファイルから読み込まれるようになりました。これはデータの位置の集約化、ファイル走査の手間の短縮、そして待ち時間の短縮に繋がります。複数のファイルを1つに小さくまとめる事の1つの利点としては、OSがディスクからデータを読み込む際に、大抵の場合はアプリケーションが要求したよりも大きな単位で、投機的にディスクからデータを読み込む事も挙げられます。これにより、隣接するファイルの読み込みがより自由に行えるようになります。残念ながら、Firefoxを実際に実行せずにファイルアクセスの順番を予測するための良い方法がなかったため、ここにはさらなる改善の余地があります。

最適化その3:jarファイル内でのファイル配置の最適化

さて、今や全てのデータが1つのファイルの中に置かれましたので、論理的な次のステップは、それらをより賢く格納する事でした。それを行うための唯一の方法は、Firefoxの起動時の処理を分析して、jarファイル内のファイル配置をその結果に基づいて並べ替える事です。残念な事に、jarファイル内の全ての項目を連続的に配置するにあたって、私達はまだ次善の策を取っています。これは、ZIP(jarファイルの実態はZIPファイルです)のインデックスが伝統的にファイルの終端に配置されている事に依っています。Wikipediaの記事にこれを図示した物があります。

先読みの利点を最大限に活かし、ディスクの走査を最小限にするためには、格納されたファイルのインデックスがZIPファイルの先頭に置かれているのが望ましいです。そのため、私は私達のZIPファイル内のデータの配置を、

<項目1><項目2>…<項目N><インデックス><インデックスの終端>

から

<最初に読み込まれる、最後の項目の位置のオフセット値><インデックス><インデックスの終端><項目1><項目2>…<項目N><インデックスの終端>

に変更しました。

ここで私がやったのは、<インデックスの終端>のオフセット値を常に4になるようにした(どうでもいい事に拘るZIPアーカイバはインデックスのオフセットがNULLだとフリーズしてしまう事があるので、これは0にすることはできません)だけです。その際、インデックスは常に前のインデックスの終端に続けて配置されなければならないという仕様を満たすために、私は最初の物と全く同じ2つ目の<インデックスの終端>を加えました。また、私は、過度に用心深いZIPアーカイバによって強制された、どれだけのデータを最初に先読みしておく事ができるかを示す数値を格納するための追加の余白も利用する事にしました。

これによって、最適化されていないomnijarに比べてディスクI/Oの2〜3倍の削減を実現しました。これは裸のファイルをomnijarにすることで20〜100倍以上の高速化が実現できた事の最大の要因です。

私がZIPの仕様を読んでガッカリしたのは、ZIPアーカイバの中にはZIPファイルが仕様が許容しているよりもずっと厳格な形式になっている事を期待している物があるということです。以前のバージョンのFirefoxや、Microsoft WindowsのZIPサポート(訳注:圧縮フォルダ)、WinRAR、UNIXのZIPアーカイバなどは、私の最適化されたjarファイルを受け付けてくれますが、7-Zipや壊れたアンチウィルスソフト(スキャン対象を無闇矢鱈に限定する事はセキュリティ上危険です)はこれらを開く事ができません

豆知識:これは、受け付けるZIPファイルの内容を選り好みするソフトウェアのせいで困らされた最初のケースではありません。例えば、Android標準のAPK読み込み処理は、Android用のパッケージが0バイトの大きさの項目を含んだZIPファイルである場合に、いちいちしつこくそれを警告してきます。これは、APK形式のファイルをWindowsにおける自己解凍形式のEXEファイルのように使う事ができないということです。Michael Wuはこの問題を解決するための独自の読み込み用ライブラリを書いている所です。

最適化その4:さらなるomnijar

omnijarは十分に素晴らしいとはまだ言えないということで、Michael Wuはさらに先に進んで拡張機能をomnijar化しました(訳注:アドオンがXPIのままで認識されるようになった事を述べたエントリ)。ほとんどの拡張機能はXPIから裸のファイルに展開される必要が無くなる事でしょう。これは、拡張機能の作者が上記のような最適化されたjar形式を、Firefoxの起動を高速化するために利用できるという事を意味します。

その他のjarファイルの最適化

起動処理の高速化用のキャッシュをjarに切り替える事によって、私達は最初の起動処理をさらに最適化できるようになることでしょう。私が最適化されたjarファイルに加えた先読み用の情報を実際に利用する事によって、jarファイルのI/Oを半減できる可能性もあります。

元記事に寄せられたコメント

Benによるコメント(2010-09-23 05:32pm)

2点だけ:

1つ目。あなたがどのように言おうと、これらの「最適化された」jarファイルはもはやZIPファイルではありません。仕様は非常に明確で、インデックスはファイルの末尾になくてはなりません。

あなたがやった事に間違った点はありませんが、しかし、それらのファイルをZIPであるかのように偽ろうとした上で、ZIPを扱うアプリケーションがそれらに対して文句を言わないようになる事を望むというのは、良い事ではありません。それよりもあなたは、最適化されたファイルの拡張子を変更することにして、最適化とその解除を手動で行うためのツールを提供した方がよいでしょう。

私は、例えば7-Zipは仕様に対して非常に厳格に設計されているがために、これらのファイル形式をサポートする事はあり得ないだろうと確信しています。

2つ目。私はFirefoxのコールドスタート(訳注:キャッシュ等にファイルが読み込まれていない状態からの起動)が(特に他のブラウザと比べて)遅いということを体感して、少し調べてみる事にしました。新規作成したプロファイルであってもまだ起動は遅かったです。私は、Firefoxは起動時に18個ものDLL(それらは全て、Firefox/Minefieldのインストール先ディレクトリに置かれています)を読み込んでいるという事に気がつきました。これは非常に良くない事で、ファイルの数の問題だけでなく、Windowsではセキュリティ対策ソフト(既定の状態であればWindows Defender、大抵の場合は何らかのアンチウィルスソフト)においての問題もあります。

私のマシン上では、ファイルのスキャンは1つあたりだいたい50ミリ秒を要していますが、この処理時間はファイルサイズには影響を受けません。Firefoxの場合、起動に数秒を要してしまいます。セキュリティ対策のソフトが大抵の場合は必要が生じた際の動的なスキャンの結果をキャッシュしていて、再起動されるか定義ファイルが更新されるまでの間は再スキャンが行われないために、この問題がウォームスタート(訳注:ファイルがキャッシュ等に読み込まれた状態からの起動)の場合には起こらないという事には注意して下さい。

いくつかの他のブラウザは、起動時にDLLを2つだけ読み込んでいて、他は必要が生じた時(動画の再生、WebGLを使う場合など)に動的に読み込んでいます。これはFirefoxの場合よりもずっといい具合に動作しているように思われます。

検索してみた所、私はLinuxについてのこの件に対するバグをいくつか見つけましたが、Windowsについてのバグは見つかりませんでした。それらが1つの大きなDLL(xul.dll)とそれ以外の小さなDLL(それらは無条件に読み込まれる)となっているので、全てを1つのファイルにまとめるのは理にかなっていると思います。

Taras Glekによるコメント(2010-09-24 09:06am)

Ben、あなたが注目した多数のDLLを提供している点についてはあなたの指摘は的を射ています。それについてのバグは https://bugzilla.mozilla.org/show_bug.cgi?id=561842 です。残念ながら、私達はこの作業をFirefox 4のリリースには間に合わせられませんので、後のリリース版で反映される事でしょう。

私はアンチウィルスソフトが起動時の処理に与える影響についても、より詳しい情報を得たいです。

ワークライフバランスの前提にある幸福観 - Oct 02, 2010

1つ前の話から一転してネガティブな話。

1つ前の話もそうだし、これらのエントリを見ても「うんうんそうだよなあ」とか「そうあるべきだよなあ」とか思うんだけど、これって何を以て「幸福」と考えるか次第で全然変わるんだよなあとも思う。

少なくとも今の僕は、メキシコの漁師とMBAホルダーのアメリカ人旅行者のジョークではメキシコの漁師の方に肩入れする。するんだけど、でも、このジョークで省略された事、「楽しい職場」の話で意図的に無視されている事についてちょっと考えてしまった。

メキシコの漁師も、楽しい職場で働く人も、「日々の収入はそんなに多くなくてもいい、自分が食って行ければそれで十分だ。だから毎日を楽しく暮らしたい。」という事だと思う。でもその前提には「毎日を楽しく暮らすためには、毎日働き続けなければならない」という事がある。もっと言うと、「今まで通りに働けなくなったら一気に幸せが失われる、そういうリスクを負わなくてはならない」という事だ。

例えば僕の場合、労働力を提供できなくなると、会社にはいられなくなるだろう。ブラック企業だろうがホワイト企業だろうが、労働力を提供することで対価を受け取るという形の働き方をしている限り、これは変わらない。交通事故で両腕を失ったら? 筋ジストロフィーとかそういう病気になったら? あるいはもっと単純に、歳を取って新しい物を覚えられなくなって受託開発でやっていけなくなってしまったら?

株の自動的な売買によって、自分は寝ててもどんどん金が増えていくとか、自分は意志決定だけすればよくてそれ以外の雑務は全部平社員に任せるとか、そういう「働かなくても金が手に入る」仕組みを構築する(「金持ち父さん」にはそういう話があったと思う)と、そういうリスクから解放される。逆に言うと、そういうリスクから解放されたければ、労働力を金に換える以外の方法で金を手に入れる手段を確立するしかない。黙々と手を動かしていればいいというような頭を使わない人間でいては、その域に達することはできない。大学で学ぶなり何なりして必死で高度な知識を身に付けないといけないかもしれないし、あるいは、持って生まれた頭の良さというものがないといけないのかもしれない。

そういう才能がない人は、前述のリスクを避けられない。才能を持って生まれることができなかった人、高度な知識を身に付けるための努力ができそうにない・そんなの無理だって言う人は、賭けに出る勇気もない人は、もう「諦める」しかない……だから「不労所得でウハウハなんて生活はどうせ自分には手に入らないのだから、スッパリ諦めて、せめて毎日を楽しく生きられるようにしよう。今と同じように働ける間くらいは。」という「身の程をわきまえた幸福観」が、ワークライフバランスとか楽しい(しかしそんなには儲からない)職場環境とかそういうものが支持される理由なのかな、と思った。

職場環境 - Oct 02, 2010

最近、僕は「自分って幸せだなあ」と思うことが多いです。このエントリでは、仕事の面におけるその理由を考えてみたいと思います。

さて、僕は今の職場環境が気に入っている。給与面で自分は不満を感じていないし、空気も好きだ。要するに幸せだと、自分の主観では思ってる。

須藤さん(現社長)は就活?の時にGoogleやはてなを見学して、ブースに区切られた上でヘッドホンまでしてるような環境を見て「こういう所では働きたくないなあ」と思ったらしい。

僕は最初はその話に正直ピンと来なかったんだけど、分からない事や知らない事で困った時に「教えて」と気軽に訊きあったり、変数名の付け方に困った時や機能の切り分け方・設計方針に迷った時に「どっちがイイと思います?」とアドバイスを求めたり、作業内容と全然関係無いどうでもいい話(本当にどうでもいい話)をしたり、というのが当たり前(会議の時だけそうするんじゃなくて、常時そう。だから栃木にオフィスを開設するにあたっても、テレビ会議のシステムを常時動かしっぱなしにしておいて、画面の向こうに向かって「ちょっと、池添さーん」と呼びかけられるようにしておこう、という風な話になった。)の今の職場環境に慣れてくると(東京に来てから結構長い間お客さんの所に半常駐だった時期があって、クリアコードの方にずっといるようになったのは途中からだった。半常駐だった所は個々人のブースが別れていたし、ヘッドホンしてる人もいて、どちらかというと前述のGoogleに近い感じだったんじゃないかなと思う)、須藤さんの言っていたことがどういう事だったのかが、なんとなくこういう事なのかなあ、という感じで分かってきたような気がする。

端的に言うと、今の自分が「個々人の席がブースで区切られてて、ヘッドホンで耳を塞いでる人もいたりして」という環境に放り込まれて「仕事をしろ」と言われた時に、やっていける自信がない。精神的負荷で潰れるとかじゃなくて(それもあるかもしれないけど)、自分にはそれでは何もできないんじゃないかって思う。IP unreachableな環境に置かれた時に、GoogleもWikipediaもMDNMXRも何も無い環境では右も左も分からないよ!という風な感じで。

須藤さんや池添さんはよく、「自分達は間違いをどうしても犯してしまう残念な人達なんだから、間違いが起こったり、一人ではうまく行かなかったりする前提でいた方がいい」という感じの事を言っている。だから、リポジトリへのコミットの単位は短くするし、自動テストも書く。1人だと煮詰まるから、些細な事でも相談する。2人でも煮詰まるから、相談してる人同士の横から割り込んで意見を言ったり言われたりもする。僕はずっと、そういう環境で自分の残念な部分を他の人に大いに補ってもらいながら作業していて、そのおかげで自分の能力以上の成果(=会社にとっての売り上げ)が出てきたと思っているから、今更1人でやれと言われても心細くて仕方がない。

Googleのような職場環境は「他人に頼るより自分でやった方が早い」とか「他人と関わらずに1人でやった方が能率が上がる」とかそういうタイプの人でなければ、少なくとも、自分がそういうタイプだと自信を持っている人でなければ生きていけない環境なんじゃないのかなーと思う。学者タイプとか研究者タイプとか。誰にも邪魔されずに作業することで最高のパフォーマンスを発揮して素晴らしい製品を生み出す、という人のための環境なんじゃないのかと思う。

翻って自分は、残念な人間だ。物覚えは悪いし知らないことだらけだし頭の回転も遅いし発想力もない。だから独創的な製品を生み出すことはできないと思う。できるのは、自分の中から湧き出てくる物でお金を儲けることではなく、自分が知ってる複数の世界の間の非対称性を埋めることで労働の対価を得る事だけだと思ってる。

この辺の話を見ても、僕は(この1点だけを見たら)elm200氏よりも小飼弾氏の話の方にシンパシーを感じる。

自分が今いる環境に順応した結果としてそう思うようになって、自分が今いる環境に対して問答無用で快感を感じるように自分の精神構造が自己調整された結果だ、という事も考えられるんだけど、とりあえず今は、「自分は元々そういう性質の人間だった」「それにピッタリ上手くハマる環境に収まることができた」という事だと考えておこうと思う。そう考えていた方が自分の主観的には幸せでいられるので。

あ。僕がこう思ってるからって、弊社の他の人がどう思ってるかは分かりませんよ。当たり前ですけど。

あと、このエントリの主題は僕1人のトピックとしては「僕は今いる環境が好きです、Googleはイヤです」だけど、一般化すると「人は自分に合った環境にいることが幸せなのだ、世間で素晴らしいとされている環境が誰にとってもフィットするというわけではないのだ」という話だと僕は思っております。

デフォルメが下手なのは、見る目が無いって事なんだよね、何事に対しても。 - Oct 02, 2010

ちびキャラっていうんですか? なんて言うのが妥当なんだろう、まあ、デフォルメされたキャラクターのこと。

4コママンガとか描く時って、コマが小さいじゃないすか。だからリアルな頭身のキャラクターだと描きにくい。デフォルメされたキャラクターにせざるを得なくなる。商品のPOPに描く時もそんな感じ。だけどそういう時の自分の絵が嫌いで嫌いで仕方ない。そういう時のデフォルメされたキャラクターをかわいらしく描ける人が羨ましくて仕方がない。昔から。

この2つを見て瞬間的に、R-Styleの方には嫌悪感を覚えた。ねんぷちの方は素直に「可愛いなあ」と思うのに。それは何故なんだろう、という事を考えたんだけど、なんとなく上記の話による同族嫌悪なんじゃないかなあと思った。

R-Styleの商品写真の唯(センターで黒いタイツはいてるキャラ)の脚がエロいと思うんですよ。僕がデフォルメされたキャラクターを描こうとしてもやっぱり脚をエロく描いてしまうと思うんですよ。エロい脚を描こうと思うとこのくらいの頭身が限界になるんじゃないかと思う。少なくとも僕の表現力ではそう。これ以上頭身が下がった状態で、僕にできる表現で脚をエロくすると、多分すごく変になる。だから頭身をこれ以上下げられない。

じゃあエロくしなきゃイイじゃん、って話ですよ。特定の特徴を強調してそれ以外の情報を省くのが「デフォルメ」なんだから、「かわいさ」を強調したいならそれ以外は省けばいいわけですよ。理屈ではそう。でも僕にはそれができないのですよ。

「かわいいもの」を描かなければいけないのに、「かわいさ」以外の要素をそぎ落とさなければならないのに、エロいものへの欲求を捨てることができない。その結果、「かわいい」以外の余計な物である「エロい」の臭いをプンプン漂わせたイヤな絵になってしまう。デフォルメの過程で「可愛い」以外のディティールを省こうとしてそこに「エロさ」が残ってしまったから、「かわいい」だけでなく「エロい」まで無駄に強調されてしまう。なんとグロテスクなんだろう。僕は僕が描いたデフォルメ絵を見るとそう感じずにはいられない。

思えば僕は昔から、余計な物を省くのが苦手だった。特徴を抜き出してそれ以外のディティールを省くのがコツである所の「似顔絵」というジャンルも、陰影を強調して影の中のディティールを真っ黒に塗りつぶしてしまうような絵も、昔から僕にはできていなかった。

絵以外でもそうだ。部屋の中には「今は使ってないけど、いつか使うかもしれないし……」という物がどんどん増えていくし、プログラムを作ればあれもこれもと詰め込みたがるし、味噌汁を作ればあれもこれもと野菜をブチ込みたがる。取捨選択ができないんだ。何が大事で何が大事でないのかが分からないんだ。物事の要点がどこにあるかが分かってないんだ。審美眼のない、焦点がぼやけた、とてもつまらない人間だと自分で思う。

センスが無いんだよね。一言で言うと。

僕がアサノさんのことを「すげえなあ」と思うのも、このへんが大きな理由なんじゃないかなと思う。

omni.jarを展開してデバッグした話と、Minefield(Firefox 4)で起動時のセッション復元が働かなくなる問題について - Sep 27, 2010

最近のMinefieldのナイトリービルドで、ツリー型タブがあると前回終了時のセッションが復元されない(タブのタイトルだけ復元されて実際には空のページになる)という現象が起こっている。この問題の原因の究明のためにずいぶん遠回りをした。

  • 最初は、SSTabRestoringやSSTabRestoredイベントを監視してる所が悪いのかと思った。なのでツリー型タブのイベントリスナの所をコメントアウトしてみた。しかしそれでもまだ問題が起こる。
  • Minefieldの方が壊れてるのか?とも思ったけど、ツリー型タブを無効にしたら問題なくセッションが復元される。なのでどうもやはりツリー型タブが悪いみたい。

こういう時は、処理がどこで止まってしまっているのかを特定するのが僕が知ってる唯一の(そして多分一番ストレートな)原因調査の仕方だ。今回だったらセッション復元が止まってしまってるので、nsSessionStore.jsの中に沢山デバッグ用のdump()を埋め込んで、どこの時点でおかしくなっているのかを調べるという事になる。

が、Minefieldではそれが一筋縄ではいかなくなってた。

構成ファイルのほとんどを1つのアーカイブの中に入れてしまうというomni.jarという変更が反映されて、今までだったらcomponentsフォルダの中にそのまま置かれていたnsSessionStore.jsも、omni.jarの中に格納されている。なので上記のような調査法を取ろうとすると、omni.jarの中にあるファイルを書き換えないといけない。

ところが7-Zipではこのomni.jarを開くことができない。多くの場合、jarファイルはただのZIPアーカイブなので7-Zipのファイルマネージャで開いて中身を編集→再圧縮ということが簡単にできるんだけど、omni.jarの場合はアーカイブ自体が壊れていると判断されてしまって中身を見ることすら適わない。

検索してみたら同じようなことで悩んでる人が他にもいたみたいで、リンク先に書かれてる情報によるとExplzhを使えばomni.jarを開けるらしい。

ということで早速Explzhを入れてみた。Explzhでomni.jarを開いてみると、確かに中身を見ることができる。しかし、中にあるファイルを編集してエディタを終了すると、omni.jarの再圧縮に失敗してしまう。ファイル名を変えるとかファイルを1個だけ削除するとかするとなんとか編集後のファイルをアーカイブに含められたんだけど、その状態でMinefieldを起動すると、ファイルが部分的に読み込めなくなってウィンドウの背景が透明になってしまうとかの謎なトラブルが発生してしまった。Explzhでもomni.jarを部分的に変更しようとすると駄目みたいだ。

追記。Windows XP以降の「圧縮フォルダ」機能でもomni.jarを展開できるらしい。圧縮フォルダなんて微妙に不便だから使ってなかったのに、こんな所で役に立つとは……

まとめると、トラブルが起こらないようなomni.jarの編集方法は、こう。

  1. omni.jarを作業フォルダにExplzhで展開する。
  2. 必要な変更を行う(デバッグ用のコードを埋め込むなど)。
  3. 展開されたファイル群を7-Zip等でZIP形式で圧縮する。
  4. ファイル名をomni.jarに変更する。
  5. 4で作ったomni.jarで、Minefieldのomni.jarを置き換える。
  6. %localappdata%\Mozilla\Firefox\Profiles\プロファイル名\ の中にあるキャッシュファイルを消す。

この方法で、Minefieldが正常に起動する状態を保ちながらomni.jarの中にあるファイルに変更を加える事ができた。

nsSessionRestore.jsに大量のdump()を入れて調べてみた所、最初のタブ(現在のタブ)の復元が終わった後で次のタブを復元する時に、すぐに処理が終わってしまっていた。さらによく調べると、復元対象のタブを決定する時にもしタブのセッション情報の_tabStillLoadingというフラグがfalseになっていたら(=タブのセッションが復元完了していたら)、そのタブをセッションの復元対象から除外するという設計になっていた。

_tabStillLoadingというフラグには見覚えがあったのでツリー型タブのソースを検索し直してみたら、別のバグの対策でこのフラグを敢えてfalseにするような処理を入れていて、これが誤爆しているせいで上記の問題が起こっているようだった(本当はそのタブはまだセッションが復元されていない・読み込み中の状態なのに、_tabStillLoadingfalseにセットされてしまうため、タブがセッション復元の対象から除外されるようになってしまっていた)。

まとめると、こういう事だった。

  • Firefox 4 の最適セッションリストア原文)で行われた変更で、ブラウザ起動時のセッション復元が、すべてのタブを一度に復元するのではなく、3個ずつ復元するように変更された。
  • その時、まだ復元が完了していないタブがいつまでも「読み込み中」の状態に見えてしまうと格好が悪いので、タブの要素のbusy属性を取り除いて、一見すると既にタブの復元が完了しているかのように見せるようになった。その代わり、まだタブの復元が必要であることを示す_restoringというフラグをbrowser要素の方に立てるようになった。→Bug 602555でリファクタリングされて、また仕様が変わった。前述の「_restoringのフラグが立っている状態」に相当するのは「browser要素の__SS_restoreState1の時」になった。
  • ツリー型タブは、タブのbusy属性だけを見て、そのタブが読み込み完了しているかどうか・セッション復元中かどうかを判断して、読み込みが完了していると判断したタブのセッション情報の_tabStillLoadingを強制的にfalseにして、タブの読み込みが完了しているとnsSessionStoreに認識させるようにしていた。
  • そのため、Minefieldでは「一見すると読み込みが完了しているように見えるが、内部的にはまだセッション復元が完了しておらず読み込み中の状態である」タブまでもがツリー型タブによって「内部的にも読み込みが完了した状態である」という扱いになるようになってしまっていた。よって、タブのセッションが復元されないという現象が発生してしまっていた。

別のバグの対策用のコードの条件分岐にもうひとつ条件を足して、「一見すると読み込みが完了しているように見えるが、内部的にはまだセッション復元が完了しておらず読み込み中の状態である」というケースを判別するようにしたら、この問題は起こらなくなった。同じコードを他にもいくつかのアドオンで使っていたので、それらも合わせて修正しておくことにした。もし同じ事をやっている人が他にもいたら、十分気をつけて欲しい。

アドオンマネージャの歴史 - Sep 22, 2010

History of the Add-ons Managerのオレオレ翻訳です。誤訳がありそうですが気にしません。


Firefox 4用の新しいアドオンマネージャのために行ってきた作業を通じて、これは興味深い話題だろうと思ったので、Firefoxのアドオンマネージャについてのこれまでの歴史と今後についてざっとまとめてみました。

Phoenix 0.2

Firefoxの最初期のバージョンにおいても、拡張機能は古いXPInstall形式のパッケージの仕組みを用いてサポートされていました。拡張機能の削除や無効化のための仕組みがFirefox自体に含まれていなかったため、これらの初期のアドオンマネージャは根本的な部分でいくつか問題がありました。また、あなたが初めてアドオンをインストールした後に目にするような拡張機能マネージャのウィンドウもありませんでした。拡張機能とテーマの一覧がFirefoxに初めて追加されたのはバージョン0.2の時で、その頃はこの製品はPhoenixと呼ばれていました。それは非常に基本的なUIで、設定ウィンドウの中に表示されていました。

(Phoenix 0.2の「拡張機能」のスクリーンショット) Phoenix 0.2の「拡張機能」(2002年)

Firebird 0.6

製品がFirebirdという新しい名前を得た後、拡張機能マネージャは設定ウィンドウ内の「テーマ」と「拡張機能」という個別のペインとして生まれ変わりました。

(Firebird 0.6の「拡張機能」のスクリーンショット) Firebird 0.6の「拡張機能」(2003年)

Firefox 0.9

Firefox 0.9ですべてが変わりました。拡張機能マネージャは個別のウィンドウとなり、今日こんにち使われているアドオンのパッケージと原則的に変わらない、新しいinstall.rdfパッケージが導入されました。

(Firefox 0.9の拡張機能マネージャのスクリーンショット) Firefox 0.9の拡張機能マネージャ(2004年)

テーマと拡張機能はそれぞれ別々のウィンドウで表示され、基本的な自動更新のための仕組みが搭載されました。これらはFirefox 1.0に向けたバックエンドのコードにおいて改良されることになっていました。この最初のバージョンは主にBen Goodgerによって書かれました。

Firefox 1.5

Firefox 1.5では拡張機能マネージャの表面的な部分について、ほんの少しだけ違いが見られます。このバージョンではFirefoxの他の部分の外観のスタイル付けに合わせるためにごくわずかな変更が行われました。

(Firefox 1.5の拡張機能マネージャのスクリーンショット) Firefox 1.5のスクリーンショット(2005年)

この舞台裏で、Darin Fisherは大きな変更を行いました。彼は拡張機能マネージャに対して、Windowsのレジストリを含む、システム上の異なる場所から拡張機能を読み込むことを可能にしたのです。彼はまた、拡張機能をプロファイルフォルダ内に抽出することを可能にし、次にFirefoxが起動された時に自動的にそれらを認識できるようにもしました。この時、リリースに向けて拡張機能マネージャを安定させるために、Rob Strongがモジュールオーナーの権限を引き継ぎました。また、このバージョンには拡張機能マネージャに対する私(※訳註:原文の著者のDave Townsend氏)の最初のパッチも含まれています――bug 307925においての物で、ごく小さな物ですが。

Firefox 2.0

Firefox 2.0では最終的に、分割されていた拡張機能とテーマのウィンドウが一つのアドオンマネージャに統合されました。

(Firefox 2.0のアドオンマネージャのスクリーンショット) Firefox 2.0のアドオンマネージャ(2006年)

水面下では、ユーザにとって危険と判断された拡張機能をMozillaの手で外部から無効化する事を可能にするためのブロックリスト機能の最初のバージョンを含む、さらに多くの変更が行われていました。この機能が作られて以来、私たちはこの機能を本当にごく希にしか使っていませんが、セキュリティ上の弱点やクラッシュを防ぐ際の助けとなってきました。

Firefox 3.0

Firefox 3において、私たちはプラグインをアドオンマネージャの中に含めるようにし、また初めての利用において皆さんがアドオンマネージャを使ってaddons.mozilla.orgからアドオンを直接ダウンロードしてインストールできるようにしました。これは私(※訳註:原文の著者のDave Townsend氏)がFirefoxにおいて作業した最初の大きな機能で、この機能がどれだけ使われているかをアドオンチームから聞く度に、私はいつも非常に嬉しい気持ちになります。

(Firefox 3.0のアドオンマネージャのスクリーンショット) Firefox 3.0のアドオンマネージャ(2008年)

内部的には、ブロックリスト機能はプラグインをブロックできるように拡張され、Windows以外のプラットフォームにおいてもシステム上の他のアプリケーションとの連携に対応するためにインストール対象となるファイルの置き場所が新しく追加されました(※訳註:bug 311008)。

Firefox 3.5と3.6

Firefox 3.5と3.6においては視覚的な変更点は全くありませんでしたが、Firefox 3.5ではブロックリスト機能がいくつかの異なる重要度のレベルに対応できるように再度改良され、Firefox 3.6ではシステム上にあるアップデートが必要なプラグインについてユーザに警告を行う機能への対応に加えて、Firefoxのメインウィンドウの単調な背景を簡単に切り替えられるようにする、産まれたばかりのペルソナがアドオンマネージャに搭載されました。

Firefox 4.0 beta

Firefox 4では、再起動が不要な拡張機能への対応の追加や、ユーザの操作をより妨げない自動的な更新のための仕組み、そして新しいアドオンに出会うためのより便利な方法などを含む、アドオンマネージャの全面的な再設計が見られます。

(Firefox 4 betaのアドオンマネージャのスクリーンショット) Firefox 4 betaのアドオンマネージャ(2010年初頭)

裏側においては、新しいアドオンマネージャは新しい種類のアドオンを、これまでよりもさらに簡単に管理できるようになっています。

Firefox 4.0

ユーザ・エクスペリエンスチームは、Firefox 4のリリース版でアドオンマネージャがどのように見えるようになるかの最終的なデザインを作成するために、一生懸命働いています。あくまで仮の物ですが、これは彼らが行おうとしていることのスケッチです:

(Firefox 4最終版用に検討中のデザインのスクリーンショット) Firefox 4最終版用に検討中のデザイン(2010年末頃?)

将来的に、私たちはさらに多くの種類のアドオンをこのマネージャの中に持ち込むことを計画しています。現在はそれ用の独自のウィンドウで管理されている検索プラグインなどのような物は、ここにうまく収まるでしょう。また、私たちは皆さんが拡張機能をより単純な形でカスタマイズするようにしたいとも考えています。可能性は低いですが、私たちは拡張機能の開発者達に対して、独自の設定ウィンドウを作る事を許容するのをやめて、新しいウィンドウを開くことを必要とせずに、単純な設定をアドオンマネージャの中で直接変更できるようにする機能を加える事を検討しています。私たちは、皆さんがインストール済みのプラグイン――それは時にセキュリティ上の問題や、安定性を損なう問題の元になります――を自動的に更新する方法を実現できたらと考えていますし、テーマの選択について、どんなテーマが利用可能かを見たり、それらを切り替えたりするのを、より簡単に行えるよう大幅な改良を行いたいとも考えています。

これらのことのうちのいくつかはFirefox 4.0までの時間で実際に行われるかもしれませんが、最終的なリリースの前に新しい物を取り入れるには、時間は残り少ないです。

DOM要素に対して起こったイベントのロギング - Sep 17, 2010

transitionendをトリガーとしてタブを閉じる処理が完了されるはずなのに、それが実行されなくて閉じられないタブが残ってしまう問題について、実際にどのアニメーションが成功したのか・失敗したのか、何がトリガーになっているのか、というのをデバッグしたかったんだけど、「閉じられないタブ」が発生した後からそれを調べる方法がなかったので、じゃあ先にログを収集しておこうという事でこういうコードを書いてみた。

var startDOMLogging = function(aElement) {
      var log = aElement.DOMLog = Array.slice(aElement.DOMLog || []);
      aElement.addEventListener('DOMAttrModified', function(aEvent) {
        if (aEvent.originalTarget != aEvent.currentTarget) return;
        log.push({
          type      : aEvent.type,
          attrName  : aEvent.attrName,
          prevValue : aEvent.prevValue,
          newValue  : aEvent.newValue,
          timeStamp : Date.now()
        });
      }, false);
      aElement.addEventListener('transitionend', function(aEvent) {
        if (aEvent.originalTarget != aEvent.currentTarget) return;
        log.push({
          type         : aEvent.type,
          propertyName : aEvent.propertyName,
          elapsedTime  : aEvent.elapsedTime,
          timeStamp    : Date.now()
        });
      }, false);
    };

gBrowser.tabContainer.addEventListener('TabOpen', function(aEvent) {
  startDOMLogging(aEvent.originalTarget);
}, false);

DOM InspectorでJavaScript Objectを表示してSubjectのEvaluate JavaScriptで alert(JSON.stringify(target.DOMLog)) とすれば、そのDOM要素で何が起こっていたのかが分かる。

エラーコンソールとかデバッグ系のツールで最初からこういう事ができるといいのにね。UxUにそういうユーティリティを追加してみようかな。

タブバーをドラッグしたらウィンドウが動くとかその辺のタイトルバーっぽい挙動を無効化する - Sep 15, 2010

ツリー型タブではタブバーをウィンドウの横に置く使い方を基本的には想定してるワケだけれども、普通にタブバーを縦型にするだけだと、Minefieldではタブバーをダブルクリックしたらウィンドウが最大化されるという謎の結果になってしまうことがある。

MinefieldではBug 555081で行われた変更により、ツールバーの空白の部分がウィンドウのタイトルバーと同じ扱いになるようになっている。ツールバーの空白部分をドラッグすればウィンドウが動くし、ダブルクリックすればウィンドウの最大化になる(Windowsの場合)し、ぴたすちおのようにタイトルバーを右クリックしたらウィンドウシェードするようなユーティリティを使っていれば、それも動く。

ただ、ウィンドウの横に移動されたタブバーのようにぱっと見ツールバーに見えない部分までもがこのような挙動になってしまうと、違和感があるし混乱の元ではある。また、ツリー型タブの場合はタブバーの空白の領域をドラッグするとタブバーの位置を変えられるという機能があるけれども、上記の通りの仕様なのでこのままではタブバーの位置を変えられないということにもなってしまう。こういう時、どうすればいいのか。

タイトルバーのように振る舞うツールバーの挙動は、chrome://global/content/bindings/toolbar.xml#toolbar-drag で定義されている。コードを見てみると、WindowDraggingUtils.jsmというモジュールを読み込んで自分自身をWindowDraggingElementという物に登録しており、こうして登録された要素がタイトルバーのように振る舞うようだ。じゃあこの初期化処理を無効化するか初期化処理で行われた結果を取り消してやればいいんじゃないか、と思ったけど、設計的にそれは無理だった。

仕方がないのでWindowDraggingUtils.jsmの方を見てみると、「タイトルバー上にあるボタン等をドラッグした時だけは上記のような動作にしないようにする」というのをどうやって実現しているのかが分かった。

  • Windowsでは、マウスのボタンが押下された時にMozMouseHittestというイベントが発行されている。
  • 任意で登録された関数(mouseDownCheck)がfalseを返した時か、クリックされた要素からその祖先までの間にドラッグ操作を受け付けそうな要素がある時は、preventDefault()している。
  • preventDefault()された場合、マウスのボタンがそもそも押下されなかったという扱いになるみたい。

端的に言うと、MozMouseHittestイベントをpreventDefault()すれば、ツールバーのタイトルバー的な振る舞いを無効化することができるということのようだ。

gBrowser.tabContainer.addEventListener(
  'MozMouseHittest',
  function(aEvent) {
    aEvent.preventDefault();
  },
  true
);

ただ、タブバー内で発生するMozMouseHittestイベントを常にpreventDefault()してしまうと、タブをクリックしてもタブが切り替わらないということになってしまう。preventDefault()するのは祖先要素にタブまたはクリック可能な要素が無い場合だけに制限しないといけない。

Minefield 4.0b6preでXUL要素とiframeの重ね合わせが鼻血出るくらい簡単になってた - Sep 11, 2010

ツリー型タブには「ポインタがタブバーを離れている時はタブバーを隠してor縮めて、ポインタがタブバーに近づいたら(フルサイズで)表示する」という機能がある。 (タブバーがコンテンツ領域に覆い被さる様子のスクリーンショット)

Firefox 4に向けて開発が進んでいるMinefield 4.0b6preでこの機能が動かなくなっていたので修正をしよう……と思ったら根本的に作りなおさなきゃいけなかった。でも以前のやり方に比べたらずっとスッキリと実装できるようになっていた。

これはそんなお話。

これまで

Firefox 3.6までは、上記の機能を実現するのにえらく苦労していた。

tabbrowser要素の仕様変更のまとめで過去に図解したけど、今までのFirefoxではタブバーとコンテンツ表示領域が1つのボックスの中に収まっていたので、ボックスの縦横の配置を変えるだけでタブバーを「縦置き」できていた。そうして「縦置き」したタブバーの幅を自動的に増やしたり減らしたりしてやりさえすれば、最も単純な「タブバーを自動で隠す」機能は実現できる。 (一番簡単な実現方法を採った場合のスクリーンショット)

ただ、実際にはそれだと実際使っててストレスを感じる。タブバーの幅が変化する度にタブバーによって押し潰される形でコンテンツ領域の幅が縮んでしまい見た目に激しくガタつくのと、それに加えて再描画のためにFirefoxが一瞬でも無反応になってしまう事がある、というのが多分その理由だろう。

じゃあタブバーの幅が増えた分をコンテンツ領域の上にかぶせてやればガタつきがなくなってイイよね、ということで上のスクリーンショットのような事をやろうとして、当時の僕はFirefoxの仕様に頭を抱える羽目になってしまった。

ネガティブマージンでは駄目だった

要素同士を重ねる、というと一番手っ取り早いのはネガティブマージンを使う方法だろう。タブバーにネガティブマージンを指定してやれば万事解決する……そう考えていた時期が僕にもありました。

(ネガティブマージンでタブがコンテンツ領域の下に潜り込んでしまった様子のスクリーンショット) 見るも無残。

どうも現行バージョンのGeckoはインラインフレームだけ特別な描画の仕方をしているらしく、iframeやbrowserの内容はオーバーレイのウィンドウのように他の内容より前に表示されるみたいだ。browser要素がDOMツリーに尽かされた後でDOMツリーに追加されたtab要素なら、browser要素よりも手前に描画されることもあるようだけど、基本的にはこうなると思っておいた方がいい。

ネガティブマージンで駄目ならposition:absoluteやらposition:fixedやらはどうなんだ、という代替案は当然出てくるだろうけど、これもやっぱり駄目だった。browserをz-index:1に、タブの方をz-index:2にという風にやっても、どう頑張ってもタブがbrowserの下に隠れてしまった。

panelは?

panelやmenupopupを使うと、OSのレベルで別のウィンドウを開いて任意の位置に重ねることができる。影や枠を表示しないようにすることもできるから、うまくやればこれが一番確実かもしれない。

ただ、自分で0から作る場合ならともかく、Firefoxのタブを後から改変するという場合には、これは激しくお勧めできない。Firefoxのタブ周りのDOMツリーを不用意にいじると、Firefoxの本来の構造を期待して開発されたアドオンが動かなくなってしまう可能性が高いからだ。

結局どうやったのか

アレも駄目これも駄目という感じだったので、Firefox 3.6以前では結局、他のアドオンに対して与える影響が一番少なそうなやり方として、いくつかのテクニックの組み合わせでそれっぽく見せるようにしてみた。

まずタブバーの幅を普通に増やす。 (タブバーの幅が増えた状態のスクリーンショット)

それだけだとコンテンツ領域が押し潰されてしまうので、そうならないようにネガティブマージンでappcontentあたりの幅を広げてレイアウトを維持する。 (コンテンツ領域の幅を広げた状態のスクリーンショット)

次にnsIContentViewerのmoveメソッドで描画内容をずらす。このメソッドは、フレームの内容の描画位置を任意の座標分平行移動する物だ。 (描画内容をずらした状態のスクリーンショット)

仕上げとして、nsIContentViewerのmoveメソッドで描画位置を変えたせいでレンダリングされていない「タブバーと重なり合う部分」を、canvasのdrawWindowで描画する。 (canvasで半透明の効果を再現した状態のスクリーンショット) スクロールしてる場合やフルズームが使われている場合に位置をうまく合わせるのが難しいけど、なんとか頑張った。

Minefield 4.0の古いベータへの対応

ちょっと前までのMinefieldでも、基本的にはこれと同じ事をやってた。 tabbrowser要素の仕様変更のまとめで説明している通り、タブバーそのものはposition:fixedで固定して位置を合わせていて、かつてタブバーがあった所に挿入したダミーの要素と実際のタブバーとの表示サイズを同期させているという点が異なるけど、browser(iframe)とタブが重ならないように工夫を凝らしているという点では変わりはなかった。

これから

そんな感じで今までやってたんだけど、Minefield 4.0b6preをアップデートして試しに機能をONにしてみたら、上記の解決策の重要な要素の1つである「nsIContentViewerのmoveメソッドで描画内容をずらす」が効かなくなってた。 (描画内容をずらせていないためにおかしな表示になってしまっている様子のスクリーンショット)

これではタブバーの幅が変わる度にコンテンツ領域がガタついてしまうという問題を回避できない。

もはやこれまでか。そう思った僕を救ったのは、別の(ツリー型タブ)の不具合によって起こっていた現象でした。

先述の通り、Minefield用には既にタブバーをposition:fixedでレイアウトするという変更を反映してた。それが原因で、TabsToolbarの中に配置されたツールバーボタンが、タブバーが自動的に隠された状態であっても表示されたままになってしまうという現象が同時に発生していた。 (問題が起こっている様子のスクリーンショット)

……ん? ちょっと待てよ! なんでその位置にそのボタンが見えてるわけ?! browserの下に隠れてない!?

検証してみたところ、いつ行われた変更によるものなのかは分からないけど、Minefieldではいつの間にか、前述した「browserやiframeの内容は常に最前面に描画されてしまう。それらと重なる位置に置かれたXUL要素はbrowserやiframeの下に隠れてしまう。」という問題が起こらなくなっているようだ。

そこまで分かれば話は早い。もう前述のような凝ったことをしなくても、普通にposition:fixedで配置してbackground:rgba(0, 0, 0, 0.25)にすればもうそれだけで、「半透明のタブバーの下にコンテンツ領域が透けて見える」状態になるということだ。 (canvasによる再現ではない本当の半透明が実現された様子のスクリーンショット) こうしてひとまず現状のMinefieldには対応することができた。

まとめ

  • Minefieldでは、position:fixed等で任意のXUL要素をコンテンツ領域の上に重ねて配置できるようになった。ポジショニングを気軽に使えるようになった。
  • 今まで必要だった、制限の回避のための工夫は、もういらない(多分)。

いい時代になったものですね。

Page 32/248: « 28 29 30 31 32 33 34 35 36 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき