Home > Latest topics

Latest topics 近況報告

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

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

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

Page 44/248: « 40 41 42 43 44 45 46 47 48 »

横長のツリー - Oct 25, 2007

公開した後から言うのもナンだけど、横長のタブバーでツリー表示にはやっぱり無理があるよねぇ……横長の時は多段タブバー、縦長の時はツリー、というのが最強のような気がする。縦長で多数列とか横長でツリーとか、逆の組み合わせは正直言って使いにくいことこの上ない。設定UIからは削って隠し機能止まりにしといた方がよかったかも。「できる」というのと「するべき」というのとは別問題だ、ということを痛感した。

タブでソース表示 - Oct 24, 2007

View Source in Tab。その名の通り、ソースの表示をタブで行うようにするだけという物。ツリー型タブの機能として加えようとしてて、よく考えたらこれツリー関係の機能関係なくね? と思ったので別途リリースすることにした。

作り始める前に「そういえばそんな名前のアドオンがすでにあったような気がするんだが……」と思って「View Source in Tab」で検索してみたけど見あたらなかったのでそれなりに作り込んでさあそろそろ公開するか、と思ったところでふと「Open Source in Tab」で検索してみたらあっさり見つかったし

まあそれでもせっかく作っちゃったから公開しておく。一応、Open Source in TabやView Source Choiceに比べて以下の点でView Source in Tabの方が高機能ではあります。

  • 「ページのソース」だけでなく「選択範囲のソース」もタブで開くことができる。
  • 通常の「ソースを表示」ウィンドウと同じUIを持った物がタブで開かれる(Open Source in Tab、View Source ChoiceだとUIなし)ので、メニューからハイライトの機能の有効無効を切り替えたり、現在の行数・桁数が表示されたり、といった元々の「ソースを表示」機能の便利なところをそのまま使い続けられる。
  • Firefox 2のセッション保存のAPIを利用しているので、タブを閉じた後もう一度開き直しても、選択範囲まで含めてちゃんとタブが復元される。
  • ツリー型タブのAPIを利用しているので、一緒に入れとくと現在のタブの子タブとしてソース表示のタブが開かれる。
  • Firefox 2(Firefox 1.5からだったか)の隠し機能でソース表示に外部のエディタを使う機能があるけど、実行ファイルまでのパスの中に日本語が入ってるとエラーで起動に失敗するので、独自にパッチを当てて、日本語を含むパスでも問題なく外部エディタを起動できるようにした。(外部エディタを使う場合は選択範囲のソースは今まで通り内部のビューワで表示される)

でも徹底的に探したわけではないので、これで後から「実はすでにView Source in Tabという名前のアドオンがあるんだが」という風に気がついたら、もうどうしようもない。→ありました

25日追記。無難なところで「Source Viewer Tab(ソース表示タブ)」に改名しておきました……

ツリー型タブのAPI(他のアドオンから「子タブ」を開く方法) - Oct 22, 2007

ツリー型タブのAPIと称して3つのメソッドの使い方を公開しました。以下のようにして使ってください。

// 一つだけタブを開く場合
if ('TreeStyleTabService' in window)
  TreeStyleTabService.readyToOpenChildTab(gBrowser.selectedTab);
gBrowser.addTab('http://www.example.jp/');

// 複数のタブを開く場合
if ('TreeStyleTabService' in window)
  TreeStyleTabService.readyToOpenChildTab(gBrowser.selectedTab, true);
gBrowser.addTab('http://www.example.jp/');
gBrowser.addTab('http://www.example.com/');
gBrowser.addTab('http://www.google.co.jp/');
if ('TreeStyleTabService' in window)
  TreeStyleTabService.stopToOpenChildTab(gBrowser.selectedTab);

アドオンとかユーザースクリプトとかで、現在のタブに関連した情報を新規タブで開くような機能を持ってる物は、これを入れておくとユーザ(主に僕)が幸せになれると思います!

Tree Style Tab - ツリー型タブ - Oct 21, 2007

先日から作業してたものの成果がそれなりの形になったので、公開しました。

これだけでも当然使えるけど、僕としては情報化タブマルチプルタブハンドラの二つと組み合わせて使うのがお勧めだと思ってます。

実際に組み合わせて使ってる様子: (スクリーンショット)

元々、使い勝手のいいツリー表示アドオンが出てきたらそっち使う気でいたんだけど、TabKitが案外期待外れだった(←うわー言っちゃったー)ので一念発起して自分好みの物を作った。インデント幅を自動調整するようにしたとか、ドラッグ&ドロップでのタブの移動とツリー編集の挙動をIllustratorのレイヤツリー風にしたとか、TBEのタブツリーより完成度は地味に高くなってると思う。

突貫工事で作ったワリには案外ちゃんと動いてくれているなあ、というのが率直な感想。なめらかスクロールの実装やサブツリーの開閉まわりのコードをTBEからコピってきて使った箇所が少しだけあるけど、改めて今TBEのコードを見てみたら、タブのスクロール一つとってもとんでもなく面倒なことをしていたんだなあということに、我ながら改めて驚かされる。だって、普通にボックスの内容をスクロールさせるメソッドがなかったんですよ? バインディングを使って不可視のスクロールバーを取得して強引にスクロールの制御を行ってたとか根本的にバッドノウハウの塊すぎて、読み解くのも一苦労でした。あの頃から比べたらFirefoxの方でAPIを用意してくれてるところが増えてだいぶ楽になったもんです。

以下、検討事項。

  • ウィンドウをまたいだドラッグ&ドロップ……は、要望があれば考えよう。
  • ドラッグ中にタブバーの端をポイントしたら自動でスクロールするようにしたい。
  • 通常の横置きタブでも動くような設計になってはいるけど、十分テストしてなかったり、うっかり縦置きタブ用に決め打ちしちゃってるとことかあるかもだったりで、その機能は今は封印ということにしておく。ていうか自分じゃもうそんな機能使いそうにないし、やる気の度合いは非常に低い。
  • アイコンとかもうちょっとマシな物にしようよ。
  • 他の(僕が作った物以外の)タブ系アドオンとの組み合わせでちゃんと動くかどうかは知らない。要望が出てき次第対応していこう。
  • 複数リンクを選択してまとめて開く機能もこれに入れるべき?
  • Text Linkとの連携もしなきゃなぁ
  • iRiderのようにすべてのリンクを常にタブで開くモードを付ける?

タブのツリー表示がだいぶ実用的になってきた - Oct 19, 2007

一昨日から取りかかってる奴だけど、サブツリーの開閉を実装して、やっと実用的なレベルになってきた。ツリーの状態もタブセッションの情報の一部として記憶させているので、セッションをまたいでツリーを維持できるし、クラッシュした後の復帰でもちゃんとツリーが復元される、はず。

フォーカス制御やタブの親子関係の保持・取得についてはほとんど全部新規に書いたけど、ツリーの開閉関係はTBEの実装に基づいている。いやまあ、もちろんコードは新しく書き直してるんだけど、アルゴリズム(と言っていいのか?)の部分ね。

あともう一息だー

タブのツリー表示 - Oct 17, 2007

ようやく手を着けることにしました。TBEの機能を分割してFirefox 2向けに移植する作業の続きの中で一番めんどくさそうな、タブのツリー表示。Tab KitとかTab Treeとか、すでに新しくて素晴らしい物がどんどん出てきてるんだけど、まあ、マイペースで行くことにします。

(現状のスクリーンショット) サムネイルは情報化タブのもの。タブの縦置きは現在はVertigo任せ。公開版ではもちろん自前で縦置きするようにする予定だけど、今は「ツリー表示」のための部分に集中して開発するために敢えて放置してる。

親子関係の構築にあたっては、TBEでは「タブを開く」処理を乗っ取って引数でゴチャゴチャやってたんだけど、Tab Treeの発想が物凄くシンプルだったので、試しにそれベースで実装してみている。

TODO(優先順位が高い物から順に):

  1. targetwindow.open()で開かれたタブも親子関係の中に組み入れる→実装した
  2. タブを閉じた時の、次にフォーカスするタブの制御→実装した
  3. タブの親子関係をセッションをまたいで保持する(開き直したタブについても親子関係を自動的に復元する)→実装した(多分)
  4. ツリーの折り畳み→実装した
  5. 畳まれたツリーを閉じたら子孫のタブも全部閉じる→実装した
  6. 開かれたツリーで親のタブを閉じたら、子孫のタブのレベルを一つ繰り上げる→実装した
  7. Windowsエクスプローラのツリーのような自動開閉→実装した
  8. マルチプルタブハンドラとの連携(畳まれたツリーに対応するために特別な処理を書かないといけない)→実装した
  9. 畳まれたツリーについて、子孫に含んでいるタブの数を表示する→実装した
  10. ドラッグ&ドロップでの、ツリーの動的な変更→実装した
  11. タブの縦置きの自前提供(動的な幅変更も含む)→実装した
  12. タブを右に表示する機能→実装した
  13. インデント幅の設定機能→実装した:ユーザがいちいち人力で変更するなんてあほらしいので、インデント幅を自動調整するようにした(初期値は変更可能)
  14. 画面外にタブが開かれた場合の自動スクロール→実装した
  15. ウィンドウをまたいだタブのドラッグ&ドロップ

TBEに存在した、別のドメインのページを読み込んだ時にタブの親子関係を自動的に破棄するとかの細かい部分については、実装してみてはいたものの自分が使ってる限りでは全然役に立ったことがないので、サクッと省略の方向で。

XULのtoolbarbuttonとCSSのopacityとpositionで嵌った - Oct 12, 2007

昨日XULとCSSであれこれ頑張ってみていて浮き彫りになってきた、XULとCSSのバッドノウハウの話の続き。

前のエントリで書いたことを踏まえて、toolbarbuttonの中のlabelを、XBLとstackを使って影付きテキストに置換するということをやってみたんだけど、そうすると今度は、ボタンを押しても何も反応しなくなってしまったじゃあないですか。こりゃ大変だ。

よーく観察してみると、ボタンのラベル文字列の部分はクリックしても無反応(ボタンの外観はちゃんと「押した」風になるんだけど、commandイベントが発行されない。コードを色々書き換えてみたけど、clickイベントすら発行されなかった。)だけど、それ以外の部分――ボタンの枠線とラベル文字列の間の余白部分あたりをクリックすると、ちゃんとボタンを押したものと認識される、ということに気がついた。ということはやっぱり、stackを使って影付きテキストにしたlabel要素が癌だってことだ。

んで条件を変えつつ色々試してみたら、以下のことが分かった。

  • 半透明にしたlabel要素をクリックしても、親のボタンをクリックしたとは見なされない。
  • 半透明じゃなくても、positionがstatic以外になっているlabel要素は、クリックしても、親のボタンをクリックしたとは見なされない。

言い換えると、「完全に不透明で、且つ、positionがstaticであるlabel要素」をクリックした時にだけ、そのtoolbarbuttonがクリックされたものとして正しく認識されるようだ、ということ。

というわけで苦肉の策として、ボタン上にポインタが乗っている時(:hover状態)はpositionもopacityも初期値(staticで不透明)にする、という風にしてみたところ、やっとちゃんとボタンをクリックできるようになってくれた。positionがstaticということはz-indexでの重ね合わせ順の制御が効かなくなるんだけど、影の方のopacityが1になればstackの原則通り内容は文書中の登場順に描画されるようになるので、トータルでは問題なくなる。:hoverの時だけ影が濃くなる(不透明になる)のは、まぁ、:hover時の特別なハイライト表示にも見えるので、結果オーライと言えよう。

ちなみに、この問題はtoolbarbutton要素だけでなく、menubar要素直下のmenu要素内にあるlabelについても起こる。こちらについても同じような対策で行けるかと思って、事実ほとんどの所はそれで良かったんだけど、:hoverの時だけということにしておくと、展開されたメニューを選択した後に再びmenuの部分にポインタを載せた時に、positionとopacityのリセット用指定が反映されないという現象が起こってしまったので、代わりに[_moz-menuactive="true"]という具合に内部処理用の属性を使ってみることにした。

そんな感じで、現行Geckoにはこういういやーなバグがまだまだ潜んでいて、案外苦労してしまうことが少なくない。そこら辺が改善された新しいバージョンっていつ出るのかなあ……

XULのstackとCSSのopacityで嵌った - Oct 12, 2007

昨日XULとCSSであれこれ頑張ってみていて浮き彫りになってきた、XULとCSSのバッドノウハウいくつか。

  1. XULのstackとCSSのopacityの微妙な関係について
  2. XULのtoolbarbuttonとCSSのopacityとpositionの微妙な関係について

まず一つ目。一般的なWebページ制作では、要素同士を重ね合わせるにはCSSのポジショニングを使うのが一般的で、XULでも同じ方法を使えるんだけど、もう一つの方法として、XULにはstackという要素がある。

通常、XULではhbox(内容が横に並ぶボックス)またはvbox(内容が縦に並ぶボックス)の2つのボックスをコンテナとして使い、縦横二方向のボックスの並びだけでGUIを作る、というのが原則となっている。この原則を覆すのがstackというコンテナ要素だ。多くのXULのコンテナ要素においては、内容に含めた要素のボックスが縦または横に並ぶのに対し、stackは、内容に含めた要素のボックスが同じ座標に重ねて表示される、という特徴がある。

チュートリアルではこれを使って影付き文字を作る例を示しているけれども、これを見て当然思いつくのが、影を半透明にして背景に自然に馴染ませたいという要求だろう。


<stack>
  <description value="Shadowed"
               style="color: black; opacity: 0.5;"
               top="1" left="1"/>
  <description value="Shadowed"
               style="color: white;"/>
</stack>

ところが、この例は実際には意図通りに表示されてくれない。Geckoのバグだと思うけど、stackの中に一つでも半透明の要素があると、stack全体が半透明になってしまうのである。つまり、ここでは影だけを半透明にしたいのに、実際には前景の文字まで半透明になってしまって却って字が読みにくくなる。

で、色々試してみた結果、stackを二重にするとこの問題を回避できるっぽい、という事が分かった。


<stack>
  <stack>
    <description value="Shadowed"
                 style="color: black; opacity: 0.5;"
                 top="1" left="1"/>
  </stack>
  <description value="Shadowed"
               style="color: white;"/>
</stack>

こうすると、内側のstackは全体が半透明になってしまうけど、外側のstackにはその影響は及ばないので、影だけを半透明にできる。(ここでは影のテキストが一つだけしかないけど、実際にはText Shadowと同様の方法で複数の薄い影をずらしながら重ねたかったということなので、stackを二重にしている。)

ただ、今度は入れ替わりに、要素の重ね合わせの順番がおかしくなるという問題が起こってしまった。XULのstackは先に入っている要素ほど下に、後に入っている要素ほど上に描画されるはずなんだけど、どういうわけか、半透明にした要素は不透明の要素よりも上に強制的に描画されてしまうようだ。

(……と思ってたんだけどもしかしたらこれは勘違いかもしれない。stack内の要素はtop属性とleft属性で場所を動かせるんだけど、もしかしたら、これらの属性がある場合は強制的にその要素がposition: relativeにされてしまって、通常のposition: staticな要素の上に表示されるようになってしまった、ということだけなのかも……これはまだ検証してない。)

そこでさらに、z-indexを使って重ね合わせの順番を指定してみたところ、やっと「半透明の影の上に不透明の文字を重ねる」という結果を得ることができた。


<stack>
  <stack style="position: relative; z-index: 1;">
    <description value="Shadowed"
                 style="color: black; opacity: 0.5;"
                 top="1" left="1"/>
  </stack>
  <description value="Shadowed"
               style="color: white; position: relative; z-index: 2;"/>
</stack>

position: relative を指定しておかないとz-indexの指定が効かない(z-indexはpositionがstatic以外の要素にしか効果がない)ので、それもセットで指定してある。

これでやっと問題を解決できたか、と思ってたんだけど、あろう事か今度はまたさらに別の問題にぶち当たってしまった。というところで、話は次のエントリへ続きます。

XPIの生成とハッシュ値の取得とRSSの生成の自動化 - Oct 10, 2007

XPIパッケージ生成用のバッチファイルとかシェルスクリプトとかを更新した。

  • プラットフォームごとのファイルを含めた拡張機能に対応。
  • 調べてみたらLinuxとCygwinには最初からファイルのSHA-1ハッシュを取得するsha1sumというコマンドがあったので、それを使って、XPIパッケージの生成時に同時にSHA-1ハッシュも出力するようにした。
  • Split BrowserのページなどのHTMLからRSSを自動的に生成(更新)する秀丸マクロについて、SHA-1ハッシュの値も取り込むように改良して、リポジトリに追加した。
  • sedを使って、Mozilla Add-ons用のXPI(updateURLとupdateKeyをinstall.rdfから削除した物)も同時に生成するようにした。

Windows用のバッチファイルはCygwinにおもくそ依存してます。Bash用シェルスクリプトは最初の行のパスさえ直せば多分他の環境でも普通に使えると思う(Ubuntu 6.06ではそのまま動いてる)。使い方は前に書いた解説を参照してください。

秀丸マクロ(Sync.macxul_updates.macxul_updates2.mac)はいずれもパスやファイルの構成を決め打ちで作ってるんで汎用性はないけど、まあ、似たようなことをやりたい人の参考になれば幸いです。(この辺もそのうちもっと汎用的なバッチファイルなりシェルスクリプトなりに置き換えたいんだけど……)

sedの使い方が少し分かってきたので、もうちょっと複雑なことができるようになりそう……かも?

Chromeウィンドウを最前面にする・最背面にする - Sep 26, 2007

Chromeウィンドウでは、window.open()window.openDialog()の第3引数でalwaysRaisedフラグを指定することで、「常に最前面に表示」状態のウィンドウを開くことができる(通常のスクリプトではこのフラグを使うには特権が必要)。じゃあ、すでに開かれているウィンドウを最前面にすることはできないのか? というのが今日のお題。

フォクすけクロックを使ってみて、Firefoxのウィンドウの下に時計が隠れてしまうのは不便きわまりないと思ったので、これをどうにかしたかった。最初は、前述のalwaysRaisedを使った方法でいけるかなと思ったんだけど、Firefoxのアドオンとして動作する時はこれでいいけどXULRunnerアプリとして動作する時には「開く元の親ウィンドウ」が無いからこれじゃダメだ、と気がついた。

んでちょっと調べてみた所によると、どうもnsIXULWindowインターフェースのzLevelというプロパティをいじることで、ウィンドウの重ね合わせの優先順位を動的に変更できるようだということが分かってきた。

以下のようにいくつかのインターフェースを経由することで、Chromeウィンドウ(nsIDOMWindow)からnsIXULWindowのインターフェースに辿り着くことができる。

var Ci = Components.interfaces;
var XULWindow = window
    .QueryInterface(Ci.nsIInterfaceRequestor)
    .getInterface(Ci.nsIWebNavigation)
    .QueryInterface(Ci.nsIDocShellTreeItem)
    .treeOwner
    .QueryInterface(Ci.nsIInterfaceRequestor)
    .getInterface(Ci.nsIXULWindow);

XULWindow.zLevel = Ci.nsIXULWindow.raisedZ;

zLevelに指定可能な値はnsIXULWindowインターフェースにおいて定数プロパティとして定義されていて、以下の種類がある。

プロパティ実際の値意味
Ci.nsIXULWindow.lowestZ 0 すべてのウィンドウの最背面
Ci.nsIXULWindow.loweredZ 4 すべてのChromeウィンドウの最背面
Ci.nsIXULWindow.normalZ 5 通常
Ci.nsIXULWindow.raisedZ 6 すべてのChromeウィンドウの最前面
Ci.nsIXULWindow.highestZ 9 すべてのウィンドウの最前面

lowestZloweredZの違いは、前者がエクスプローラその他Windowsネイティブのアプリケーションのウィンドウも含めてすべての最背面になるのに対して、後者はあくまでFirefoxのウィンドウの中での最背面になるだけであるということ。loweredZを指定したChromeウィンドウが他のネイティブアプリのウィンドウの下にある時、そのChromeウィンドウをクリックすると、そのChromeウィンドウがネイティブアプリのウィンドウの上に表示されるようになると同時に、それに「押し上げられる」形で、FirefoxのウィンドウすべてがそのChromeウィンドウより前面に表示される。

highestZraisedZもそれと同様に、後者を指定したウィンドウは上にネイティブアプリのウィンドウが重なりうるけど、前者にはいかなるウィンドウも上には重ならない……のかと思いきや、こちらはどっちを指定してみてもraisedZで期待される通りの挙動にしかならなかった(Firefoxのウィンドウの中での最前面になるだけで、他のネイティブアプリのウィンドウが前面にくると、その下に隠れてしまう)。これってバグ?

ちなみに、数値で1~3を指定した場合はloweredZ(4)を指定したのと同じ挙動になるようだ。多分7~8はraisedZ(6)と同じで、それ以上はすべてhighestZ(9)と同じになるんだろうと思うけど……前述の通りhighestZraisedZは実際の挙動に違いが全然無いので、それを確認することはできなかった。

あと、ずっと前にEz Sidebarでこの問題にぶち当たってから気になってるもののずっと直ってないみたいなんだけど、raisedZ以上が指定されたウィンドウがあると、通常のウィンドウで開いたモーダルダイアログが親ウィンドウの下に潜ってしまうという問題が起こる。パスワードの入力を求めるダイアログ等がFirefoxのウィンドウの下に潜ってしまって使い物にならないので、これはマジで困る。どうにかならんものだろうか。

――ということで対策を考えてみた。

var XULWindow = window
     .QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIWebNavigation)
     .QueryInterface(Ci.nsIDocShellTreeItem)
     .treeOwner
     .QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIXULWindow);
var observer = {
  observe : function(aSubect, aTopic, aData)
  {
    if (aTopic == "xul-window-registered") {
      XULWindow.zLevel = Ci.nsIXULWindow.normalZ;
      window.setTimeout(function() {
        XULWindow.zLevel = Ci.nsIXULWindow.highestZ;
      }, 250);
    }
  }
};

var ObserverService = Cc["@mozilla.org/observer-service;1"]
      .getService(Ci.nsIObserverService);
ObserverService.addObserver(MakeOnTopObserver,
                            "xul-window-registered", false);

新しいウィンドウが開かれる直前にウィンドウのzLevelを元に戻して、ウィンドウが開かれた後にまた最前面に戻す。こうすれば最後の問題は回避できる。

Page 44/248: « 40 41 42 43 44 45 46 47 48 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき