Home > Latest topics

Latest topics 近況報告

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

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

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

Page 23/242: « 19 20 21 22 23 24 25 26 27 »

いつの間にかインラインフレームを透過できるようになっていた - Jan 25, 2011

Bug 591652 – Make the tab view (Panorama) background transparent to reveal glass (if enabled) on Windowsというバグがfixされて、Panoramaの背景が透過されるようになった。Windows Vista以降でAero Glassを有効にしてれば、見事なスケスケになる。

で、ほうほうと思ってチェックインされたパッチを見てみたんだけど、「Aero Glassじゃない時だけ背景を指定する」というコードしかない。ひょっとしてフレームを透過するバックエンドってもうずっと前から入ってたの? そういえばPanorama用のiframeには transparent="true" という指定がずいぶん前からあったような気がするけど、特に透過されてる様子もなかったから、まだ実装されてないのかと思ってた。

それでMinefield 4.0b10preを起動してDOM InspectorでFirefoxのDOMツリーをいじって試してみたら、browser要素とかiframe要素とかに transparent="true" という属性の指定を加えて、そのフレーム要素・祖先要素すべて・フレームの中に含まれるドキュメントのbodyを background: transparent !important; にするだけで、普通のWebページでもデスクトップの壁紙が透けて見えるようになった。これは面白い。

最小構成だとこう。

parent.xul:

<?xml version="1.0"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
        style="-moz-appearance: -moz-win-glass; background: transparent;"
        width="200" height="200">
  <iframe transparent="true"
          flex="1"
          style="background: transparent;"
          src="child.xul"/>
</window>

child.xul:

<?xml version="1.0"?>
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
      style="-moz-appearance: none; background: transparent;">
  <label value="Hellom, transparent world!"/>
</page>

この2つのファイルをテキスト形式でデスクトップに保存して、エラーコンソールから window.openDialog('file:///c:/Users/username/Desktop/parent.xul'); とやれば試せる。

Aero Glassじゃない時は普通の背景を表示させたいなら、CSSの方にこう書いておけばいい。

window:-moz-system-metric(windows-compositor) {
  background: -moz-field;
}

夢が広がりまくりですね!

XBLとアドオンとDOMツリーの切り貼りとツールバーカスタマイズの危険な関係 - Jan 23, 2011

ツリー型タブPersonal Ttitlebarと併用できるようにするためにずいぶん骨を折った。

Firefox 4のタブバーの仕様

Firefox 4ではタブバーとtabbrowser要素がDOMツリー的に切り離されて、tabs要素がカスタマイズ可能なtoolbarの中に置かれるようになった。この話は以前に勉強会で発表した(この資料の日付を見て「うわーもうあれから1年近く経とうとしてるのか、Firefox 4の開発どんだけ遅れとんねん」とか「そんな昔のことを『ちょっと前に発表しましたが』とか書こうと思ってしまった自分ってどないやねん」とか思ったのですがそれはどうでもいいです)んだけど、その時こんな話をした。

  • 今まではorientとordinalやdirectionで簡単にタブバーの位置を右や左や下には動かせたが、それができなくなった。
  • Tab Mix Plusは、タブバーのtabs要素をDOMツリーから一旦切り離してtabbrowser要素の下にappendChildで再挿入することで、タブバーの位置を変えるようにしたようだ。
  • ツリー型タブでは、DOMツリーは触らずに、toolbarの表示位置をposition:fixedで動的に位置を合わせることで擬似的にタブバーの位置を変えたように見せかける方法を採ることにした。
    • この話をしたら会場から失笑の渦が巻き起こった。「無茶しよるなー」的な。

その時も特には説明しなかったんだけど、何故僕はそうまでしてDOMツリーの変更を避けたがるのか。今回Perosnal Titlebarとの衝突を解決するためにここで散々悩まされたので、改めてここに記しておこうと思う。

Firefoxのツールバーと絡むアドオンを作る時に注意する事

Firefoxのツールバーの各機能は、ユーザが任意にドラッグ&ドロップで並べ替えたりアイテムを追加・削除したりできるようになっている。この時内部的には当然だけどDOMツリーが動的に切り貼りされている。

この時、ツールバーから削除されたボタンに対してDOMのイベントを監視し続けるのは変だし、そのボタンへの参照をアドオンの中の変数でずっと持ったままだと、いわゆるメモリリークが起こることもある。なので、僕はツールバーにボタンを追加するアドオンについては、ツールバーのカスタマイズに入る前に一旦「ボタンの終了処理」を行って、ツールバーのカスタマイズが終わった時点でもう一度「ボタンの初期化処理」を走らせるようにしていることが多い。

ちなみに、こういう事をするためにDOMイベントが使えればいいんだけど、Firefox 3.6までのバージョンではそんな配慮は全然無い不親切な設計なので、カスタマイズを開始する関数の BrowserCustomizeToolbar() とかカスタマイズ終了時に呼ばれる BrowserToolboxCustomizeDone() とかツールボックスの customizeDone() メソッドだとかを上書きして処理を挟み込んでやらないといけなかった。Minefieldではいつの頃からか beforecustomization とか aftercustomization とか customizationchange とかのイベントが発行されるようになったので、こういうダーティなことはやらなくても済むようになった。もっと早くからこうしてくれていればよかったのに……いやそれは今はどうでもいい。

自分で追加したツールバーのボタンについてそういう事が必要なのと同様に、例えば標準のWeb検索バーの挙動を変更するセカンドサーチのような「既存のツールバーボタンの挙動を変える物」も、同じような事をしないといけない。特に、既存のボタンにXBLで追加されたメソッドを後から上書きしているようなケースでは。セカンドサーチの例で言うと、こういう感じだ。

  • セカンドサーチはWeb検索バーにXBLで追加されたメソッド handleSearchCommand() を上書きする。
    • このメソッドが上書きされていることを前提として、他の機能も成り立っている。
  • Web検索バーがDOMツリーから一旦取り除かれ、再度挿入されると、その時点でXBLの定義が再度適用される。そのためセカンドサーチが上書きしたはずの handleSearchCommand() メソッドも元に戻ってしまう
    • Web検索バーがツールバーからパレットに移動されなくてもそうなる。何故なら、ツールバーのカスタマイズ時にはすべてのカスタマイズ可能な要素が一旦DOMツリーから取り除かれた後、toolbarpaletteitem という要素にappendChild()されて、元の要素があった位置に挿入される、という処理が行われるから。
    • ツールバーのカスタマイズを完了する時はこの逆の操作が行われる。つまり、すべての toolbarpaletteitem 要素が削除されて、代わりに、その中にあった要素が toolbarpaletteitem があった位置に再挿入される。

Firefox 4でタブバーがツールバーに移動された時も、これと同じ事が起こるんじゃないかとちょっと思ってたけど、実際はそうならなかった。Firefoxの他の部分が「タブがある事」を前提に設計されているせいで、タブバーをツールバーカスタマイズでツールバー上から完全に取り除いたら、他の機能が色々と破綻してしまうから……という事なんだと思われる。なので今のMinefieldでは、タブバーのtabs要素はメニューバーと同様に「ツールバーの中にあるけど動かせない要素」という扱いになっている。

そういう事情で、Firefoxもタブバーまわりのコードは「DOMツリーが動的に編集されても動作するような堅牢に設計」にするための注意は払われていないし、他のタブ周りのアドオンもそういう設計にはなっていない事が多い。というか、そういうアドオンがあまりに多いからFirefox本体の側でもタブバーをカスタマイズで移動できないようにせざるを得なかったって事なんじゃないかと思うんだけど。

Personal Titlebarを使った時に起こる事

Personal Titlebarというアドオンは、Firefox 4の(Windowsでの)タイトルバーに任意のツールバー用のボタンを配置できるようにするという物だ。それだけでなく、タブバーすらカスタマイズで移動できるようにしてしまう。それが問題だった。

前述した通り、Firefoxのツールバーはカスタマイズのモードに入っただけでもDOMツリーが切り貼りされる。Personal Titlebarがあるとタブバーのtabs要素もそういう処理の対象になる。ツールバーのカスタマイズに入るだけでもタブバーの各プロパティが初期化されてしまい、ツリー型タブが上書きしたメソッドも元に戻ってしまって、表示がグチャグチャにぶっ壊れる。これが衝突の真相だった。

これを回避するためには、単純に考えれば「ツールバーのカスタマイズに入る前にすべてを元に戻し、カスタマイズが終わったら再度初期化する」ということをやればいいということになる。でも話はそう簡単にはいかなかった。

beforecustomization のタイミングでできる事には限りがある

beforecustomizationイベントは、普通の同期型のイベントとして発行されていて、このイベントを捕捉したすべてのイベントリスナの中で処理が終わった後、ツールバーカスタマイズのための本来の処理が始まるようになっている。「このアドオンの終了処理は無事に終わりました。ツールバーのカスタマイズを初めても大丈夫ですよ。」という事を、アドオンの側が明示的に通知する手段はない。単にイベントリスナの処理が終わったらその時点で「終了処理が終わった、もうカスタマイズを初めても大丈夫だ」と判断されるような単純な設計だ。

一方で、ツリー型タブはタブバーの表示を縦にしたり横にしたりとダイナミックな切り替えをする時に、タイマーを多用している。何故かというと、XULの属性値やCSSのプロパティを変更した後、そのイベントループ中では結果が適用されないままなので、現在のイベントループを一旦終了させた上で、setTimeout()で続きの処理を次のイベントループ内で行わないといけない、という場面が多いからだ。

なので、beforecustomization イベントを捕捉した時点でタブバーの「終了処理」を行おうとしても、現在のイベントループの中でできる事までしか終了処理を終わらせられない。中途半端な状態でツールバーのカスタマイズに突入してしまう事になるし、しかも、次のイベントループに回すための続きの処理がツールバーのカスタマイズに突入した後で走ってしまうから、もうあっちもこっちも色々前提が崩れててシッチャカメッチャカな事になる。

必要なのは「今のイベントループの中で終了処理を完結させる」「次のイベントループを待つ必要がある終了処理を行う」この矛盾した2つをどうにかして両立させる事だ。

DOMイベントが発行されるまで今のイベントループを強引に停止させる

結論から言うと、XPCOMのスレッドの機能を使えばできる。

doAndWaitDOMEvent : function TSTUtils_doAndWaitDOMEvent() {
  var type, target, delay, task;
  Array.slice(arguments).forEach(function(aArg) {
    switch(typeof aArg) {
      case 'string': type = aArg; break;
      case 'number': delay = aArg; break;
      case 'function': task = aArg; break;
      default: target = aArg; break;
    }
  });

  if (!target || !type) {
    if (task) task();
    return;
  }

  var done = false;
  var listener = function(aEvent) {
      setTimeout(function() {
        done = true;
      }, delay || 0);
      target.removeEventListener(type, listener, false);
    };

  if (task)
    setTimeout(function() {
      try {
        task();
      }
      catch(e) {
        dump(e+'\n');
        target.removeEventListener(type, listener, false);
        done = true;
      }
    }, 0);

  target.addEventListener(type, listener, false);

  var thread = Components
          .classes['@mozilla.org/thread-manager;1']
          .getService()
          .mainThread;
  while (!done)
  {
    thread.processNextEvent(true);
  }
},

こんなユーティリティメソッドを作った。DOMイベントターゲット、そのターゲットに到達するはずのDOMイベント名、別のイベントループで実行されなくてはならない処理を含む関数、を引数として受け取り、渡された関数を実行して、今のスレッドの処理を止める。指定されたDOMイベントが発火したら、今のスレッドを止めるための無限ループから抜ける。これで、beforecustomization イベントのタイミングで複雑で長い終了処理を実行できるようになった。

まとめ

Personal Titlebarというアドオン1つとの衝突を解消する事だけ考えるなら、タブバーだけは移動できないようにPersonal Titlebarのコードに対してさらに変更を加えてしまうという手もあった。ただ、それでは「既にPersonal Titlebarでタブバーの位置が変更されていた所にツリー型タブがインストールされた」という場合には意味がないし、そもそもFirefox本体の側がタブバーをカスタマイズで位置変更できるようにする可能性もある(Add-on SDKベースで作るアドオンなら互換性が担保されるから、ということでSDKベースでない既存のアドオンをバッサリ切り捨てる事になるような変更もFirefox本体に入れやすくなるから)。なので頑張ってみた。

ただ、こういう事が起こる原因になるから、自分が作るアドオンの中では極力DOMツリーはいじらないようにしたいとは、今も変わらず思ってる。高速化のために最上位のDOMツリーをゴッソリ入れ換えるのもNGだし、ましてや、WebページのbodyのinnnerHTMLを文字列として一括置換するなんてのは論外だ(そういう事をしても既存のイベントリスナに影響を与えないといった風に仕様でちゃんと定められていて実装もそうなっているのなら問題ない。仕様や実装がそう変わったんだったら高速化のためにそういう工夫を取り入れるのはむしろ奨励すべき事だとは思う)。

Firefox本体の側で行われた変更なら他のアドオンも追従するだろうけど、僕個人でこうして細々と開発しているアドオンのためにまで、わざわざ他のアドオン作者の人が頑張って対処してくれるとは思えない。僕だって、他の知らないアドオンのために事前に対処はできない。僕にできる事は、「自分が作る物については、他のアドオンに与える影響を小さくするようなるべく配慮する事」、ただそれしかない。

Nautilusで「ここでターミナルを開く」 - Jan 17, 2011

Windowsには昔からよく知られた便利機能でCommand Prompt Hereという物がありまして、要するに「フォルダの右クリックメニューから、そのフォルダをカレントディレクトリにした状態でコマンドプロンプトを開く」というやつなんですが、Windows 95の頃にはPower Toysというユーティリティ集でこの機能を簡単に追加できたりもしました。

これと同じ事をGNOMEのNautilusでやるパッケージがあったんですね。その名もnautilus-open-terminal。Debianにも同名のパッケージがあるようです。

CUIメインで使ってる人には用がなさそうですが、僕みたいにヌルい人にはあると便利です。

ツリー型タブとマルチプルタブハンドラのイベント周りのAPIをちょっと変えた - Jan 11, 2011

Tree Style TabMultiple Tab Handlerを更新した。

今回のアップデートでも例によってMinefield対応のための修正をちょっとずつ入れてるんだけど、その中で1つ、なかなか気付いてなくてハマってた所があった。それはカスタムイベントを使ってた部分。

DOM2 Eventsではこんな風にして任意のDOMイベントを発行できる。

var event = document.createEvent('Events');
event.initEvent('MyCustomEvent', true, false);
event.status = 'current status';
event.tab = tab;
gBrowser.dispatchEvent(event);

受け取る側はこれをaddEventListener()で登録したリスナで拾うようにすれば、各々のモジュールの結合度合いを弱められる。なので僕は自分のアドオンでも積極的にこれを使ってる。

が、これがMinefieldでは使えなくなってた。

多分Compartment(JavaScriptのメモリ空間をスクリプトのオリジンだったかウィンドウだったかごとに分ける機能)が入ったからだと思うんだけど、Chrome URLのスクリプトで上記の例のように追加した任意のプロパティを、JavaScriptコードモジュール側のイベントリスナで参照できなくなってた。上記の例だと、捕捉したイベントのevent.tabundefinedになってしまってて、こういうやり方で情報を引き渡してた部分がエラーになってしまってた。wrappedJSObjectundefinedなので、生のオブジェクトを辿る事もできなかった。

MDCにある任意のカスタムイベントを実装する方法の詳しい説明によると、XPIDLでインターフェースを定義してC++で実装を書いてという事をやれば、今までと完全に同じAPIで任意のイベントを発行できるようなんだけど、それはちょっと重たすぎてやる気になれない。

なので次善の策として、汎用のデータを受け渡すためのイベント型があればそれを使おうと思って検索したら、Firefox 3以降ではDataContainerEventとかMessageEventとかの型のイベントが利用可能になってたという事を知った(今更)。

渡すデータがJSON文字列化できる物なら、WebSocketで定義されてるMessageEventがいいっぽい。

var event = document.createEvent('MessageEvent');
event.initMessageEvent('MyCustomEvent', true, false,
  JSON.stringify({ status : 'current status',
                   tab : tab.getAttribute('id') }),
  '', '', null);
gBrowser.dispatchEvent(event);

受け取った側はJSON.parse(event.data)でデータを復元できる。

DOM要素とかも渡したいなら、nsIVariant型でデータを受け渡せるDataContainerEventを使うしか無さげ。

var event = document.createEvent('DataContainerEvent');
event.initEvent('MyCustomEvent', true, false);
event.setData('status', 'current status');
event.setData('tab', tab);
gBrowser.dispatchEvent(event);

受け取った側はevent.getData('tab')のようにしてデータを取得できる。

ということで、プロパティアクセスにしてた所は全部DataContainerEventのやり方を使うように直した。ただ、後方互換性のためにプロパティアクセスでも情報はセットしてあって、同じCompartmentのスクリプトからなら多分今まで通りのやり方でも情報を受け取れると思う。

あと、DataContainerEventの存在を知る前に、MDCのドキュメントに書いてあった「イベント名がnsDOMで始まってない物は任意の情報は受け渡せないよ」という部分を読んでイベント名を「nsDOMTreeStyleTab...」という感じに変えていて、実際これでちゃんと動くようになった部分もあったんだけど、結局DataContainerEventにするようにしたからこれは結果的には余計だったかもしれない……

transitionendイベントが発火されないことがあるというバグが修正されそう - Jan 10, 2011

CSS Transitionsではアニメーションの終了時にtransitionendというイベント(webkitではwebkitTransitionEnd)が発行される事になってて、Minefieldに既に入ってる「タブを開く時にアニメーションする」「タブを閉じる時にアニメーションする」という機能でもこれが使われてる。具体的には、max-widthをアニメーションさせることでタブがぬるっと生えてきたりぬるっと縮んでいったりという効果を与えて、アニメーションが終わった後で実際にタブの要素を削除するという風な事が行われている。

このtransitionendイベントがたまに発行されない事があって、そのせいで「閉じたはずなのにタブがそのまま残ってしまう」「タブが開かれた後に行われるはずの処理が行われない」といった問題が発生していた。特に、ツリー型タブではタブバーの向きを横長ではなく縦長に変更していて、その絡みでmax-widthのアニメーションの代わりにmax-heightとかmargin-topとかopacityとかをアニメーションさせるようにしてるんだけど、そのように複数のプロパティについて異なるdurationでアニメーションを行うようにしてる時にこの問題が顕著に発生するようで、しかし確実に問題を再現させる条件がはっきりと分かっておらず、Bugzillaに報告しようにも報告できない状態が長く続いてた。

それが今回、ひょんな事から確実に問題が再現する条件を特定できたので、Bugzillaに既に存在していたBug 613888 – Sometimes transitionend doesn't fireに再現性100%のテストケースを投稿してみた。

そしたら、そこからの動きが早かった。タイトルが示すように「時々しか起こらない」ということで割と優先度低めの扱いだったっぽいのが、hardblockerになってblocking2.0になって(つまりこのバグが直らなきゃFirefox 4はリリースされないという致命的なバグと認識された)、David Baronさんがパッチを書いてくれて、ついでに僕の投稿したテストケースを元にした自動テストもパッチに含めてくれて、あとはレビューとチェックイン待ちという状態になっている。

べつに僕が最初に問題を見つけた訳ではないし、僕が実際にパッチを書いたわけでもないけれども、自分のやったことがきっかけになって厄介なバグが修正に至ったと思うと、率直に言って「やったぜ!!!」と自分の事のように嬉しく感じてる。

このエントリで何を言いたかったのかというと、要するにその「やったぜ」の自慢話ということなんだけど、それと同時に、再現性100%のテストケースや再現手順を特定することは大事なんだよ、それを自動化することも大事なんだよという事も伝えたかったのです。

再現性100%の手順が判明していればすぐに開発者の環境でデバッグできるし、自動テストがあればそれをそのままリポジトリに取り込むこともできる(=今後のregressionの発生を予防できる)。パッチを書けない人でも書けないなりの協力はできるのです。単に「動かないよ」と言うだけの場合よりも、原因特定のための検証を開発者がやる手間が省けるから、効率がいいしバグも早く直る訳です。

  • Mozillaの自動テストには、Mozillaのリポジトリに含まれているテストで実際に使われてるフレームワークが列挙されている。
  • 今回のテストケースではその中の1つのMochitestを使った。
    • Mochitestは基本的にはMozillaのビルド環境を整えた上で使う物だけど、MochiTest makerと最新のナイトリービルドを使えば、Mozillaのビルド無しにテストケースを書いて試すことができる。
    • 実際にどんなテストがあるかは、MXRで「bug_」を名前に含むファイルを検索してみると色々な例を見れる。
  • FirefoxのUIの上で操作した時に起こるバグの再現だったら、MozmillUxUが使えるはず。

というわけで、バグ報告には確実に問題を再現できる手順(できれば自動テスト)を添えて下さいね、という話なのでした。

16日追記。パッチがチェックインされた後のナイトリービルドで、自分の環境では上記の問題が解消されていることを確認できた。よかった……これで安心してFirefox 4を迎えられるよ。

Linuxで一度にオープンできるファイルの最大数を変える - Jan 07, 2011

Ubuntuの場合、初期状態では1つのプロセスで開けるファイルの最大数は1024個までと決まっているようで、それ以上の数のファイルを開こうとするとエラーになる。普通に使っててこの制限を気にする場面は全然無いんだけど、自動テストで大量のファイルを処理するようなやつを実行するとたまにこの制限に引っかかってしまうことがある。

現在の制限がどうなっているかは、ulimit -a で調べられる。open filesと書いてある所の数値がそれだ。

この制限を一時的に緩和するには、ulimit -n 任意の整数 とやればいいらしい……んだけど、ulimitはsudoでは実行できないようだった。rootで操作すればいいんだけど、普通にUbuntuを使ってるとrootにはなれないので、この方向を頑張るのはちょっとやる気が出ない。

代わりの方法として、/etc/security/limits.conf を編集するという手もある。例えばすべてのユーザに対してファイルの最大オープン数を2048個に増やしたければ、/etc/security/limits.confに以下のような指定を書き加える。

* soft nofile 2048
* hard nofile 2048

これで再起動すれば、すべてのユーザについて、1プロセスで扱えるファイルの最大数が2048にまで増える。

新しいタブとかウィンドウとかで「戻る」を押しても戻れねえよムキーッとなる問題を解消するアドオン「親のタブに戻る(Back to Owner Tab)」をリリースしたよ - Jan 07, 2011

Back to Owner Tabというアドオンを作ってみた。

例えば初心者ユーザにはこういう事がありがちだろう。

  • ブラウザのウィンドウを常に最大化して使っている。
  • タブとかウィンドウとかよく分かってない。「戻る」ボタンを押せば1つ前のページに戻れる、という事は(教わったので)知っている。
  • リンクをクリックした結果新しいページが表示されたとして、それがただのページ遷移なのか、新しいタブで開かれたのか、新しいウィンドウで開かれたのか、違いがよく分かってない。
  • 新しいウィンドウで開かれたページを見終わって「元のページに戻ろう」と思って「戻る」ボタンをクリックするが、ボタンをクリックしても何も起こらない。

こういう場面で、「戻る」をクリックしたらとにかく元のタブなりウィンドウなりに戻るようにするのが、このアドオンだ。

だいたい、ウィンドウを最大化してたりタブを表示しないようにしてたりすると、「戻る」で戻れるのかそうでないのかすぐには分からないから、初心者でなくてもこういう物には意味があると思う。

Firefox 3.5以降では browser.tabs.selectOwnerOnClose が true で且つそのタブが「新しいフォアグラウンドのタブ」として開かれた時にだけ「このタブの親はこのタブですよ」という情報が保持される。また、JavaScriptではwindow.openerでオープン元のウィンドウを辿ることができる。このアドオンは、これらの情報を手がかりにして「親のタブ」を検索するようになってる(ツリー型タブがあるならツリーの構造から親のタブを検出する)。

確かタブブラウザ拡張にもこういう機能を含めてた気がするんだけど、それらを単機能の拡張機能として再実装した時に取りこぼしてた。その後、ツリー型タブにこの機能を含めてくれという要望が何回か来てたんだけど、今だったら browser.tabs.selectOwnerOnClose があるから別にツリー型タブに依存した機能にしなくてもいいよなーと思ったので、こうして今回新たに1つのアドオンとして作ってみたというわけ。

Add-on SDKは使ってないけどBootstrapped Extensionsの形にしてあるので、Minefieldでは再起動無しでインストールできる。昨年の発表では「Bootstrapped Extensionsでは『戻る』ボタンの挙動をオーバーライドするみたいな事はできない」と言ったけど、やってみたらできてしまった。あと、そのために使った方法がFirefox 3.6では動作しなくてちょっと悩んだんだけど、Firefox 3.6ではそもそも絶対に再起動が必要だから「変化を可逆的にする」事にこだわらなくてもいいので、そこは横着してダーティなやり方を使ってる。

なんとなく既出のような気もしたけど、「back owner」とかその辺の単語で検索してもそういう物を見つけられなかったので、じゃあ作るか……と思って作ってみた。既出だったら恥ずかしい。

ちなみに、似たような目的のアドオンでTab Historyという物もある。こちらは「新しいタブを開く時に、元のタブの『戻る』『進む』の履歴を引き継ぐようにする」というアプローチを取っている。僕もTab Historyを使ってたんだけど、せっかく作ったので、しばらくはBack to Owner Tabを使って様子を見てみようと思ってる。

Inkscape向けのマンガ用A4-B5テンプレート - Dec 26, 2010

最近は同人のマンガは全部ComicStudioで作ってるんだけど、今自宅のメインのWindowsマシンが(多分)マザーボードの故障で修理中で手も足も出ないので、タブレットでデジタル作業というのはさすがに諦めてアナログ作画で何とかしようと思ったのです。

で、仕上がり寸法B5の作品にしたいと思ってるんだけど手元にはA4のPPC用紙しかないので、トンボとかガイド線とか一式が入ってるテンプレートが必要になったのでInkscapeで作ってみたのです。

A4-B5.svg

途中、Inkscapeでのトンボ(トリムマーク)の作り方が分からなくて詰まった。やり方の解説を見つけたのでメニューを見てみても、Ubuntu 10.10のInkscapeだと「エクステンション」メニュー直下に「プリントマーク」が無いし(サブメニューを辿ったら「レンダリング」の中にあった)。

寸法は、用紙がA4、裁ち切り線がB5、基本枠(セリフ等を基本的にはこの中に収めるようにしなさいという枠)はA5です。トリムマーク以外はシアン10%になるようにしてあるので、普通にコピー機で白黒コピーしたら多分コピーされない。はず。

料理 - Dec 25, 2010

イブが終わって世間のクリスマス気分がすっかり終わった間のある今日になって、半分はヤケで、クリスマスらしい料理という物を作ってみようと思い立ったのです。

これならできるんじゃないか……?と思った物を適当に3つほどピックアップした。

結論から言うと、まともにできたのはミートローフだけだった。これは電子レンジとクッキングシートとボウルと包丁とまな板と皿があればそれでできて、時間も手間もかからないし失敗もない。素晴らしい。日常的に作って全然アリだと思った。

フードプロセッサーもジューサーもミキサーもないのにポタージュスープ的な物を作ろうというのは間違いだった。レシピをよく見ないまま作り始めて途中でそれに気がついて、おたまの底とかスプーンとかを使って何とか材料を細かく潰そうと頑張ってみたんだけど、どうも粒が残る。調理器具を手に入れたらもう一度やってみたい。

あとお菓子。ホームベーカリーとか無いし素材をあらかじめ暖めておくのも忘れてたしオーブン機能のあるレンジもなくてオーブントースターしかないしで、これも散々だった。菓子作りは計量が命だというのをどこかで聞いた記憶はあったのでそこだけはちゃんとやったけど、無塩バターじゃなく普通の塩入りバターを使ってしまったし、どうにも生地がベタベタしたままだし、手持ちの道具はオーブントースターだけだし、ハケも持ってないし(Jetpackを作った時に使った物はさすがに使えない)、で、なんかよく分からない物ができあがった。思ってたほどは酷くはなかったけど、その後で普通に買ってきたケーキを食べたらそっちが死ぬほどうまかったので、プロの人はすごいなあと思った。

どれも作るの初めてだったし3種同時進行というのも初めてだったし、世の中そううまくはいかないものだなあということを実感したのでした。364日フライングで練習したということで、この経験を活かせる時が来る事を願う。

ゆうきまさみ開業30周年記念企画展に行ってきた - Dec 25, 2010

渋谷PARCO 1で開催されている原画展で、パトレイバーの原稿の展示が23日で終わるという事を22日になって知って、慌てて行ってきた。

単行本は実家に置いてきたんだけど、展示されてたイングラム対グリフォンの最終戦の原稿を見てると、最終戦を読んだ時の興奮が蘇ってきて涙目になりかけた。「機動警察パトレイバー」は本当に名作だと思う。未読の人はほんとに1回読んでみるといいです。

で、帰宅してその勢いで劇場版第1作を見た。ブルーレイだけど、5.1chじゃない方の音声を選ぶと(ステレオPCMで)サウンドリニューアル版でない当時の音声で楽しめるという事に、初めて気がついた。5.1chサラウンドの環境なんか持ってないから音声を選び直したんだけど、これは嬉しいサプライズだ。「呪ってやるー!!」は当時の演技の方が好きなのです。

Page 23/242: « 19 20 21 22 23 24 25 26 27 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき