Home > Latest topics

Latest topics 近況報告

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

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

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

Page 16/241: « 12 13 14 15 16 17 18 19 20 »

JSDeferred - Why this code doesn't work? - Jun 12, 2012

I got a mail.

I've started to use jsdeferred 2 days ago and I'm really really happy with it because I consider it's really easy to use, light and it looks very powerfull. Anyway, I have one little doubt I hope you can help me about.

Here's the thing, I would like to deferredize some functions to use in some chains, but I haven't figured out what's the best way to get it, I put you a little example

If I try something basic like this:

function my_deferred(data) {
var deferred = new Deferred();
deferred.call(data);
return deferred;
}

function main() {
Deferred.define();

my_deferred("foo").
  next(function(data) {
    console.log(data);
  });
}

The chain is not executed (I don't know why). But if I change to something like this, using setTimeout, it works:

function my_deferred(data) {
var deferred = new Deferred();
setTimeout(function() {
  deferred.call(data);
},1);
return deferred;
}

function main() {
Deferred.define();

my_deferred("foo").
  next(function(data) {
    console.log(data);
  });
}

The question is, wouldn't it be possible to get the right behaviour of the chain without using setTimeout? I would like to deferredize some functions without the penalty of using setTimeout.

You should use Deferred.next() ( it is available as a global function next() if you use Deferred.define() ) instead of setTimeout(), like:

function  my_deferred(data) {
  var deferred = new Deferred();
  Deferred.next(function() {
    deferred.call(data);
  });
  return deferred;
}

Deferred.next() works just like setTimeout(), but in most cases it works faster than setTimeout().

deferred.call() just calls the next job which is registered as a callback function given to its .next() method. So, you have to call deferred.call() after you register the next job.

However, In your case, any "next job" has not been registered yet when you call deferred.call(). As the result, the "next job" registered after deferred.call() was called won't be called by anyone.

function my_deferred(data) {
  // (3) Now, we are in this function.
  var deferred=new Deferred();
  deferred.call(data); // (4) deferred.call() is called, then
                       //     the next job ( registered via
                       //     deferred.next() ) is also called.
                       //     However, it has not been registered yet.
                       //     As the result, nothing happens.
  return deferred; // (5) We return the deferred object and
                   //     exit from this function.
}

function main() {
  // (1) Starting position of this event loop.
  Deferred.define();

  // (2) The function is called.
  my_deferred("foo").
    next(function(data) {
      // We never come here!!
      console.log(data);
    }); // (6) You register the next job to the returned deferred
        //     object, via its next() method. However, because
        //     deferred.call() was already called, the job will
        //     never be called by anyone.
  // (7) End of this event loop.
}

Instead,

function my_deferred(data) {
  // (3) Now, we are in this function.
  var deferred=new Deferred();
  Deferred.next() {
    // (8) Now, the next event loop is started.
    deferred.call(data); // (9) deferred.call() is called, then
                         //     the registered next job is also called.
  }); // (4) We just reserve the task for the next event loop.
  return deferred; // (5) We return the deferred object and
                   //     exit from this function.
}

function main() {
  // (1) Starting position of this event loop.
  Deferred.define();

  // (2) The function is called.
  my_deferred("foo").
    next(function(data) {
      // (10) We are here!
      console.log(data);
    }); // (6) You register the next job to the returned object.
  // (7) End of this event loop.
}

As above, you must register the next job to the deferred object before its call() is called.


ちょよんごさんによると、このメールの送り主の人(ここでは省いたけど、WebGL用のスクリプトを書いてるそうです)は、JSDeferredを使ってるとおぼしき開発者に手当たり次第質問を投げてるらしい。そんなこととはつゆ知らず「僕作者じゃないんだけどなあ」と呑気にちょよんごさんに転送してしまって、余計なストレスをかけてしまったようなので罪滅ぼしと思って真面目に返信してみた。伝わってるかどうかは分かんないけど。

これはJSDeferredの結構典型的なハマリ所だと思う。XMLHttpRequestとかNode.jsの非同期なメソッドみたいに、コールバック関数が必ず次以降のイベントループで呼ばれる物に対してであれば、このメールの送り主の人が書いてるような

var Deferred = require('jsdeferred').Deferred;
var fs = require('fs');

function statDeferred(filePath) {
  var deferred = new Deferred();
  fs.stat(filePath, function(error, stats) {
    if (error)
      deferred.fail(error);
    else
      deferred.call(stats);
  });
  return deferred;
}

statDeferred('/tmp/foobar')
  .next(function(stats) {
    if (stats.isDirectory()) {
      ...
    }
  });

こういう流れの書き方で何も問題ない。

問題は、やらせたい処理が同期的であった場合で、

function statDeferred(filePath) {
  var deferred = new Deferred();
  try {
    var stats = fs.statSync(filePath);
    deferred.call(stats);
  } catch(error) {
    deferred.fail(error);
  }
  return deferred;
}

これでは動かないのですよね。 何故かというと、 deferred.call() は「その deferrednext() に渡された関数、という形で あらかじめ 登録されていた『次のジョブ』を実行する」物だから。 この例だと statDeferred()deferredreturn する前に deferred.call() を呼んでしまっているから、その後で次のジョブを登録しても、登録した「次のジョブ」を呼ぶ人が誰もいないわけです。

function statDeferred(filePath) {
  // (2) 関数の中に入った。
  var deferred = new Deferred();
  try {
    var stats = fs.statSync(filePath); // (3) 処理を実行した。
    deferred.call(stats); // (4) 登録済みの「次のジョブ」を実行しよう……
                          //     とするんだけど、まだ何も登録されてないので、
                          //     当然何も起こらない。
  } catch(error) {
    deferred.fail(error);
  }
  return deferred; // (5) 関数を抜けた。
}

// (1) 今のイベントループでのスタート地点。
statDeferred('/tmp/foobar')
  .next(function(stats) {
    // 「次のジョブ」の登録後に deferred.call() が呼ばれないので、ここには到達しない。
    if (stats.isDirectory()) {
      ...
    }
  }); // (6) 戻り値の next() を呼んで、「次のジョブ」を登録した(今更)。
// (7) 今のイベントループの終わり。

だから、 setTimeout() なり Deferred.next() なりを使って、 deferred.call() を呼ぶ処理を「次のジョブを登録する処理」よりも後(=次のイベントループ)に実行する必要がある。そうすれば、

function statDeferred(filePath) {
  // (2) 関数の中に入った。
  var deferred = new Deferred();
  Deferred.next(function() {
    // (7) 次のイベントループで、予約されたこの処理が始まる。
    try {
      var stats = fs.statSync(filePath);
      deferred.call(stats); // (8) 登録済みの「次のジョブ」を連鎖的に呼ぶ。
    } catch(error) {
      deferred.fail(error);
    }
  }); // (3) 次のイベントループで実行するように予約。
  return deferred; // (4) 関数を抜けた。
}

// (1) 今のイベントループでのスタート地点。
statDeferred('/tmp/foobar')
  .next(function(stats) {
    // (9) 「次のジョブ」として、この処理が始まる。
    if (stats.isDirectory()) {
      ...
    }
  }); // (5) 戻り値の next() を呼んで、次のジョブを登録した。
// (6) 今のイベントループの終わり。

……という順番で処理が進むから、期待通りに動くようになる。

どの処理が一体何をしているのか、どの関数が何を返しているのか、自分が呼んでいるメソッドは誰のメソッドなのか、といった事をちゃんと理解しておくと、この話がすっと頭に入ってくると思うんだけど、ただの構文として覚えてしまっていると、メールの送り主の人みたいに「何で動かないの……」って詰まってしまうんだと思う。

という風に偉そうな事を言ってるけど、僕自身も最初は多分ただの構文として覚えてた方で、ただ、「同期処理の時は setTimeout() なり Deferred.next() なりを使って deferred.call() を呼ぶ」という所までを「構文」として暗記していたから、結果的にはちゃんと動いてくれてたという状態だったんだと思う。その後若手IT勉強会の中でコードリーディングをやってだんだん仕組みが分かってきて、「ああなるほど、こういうことだったんだ」と理解できるようになった。

Firefox Hacks Rebootedでもいっぱい書いたけど、JSDeferredの本質は、「あらゆる処理について、その次にやらせたい仕事を next() のコールバック関数という形で後から登録できるようにする」ものだ、と僕は認識してる。「後から登録する」という都合上、この性質は非同期処理(関数を抜けた時点でまだ処理が始まっていないという種類の処理)と非常に相性がいい。けれども、非同期処理じゃないと使えないわけではない。ただ、「後から登録する」というのは、普通に順番通りに進む同期的な処理の中では行えないイレギュラーな事だから、 setTimeout()Deferred.next() を使わざるを得なくて、それで初見の人に分かりにくくなってしまう。そこがもどかしい所だ。

The priority policy of my addon projects - May 10, 2012

In recent days, I discussed on the issue about scrolling of the vertical tab bar. It made the priority policy about my addon projects clear, again. So, let's sum up them.

  • I assign the highest priority to issues I actually annoyed. Most projects were started because I wanted to use such addons. This is the main motivation to continue developing for me. In other words, when I suffer from a bug in my daily use, I'll fix it prior to other bugs, even if the mine is just trivial and the yours is very serious. After that, if I have time good enough, I'll research and fix your issues. If I've never used the feature (and I never use it in the future), then there is extremely low feasibility rating.
  • I'm negative about adding new features (especially digressive features) to existing addons. Because I currently have no plan to switch to other browsers (Google Chrome, etc.), I want to keep codes easy to follow up to future releases of Firefox. Even if the new feature looks simple, it can cost much time for maintenance in the future chronically. Long term sustainability is prior to short term convenience, for my projects. I'll reject requests which can lose maintainability or independency of the project, even if it is very useful feature, fixing serious bug, and so on.
  • I think that any addon shouldn't break features of Firefox itself without any apparent reason. For example, because the tab bar is automatically hidden in the full-screen mode (F11 key) by default, the vertical tab bar also should be done. If my addon breaks Firefox's default behavior unexpectedly, then I'll make effort on fixing it. However, if the issue is not introduced by my addon, then I often step back from it.

Because currently I have less time to develop addons, I have to apply these policies strictly. Actually, in recent days, I spend just a few days of my time per a month for my private development. Sadly I have to keep many requests pending.

However, codes of my addons are licensed under open source licenses. For example, Tree Style Tab is licensed under GPL/LGPL/MPL. You can fork, develop, or re-distribute any project based on my codes, by your hand. Your version can be better alternative for people who suffered from the issue ignored by me. (And, if it is enough reasonable, I possibly merge your changes to my repository.)

シス管系女子 第10話「ネットワーク越しにファイルをコピーしよう」 - May 09, 2012

もう1ヶ月経ってしまった……

ということで日経Linuxにてゆるゆる連載中のコマンドライン系豆知識漫画、「シス管系女子」の第10話が掲載されている日経Linux 2012年6月号が発売されています。 (本編中の1コマ) 今回はscpの紹介です。これのために改めて調べるまで、scpをナメてました自分。

日経Linuxの公式サイトからAmazonの詳細ページにリンクされてます。特集記事も面白いので、デスクトップ環境は使った事あるけど……とか、仕事でサーバを管理しなきゃなんだけど……とか、なんかWaylandとかXとか色々話題になってるけどよくわかんね……とか、そういう人はぜひ一度ご覧になってみてください。紙媒体という都合上、カッティングエッジの最新情報にはさすがに追いつきにくいのは否めないですが、その分教養が深まる読み物が色々ありますので。

あと、日経BP記事検索サービスで「まんが シス管系女子」と検索すると、過去の号に掲載された分をネットで購読(※PDFのダウンロードみたいな形式ではなく、オンラインビューワーで見る形だそうです)できる模様です。以下、現時点で出てくるバックナンバーです。

マンガだけ見てみたいけど近くの本屋に置いてないなーという方は、電車賃使って立ち読みしに行く代わりにこちらもご検討されてはいかがでしょうか。いや、マンガだけと言わず他の記事も。今号で終了してしまいましたがまつもとゆきひろ氏の記事とか、僕も楽しく読ませて頂いておりました。

ところで、単行本出ないの?って声をたまに頂きますが、全然ページ数足りてないんで……この調子だとあと2年くらいやらないと出ない気がします。(そんなに連載続くんか?)

自宅のPCから異音がするようになったのが直った - May 09, 2012

なんか先週末くらいから急に、カラカラカラというかシャッシャッシャッシャッというか、回転する物が何か別の物と当たったり擦れたりしてるような音がしだした。

寿命を迎えたPC用の冷却ファンによくある音だよな……と思って蓋開けて見てみて、CPUでもなければ筐体のでもないしということで、グラフィックカードのファンから音がしてるっぽいという事は分かった。

でもなんで急にそんな音がするようになったのか皆目見当も付かなくて、ホントに寿命なのかなーだったら困るなーと思いながら騙し騙し使ってたんだけど、一昨日あたりからカリカリいう音が絶えず出るようになっていかにもこれはヤバイという感じだったので、とりあえず電源落としてた。

今日になって、もしかして油さしたらよくなるかな?と思って潤滑油のスプレー(ノズルの先に細いストローみたいなのをさす奴)をプシュッとやってみたんだけど、部屋が油臭くなっただけで音は全然変わらなかった(擦れてる音がちょっとだけ、潤滑油のおかげか小さくなりはしたけど)。

こうなったらとことんやってやろうじゃないか、ということでまた蓋開けてグラフィックカード外してファンのとこを指でくるくる回してみたら、どうも出っ張ってる部品とかファンの周りのヒートシンク?とかに当たってるみたいで、なんで急にそんな風に当たるようになったんだろ……コンデンサが膨張してぶつかるようになったとかそういう事でもないみたいなんだけどなあ、とかなんとか思いながらヤスリで当たってたとこをゴリゴリ削り始めたところで、回転するファン自体の方に、なんか指で押すとぐにっと隙間ができてそれが広がる感じになってるとこがあるという事に気がついた。

そういう作りのものなのかなーと思ってたんだけど、ふとファンの真ん中の所にカバーみたいに貼ってあったシールをはがしてみたら、そういう作りなんじゃなくて、ヒビが入ってファンの半分が浮いてる状態になってるだけだったという事にやっと気がついた。半分は軸にくっついてて半分は軸からはがれてるという状態だったから、回転数が上がると遠心力で広がって周囲にぶつかったり、重力やら空力やらで歪んで電子部品にぶつかったりしてたみたいだった。ここに辿り着くまで1週間くらいかかってしまった……

割れたところを、軸にまで染み込まないように注意しながら瞬間接着剤を流し込んで補修したら、電源入れても擦れる音はしなくなった。やっぱりこれが原因で間違いなかった。

もうかれこれ5年くらい使ってる気がするけど、環境移行するのがめんどいのでまだまだ頑張ってもらいます。1回電源が逝ったのをわざわざ有償修理で直してもらったくらいだし……(DELLの通販で買ったマシンだから、明らかに新品買った方がコストパフォーマンス的にはいいはずだけど、それよりも同じ環境使える事の方が僕にとっては大事なのです。)

setTabState()を使わないでタブのサスペンドと復元をやる実装のサンプル - Apr 25, 2012

ツリー型タブに「バックグラウンドにあるタブをアンロードする機能を付けてくれ」って要望が来てて、そんなもんDormancyやらBarTabやらSaveMemoryやらUnloadTabやらなんぼでもあるがな、と思ったんだけど調べてみたらツリー型タブと併用できなかったり(Dormancy, UnloadTab)併用できても今のFirefoxで動かなくなってて開発止まってたり(BarTab)併用できないわ開発止まってるわだったり(SaveMemory)と軒並み全滅だった。

そもそもこの手の奴がなんでツリー型タブと併用できないのかっていうと、

  • ツリー型タブは、ツリー構造の情報をタブのセッション情報の一部として保存している。
  • タブをアンロードする系のアドオンは、セッションストアAPIを使ってgetTabState()でタブの現在のセッション情報を吸い出した後、タブを閉じて、新しい空のタブを開いて、そのタブが選択された時にさっき吸い出したセッション情報をsetTabState()で適用する、という事をしている。

ということで、アンロードする系のアドオンが元のタブを閉じてしまうからツリー構造が破壊されてしまうわけです。BarTabは互換性のためにツリー型タブのAPIを呼んでツリー構造をわざわざ復元するようにしてくれてたから併用できてただけで、本質的にはやっぱり相性が悪い。

っていうかべつに元のタブを閉じる必要なんてなくね? nsISHistoryのPurgeHistory()でセッションヒストリを空にするだけやったらあかんの? あと状態を復元する時もタブの属性とかまで含めて全部上書きせんでもいくない? と思って、「アンロードする時はセッションヒストリを消すだけ」「復元する時はセッションヒストリを復元するだけ」という実装のサンプルを作ってみた。

めんどくさかったから、nsSessionStore.jsをそのまま読み込んで流用するという乱暴なことをやってる。

これに「何分以上放置したら勝手にアンロード」「タブが選択されたら復元」みたいな事を加えればDormancyとかBarTabとかの代替になるんだろうけど、これ以上管理対象のアドオンを増やすのもイヤだし、かといってDormancy等にそのまま取り込んでもらえるとも思えないし(やり方があまりにダーティすぎて、開発の継続性を低下させてしまうだろうし、そもそも現状で困ってるのなんてツリー型タブのユーザくらいだろうし……)、どうしたもんでしょうかね。

……とかいってたんだけど結局真面目に作り始めてしまった。30分以上放置してたら勝手にアンロードするとかその程度の事はとりあえずできるようになってはいる。

Fox Splitterを更新した - Apr 23, 2012

バージョン0.6系(旧版)2.x系(現行バージョン)の両方とも更新した。

バージョン0.6系の方は、前に書いた2.x系への自動アップデート機能の追加だけで、他は何もいじってない。AMOからインストールした人が2.x系に自動アップデートされないという問題への対処のためだけに作ったバージョンなので、AMOにしかアップロードしてない。基本的にこっちはもう終了したバージョンということでよろしく。

2.x系の方は、最近になってUbuntu上でヘビーに常用し始めるようになって色々気付いた問題を修正したのと、僕の使い方で「ああこういう機能欲しいやばい(ないとめんどい)」と思った機能を追加した。

修正の方で特に大きいのは、「グループ化されたウィンドウの1つを移動した後に他のウィンドウをそれに併せて移動する」という部分の改善だと思う。

GNOME2のワークスペース切り替えの時はそこまで酷いことになってなかったんだけど、Ubuntu 11.10にアップデートして3×3のワークスペースを使うようにし始めた(これ多分GNOME3の機能ですよね?)ところ、全く使い物にならないレベルでグループの配置が壊れるようになってしまった。GNOMEのワークスペース切り替えは、少なくともFirefoxの中から見た時には、各ウィンドウの座標を固定してビューポートの方だけを移動させるんじゃなくて、ビューポートの座標の方を固定して全部のウィンドウの座標をぐりぐり動かしているように検知されている。なので、ワークスペース切り替えの時に全部のウィンドウのscreenX/screenYの値が変わってしまう。それで、それぞれのウィンドウがてんでバラバラに「グループの中のウィンドウが1個動かされたから他のウィンドウも再配置しよう」という事を始めてしまってシッチャカメッチャカになっていた。

「グループ化されたウィンドウ全部が相対座標を保ったまま一度に移動されたので、再配置の必要なし」とかの判断をちゃんとするようにすればよかったんだけど、僕の頭で思いつくやり方だとどーにもうまくいかんかったので、諦めて安全確実だけどちょっと重い方法でウィンドウの移動→グループ全体の再配置を行うようにした。普通にウィンドウをドラッグで移動した時とかのレスポンスは悪くなったんじゃないかと思うけど、背に腹は代えられない。

新機能は、「グループ化されたウィンドウの1つでPanoramaを使った時に、グループ全体の大きさまでそのウィンドウを一時的に広げる」という機能が元々あったのを、Panoramaの時以外にも使えるようにした(ついでに、詰めが甘かった所を色々直した)という物。何でこういう物が欲しかったかというと、

  1. 僕は今Ubuntuのワークスペースの1つをFox Splitterで3分割したFirefoxのウィンドウ専用に割り当てている。
  2. 分割後のそれぞれのウィンドウには、別々のプロジェクトのRedmineのチケット一覧を表示している。
  3. それぞれのプロジェクトでチケットを追加する時は、その分割されたウィンドウの中でやっている。
  4. Redmineはある程度の大きさのウィンドウで表示される前提でレイアウトが組まれているので、狭いウィンドウの中では非常に使いにくい。
  5. なので、チケットを書いたり詳細を読んだりするときだけそのウィンドウを大きくして、終わったら元の大きさに戻す(そうしないと他のウィンドウのRedmineが見えないから)という事をよくやっていた。

という使い方をしていて、いいかげんいちいち自分でリサイズするのが面倒になったから。

今のFox Splitterは、全体を管理する大きなウィンドウのような実体が無い状態で各ウィンドウをあたかも1つのグループの下に属しているかのように協調して動作させる、ということをやっていて、作ってる側の自分としては、頭を抱える部分も多いけれども「元々Firefoxにある物だけを駆使してどこまでできるか?」ということを追及するある種の挑戦というかパズルに挑んでいるような感覚もあって、そういうことを効率よくやるためには結局2分木でやるのが安全確実なんだなあとか色々と気付かされた所があって、ノウハウ的にも自分のやってきたことの集大成になってるんだけど、エンドユーザとしての使い勝手は多分旧版のFox Splitterに比べると劣化してると受け取られることの方が多そうで、報われないことに一生懸命になってるなー感が自分である。

とはいっても、自分で使う分にはとりあえずこれだけ動いてくれれば十分だし、旧版の設計で今後もずっと自分でメンテナンスし続けるのは絶対に無理だし、もっといいやり方が見つかるまでは、この路線を変えることは多分無いと思う。

シス管系女子 第9話「コマンド履歴をもっと使おう」 - Apr 09, 2012

表紙にも載ってなくてあんまり存在を知られてないっていうか忘れられてるくさいので、マメに宣伝していこうと思います……

Linuxの主にコマンドライン関係のTips、小ネタ、豆知識をゆるゆると紹介・解説するマンガの「シス管系女子」をこっそり連載中の日経Linux 5月号が発売されました。 (本編中の1コマ) 今回は前回に引き続き、Bashのコマンド履歴の話です。

ところでバックナンバーを見返していて気付いたのですが、他のライターの方にもご覧頂けているようで、確か3月号か4月号の記事でtmuxの紹介の回に言及していただけてました。こういうのは素直に嬉しいですね。

Ez Sidebarを数年ぶりに更新した - Apr 07, 2012

とかなんとか発言した舌の根も乾かないうちにEz Sidebar 4.0.2012040701を公開した。実験的にやってみたら案外あっさりできたので、その勢いで完成まで一気に。実質的にほぼ0からのスクラッチで、基本設計が全く別物になっていてコードの共有部分はほとんど無い。

旧版ではサイドバー用のウィンドウを物理的に(DOMツリー的に)別ウィンドウとして開いていて、パネル内のスクリプトに対してどうやってブラウザウィンドウの中にあるように見せるかという所が技術的な鍵だった。例えばwindow.parent.gBrowserにアクセスされたら、最も手前にあるブラウザウィンドウを探してきてそのgBrowserを返す、みたいな感じで。そういう強引なことをやってたから、つくづく、よくあんなんで動いてたなという感じだ。

今回の再実装では、根本的な考え方は至極単純で、ウィンドウの内容が初期化されるタイミングで<panel>の中にサイドバーのボックスを丸ごと移動して、以後はその<panel>を「別ウィンドウに切り離されたサイドバー」として表示している。これだとサイドバーは相変わらず元のウィンドウのDOMツリーの中に存在しているから、パネル内のスクリプトから見た時に普通に親のフレームとしてFirefoxのウィンドウにアクセスできるし、Firefoxのウィンドウの側からもパネルの内容を普通にサブフレームとして認識できる。Firefoxのウィンドウが複数ある時は最前面のウィンドウの<panel>だけを表示しておき、ウィンドウが切り替わったタイミングで同じ位置・同じ大きさに<panel>を表示する、という事をやってるので、見た目的には1つの<panel>が個々のFirefoxのウィンドウとは独立して存在しているように見えなくもない。他にも、ドラッグ操作での移動とかリサイズとか、ただの<panel>をウィンドウっぽく動かすために細かい所で違和感が出ないように色々やってる。

何故旧版では<panel>を使わなかったのかというと、やりたくてもやれなかったんですよ。サイドバーは一種のインラインフレームなんだけど、確か昔は<panel>の中にインラインフレームを置くとまともに動作しなかったと思う。そういう細かい技術的な障壁が当時は色々あって、Ez Sidebarのような事をどうしてもやりたいとなると、旧版のようにダーティなハックをたくさん仕込まないといけなかった。それが今では、「こう書いたらこう動いて欲しいよね」という書き方をすればだいたいフツーに動いてくれるわけですよ。隔世の感だ。

あと、バージョン3.2(1つ前のバージョン)にあった機能を全部引き継いでるわけではなくて、というかサイドバーをメインウィンドウから切り離して表示する機能以外は全部バッサリ切り捨てた。All-in-One Sidebarのような有名所のアドオンが既にそういう機能を持ってるみたいだから、わざわざ同じ機能を作らなくても、そっち使えばいいじゃんという話です。Ez Sidebarは、他のアドオンが提供してくれない機能だけに絞って提供した方が意義があるはず……と思って。

過去にこのアドオンの名前を「Sidebar Window」から「Ez Sidebar」に変えたのは、サイドバーの切り離し以外の機能も色々付けたからだったんだけど、今回のリリースで機能的には最初の物より低機能な所に逆戻りしてしまった。皮肉な結果だ。

Fox SplitterのせいでユーザのFirefox 3.6からの移行が進まないって言われた件 - Apr 02, 2012

Linuxでwmctrlを使うようにしたバージョンのFox Splitterを今日付で公開した。

なんだかんだで最近腰が重いんだけどその重い腰を上げてリリースのための作業をやろうと思った背景の1つには、Mozillaの中の人からメールで表題の件について連絡があったからだ。既知のバグがあってmasterでは直ってるのにリリースされていない、という状況ではそのメールに返信するのが憚られる……と思って、慌てて細かい所を直してリリースしたというわけ。これも罪悪感駆動開発な気がする。

Fox Splitterのユーザが古いバージョンを使い続けている最大の理由は、AMOでFox Splitter 0.xから2.0への自動アップデートが行われないからじゃないかと思ってる。諸々の事情でFox Splitter 2.0では旧版からアドオンのIDを変えないといけなかったので、AMOのサイト上ではFox Splitter 2.0と0.xが別々のアドオンとして登録されてて、Fox Splitter 0.xのユーザにはFox Splitter 2.0が自動アップデート経由で提供されない。2.0への移行は、完全にユーザの自由意志に任せざるを得ないという事になっている。使い勝手がどうとか以前に、勝手にアップデートが下りてくるかこないかがネックになってるっていう予想だ。

強権的手段として、「単にFox Splitter 2.0を自動的にインストールして、その後Fox Splitter 0.xを削除する」というだけの内容のアドオンをFox Splitter 0.x最新版としてアップロードすれば、Fox Splitter 0.xから2.0への移行を強制することはできるけど……2.0の方には否定的なレビューが多く付いていて評価も低い(旧版は星2つ以下は15%なのに対し、新版は星2つ以下が57%……まあ母数が圧倒的に少ないから統計的にはあんまり意味がないかもなんだけど)という現状を見ると、そこまでやっちゃっていいっていう自信をまだ持てずにいる。

4月4日追記。Mozillaの中の人から「ちょうどそういう(Fox Splitter 0.x系の新バージョンとして、Fox Splitter 2への自動アップデート機能を含んだ物をリリースするという)方法について提案しようと思ってた所だった」的なレスポンスがあったので、春の嵐で早退したのをいいことに頑張って書いてみたんだけど、死ぬほどめんどかった。

Fox SplitterのLinuxでの挙動の改善と、Mac OS Xで残された課題 - Mar 25, 2012

Fox SplitterをWindows以外で使った時に 実にパネェ感じでストレスフルな挙動を示す件について、とりあえずLinuxではちょっとだけ改善できた気がする。

要点を先にまとめておくと、こういうことだ。

  • Windows上では以前から、ウィンドウの1つが選択されて最前面に来たら、グループ化された他のウィンドウもそれによって「押し上げられ」て最前面に来る、という挙動になっていた。
  • でもFirefoxの仕様上の制限で、LinuxとMac OS Xではそれができていなかった。
  • 今回、Linuxではwmctrlを呼び出すことによってWindows上と同じような挙動を再現できるようになった。
  • Mac OS Xで同じ事ができるのかどうかは分からないままである。
  • JSDeferredはやっぱり素晴らしいです。

以下、背景も含めた詳しい話。

続きを表示する ...

Page 16/241: « 12 13 14 15 16 17 18 19 20 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき