Now browsing the SCRAPBLOG weblog archives.
Linuxテスト環境導入 これまでの経緯
2月頃
拡張機能開発の際にFirefoxのプラットフォームに依存した挙動に頭を悩ませることが多くなり、Windows以外のテスト環境の必要性を切実に感じ始める。
3月20日
VMWare Player(無料)をインストールし、Ubuntu 6.10 VMWare Image 日本語版をダウンロードして起動。いとも簡単にWinXP上でLinuxやFirefoxが使用可能になった。特に何も設定せずにインターネットにもつながるし、Windowsとのファイル共有も可能で便利。しかし、メモリ256MBのせいかUbuntu起動に7~8分近くかかり、動作が極端に遅く、使い物にならない。
3月30日
メモリ512MB(6000円程度のバルク品)を購入して増設。VMWare上でのUbuntuの起動が2~3分程度に短縮され、動作もかなりマシになった。マウスポインタの動きが早すぎで焦るものの、「xset m 1 10」とかやって解決。とはいえ快適といえるほどではなく、とくにタブを切り替える動作なんかにモッサリ感を感じる。また、これはVMWare Player側の問題だけど、ウィンドウサイズを覚えてくれなくて起動するたびに800×600くらいにリセットされるのが微妙に嫌だったり、全画面表示中にマウスを上の方に持っていくと、青いツールバーが表示されるのがかなりウザかったり。多分無料版だからか?でもワンタッチでWinXPとLinuxを行き来できる利便性は半端じゃない。
4月15日
CDから起動が可能なLinuxであるKNOPPIXを試す。KNOPPIX 5.1のISOイメージをダウンロードしてCD-RWに焼き、PCを再起動してCDのドライブから起動させる。しかし”No suitable X-Server found for your card”というエラーが出てXが起動しない。少し調べて、起動時に「boot: dynabook」と打ち込むことで無事解決。今回はVMWare上ではないのでさすがに動作は快適である。しかしインターネットにつながらない(設定方法がよくわからない)、ファイルを編集して保存しても、あとでWindows上から内容を取り出せない(もしかしたら可能かも?)などといった問題があり、開発環境としては不足。でも、Ubuntuと比べて画面の雰囲気とかがWindowsに近い感じで好き。
4月16日
第三の方法として、WindowsとLinuxのデュアルブート環境構築を試案中。でもパーティションを切る必要があったりして、やったことない自分にはハードルが高そう。
nsIPopupBoxObject::enableKeyboardNavigator
通常、 ポップアップ (*1) を開いているときは、キーボードからの入力が効かなくなる。このキーイベント横取りは nsIPopupBoxObject::enableKeyboardNavigator(false) で無効化することができる。このメソッドは enableRollup 同様、 showPopup した直後に呼び出す必要がある。一方ツールチップ (*1) ではデフォルトでキーボード入力イベントの横取りはしないようになっている。
*1 ここでいうポップアップとは popup か tooltip 要素を showPopup メソッドの引数 popuptype を「popup」にして開いたものを指し、ツールチップとは引数 popuptype を「tooltip」にしたものを指す。
ところで、 Firefox 3 では nsIPopupBoxObject::setConsumeRollupEvent というメソッドも使用可能だが、これがどういう効果があるのかよくわからん。
nsIPopupBoxObject::enableRollup
通常、 ポップアップを開いているときは、Firefox のウィンドウ内のどの部分をクリックしてもクリックイベントが横取りされ、クリックイベントが発生する代わりにポップアップが閉じられる。この動作は nsIPopupBoxObject::enableRollup メソッドで変更が可能である。 enableRollup はポップアップを開いた後に呼び出す必要があることに注意。
ここでひとつプラットフォーム依存の悩ましい問題があり、 Windows では enableRollup(false) すると、ツールチップのようにポップアップ内に配置したボタンなどの要素がクリック不可となってしまう。
Windows 以外での環境での動作を知りたいので、テストケースを使った動作確認よろしくお願いします。
popup testcase
—
Windows + Firefox 2 では以下のようになるはずです。
Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
[1] x | o
[2] o | x
[3] o | x
[4] o | x
—
Mozilla/5.0 (Windows; U; Windows NT 5.1; ja-JP; rv:1.9a4pre) Gecko/20070405 Minefield/3.0a4pre
上記と同じ結果。
—
一方、Linux + Firefox 2 ではポップアップ内のボタンは常にクリック可能。
Mozilla/5.0 (X11; U; Linux i686; ja; rv:1.8.1.1) Gecko/20060601 Firefox/2.0.0.1 (Ubuntu-edgy)
[1] x | o
[2] o | o
[3] o | o
[4] o | o
テストケースにはありませんが、 enableRollup(true) も試したところ、OKダイアログを閉じるときにクラッシュするバグがありました。
ポップアップとツールチップの仕様がOSによって違う (1への補足)
SCRAPBLOG : ポップアップとツールチップの仕様がOSによって違う (1) の補足
Windows + Firefox 2 で、以下の動作を確認。
1. テストケースを新しいタブで開く。
2. [popup as tooltip] か [tooltip as tooltip] ボタンを押してポップアップ・ツールチップを開く。
3. ツールチップを閉じずに別のタブへ切り替える。
4. [label] [menuitem] [button] [toolbarbutton] それぞれをクリックしてみる。
すると、なぜか4つすべての要素がクリック可能である。
ポップアップとツールチップの仕様がOSによって違う (2)
<tooltip> 要素には、マウスがツールチップ上から逃げたときに自動で閉じる仕組みがあるのだが、その挙動が Windows と Linux とで異なるのが悩ましい。
まず前回と同じテストケースを開き、 [tooltip as popup] か [tooltip as tooltip] ボタンをクリックしてツールチップを表示させる。次にツールチップ上へマウスを乗せてからツールチップの外へ移動する。
このとき、 Windows + Firefox 2 ではすぐにツールチップが閉じる。しかし、 Linux ではすぐには閉じず、さらにもう一度ツールチップ上に乗る→ツールチップ外へ移動を繰り返したときにツールチップが閉じる。この動きは果たして正しいのだろうか?
この <tooltip> 要素特有の自動で閉じる仕組みは XBL にて実装されていて chrome://global/content/bindings/popup.xml の <handler event=”mouseout”> を見ればわかる。
Windows では event.relatedTarget を調べてツールチップ外へ逃げたことを識別可能であるようだが、 Linux ではなぜか event.relatedTarget が null となり、代わりに _mouseOutCount の値が2になった時点でツールチップを閉じているようだ。
ソースコードのコメントを読むと、マウスがツールチップ上に乗った時点で _mouseOutCount が1となり、マウスがツールチップから逃げた時点で _mouseOutCount が2となってツールチップが閉じられるような仕組みを想定しているようだ。しかし、実際はマウスがツールチップに乗ったときに発生する mouseout イベントでは event.relatedTarget が null ではないため、 if (!rel) の条件は偽となって _mouseOutCount は増えない。したがって、 Linux では2回ツールチップ外へ逃げたときにツールチップが閉じるという挙動になっている。もしかしてこれはバグだろうか?
なお、Windows + Firefox 3 では、SCRAPBLOG : Bug 373518 – event.relatedTarget is never set when leaving popup にあるようにツールチップ外へ逃げたときの event.relatedTarget が null となるため、 Linux とまったく同じ動きになる。そもそも Bug 373518 自体もバグなのか何なのかよくわからなくなってきた。
例によってMacでの動作は未確認ですので、情報お待ちしております。
ポップアップとツールチップの仕様がOSによって違う (1)
ポップアップとツールチップの仕様が Windows と Linux で色々と違いがあって悩ましい。
まず、 <popup> と <tooltip> 要素内に <button> や <menuitem> などのクリックが可能な要素をいくつか配置する。次に、それぞれを showPopup(event.target, -1, -1, type, "bottomleft", "topleft") などとやってツールチップとして表示させる。
すると、 Linux では <button> も <menuitem> も問題なくクリック可能である。多分どんな要素に対してもマウスクリックイベントが伝わりそうな雰囲気。
しかし、 Windows では <button> をクリックしようとしても、何か透明な壁にさえぎられているかのようにクリックできない。なぜか <menuitem> だけはこの壁をすり抜けてクリックすることができる。これは憶測だが、この透明な壁によるマウスクリックイベントの奪取は DOM のレイヤーよりも上で行われているため、 キャプチャフェーズに対するイベントリスナをセットしたりしても、一向にクリックイベントを発生させることができない。
Mac ではどうなるか知らん。情報求む!
Software Design 2007年4月号
Software Design 2007年4月号
「Firefox拡張機能開発チュートリアル」の5章「Firefox拡張機能を作ってみよう!」を執筆しました。
現在発売中ですので、拡張開発を始めようとしている方は参考にしてください。
使用したソースコードはこちらで入手可能です。
XBL:XBL 1.0 Reference:Elements – MDC
XBL:XBL 1.0 Reference:Elements – MDC の和訳が完了。のべ6時間くらいかかった。
以下に意味がさっぱりわからん場所をメモしておきます。わかる方は補完よろしくお願いします。
- bindings 要素の解説
(explicitly or inherited)
→勘+意訳「そのバインディングが継承されたものかそうでないかに関わらず」 - bindings 要素の注意
URI in namespace declarations is an opaque string used to uniquely identify the namespace. It doesn’t have to (and often it doesn’t) point to some actual schema or a namespace-related resource.
→難しい… - children 要素の解説
Only immediate children are matched against the selector.
→children 要素直下にある要素だけが includes 属性とのマッチングが行われるということ? - implementation 要素の解説
For example, in JavaScript the value of this attribute represents the name of the corresponding class that is constructed for the implementation.
→勘で和訳「例えば JavaScript では、この属性の値が、その実装のために生成されたクラス名に対応します。」
Bug 373518 – event.relatedTarget is never set when leaving popup
mouseover イベントの event.relatedTarget によってマウスがどこから来たか調べたり、 mouseout イベントの event.relatedTarget によってマウスがどこへ行くのかを調べることができる。ところが Firefox 3.0a3pre で試したところ、 popup 要素上で発生した mouseover/mouseout イベントの relatedTarget が null であるため、マウスがポップアップを離れてどこへ行ったのかを判別することができないという問題が発生した。 Firefox 2 では問題なく動作するので、おかしいなと思い Bugzilla へ登録しておいた。
Bug 373518 – event.relatedTarget is never set when leaving popup
ついでに MDC に DOM:event:Comparison of Event Targets – MDC という未完成記事があったので、 mouseover/mouseout に対する target と relatedTarget の違いについて加筆しておいた。
ユーザのアイドル時間を測定する nsIIdleService
Firefox 3 (Minefield) 以降限定だが、 nsIIdleService を使ってユーザのアイドル時間を測定したり、ユーザが一定時間何も操作しなかったことを検知したり、さらにその状態から操作を開始したことを検知することができる。言わずもがな、メッセンジャーのようなアプリケーションでユーザが退席中かオンラインかを見分ける用途などに最適だ。
まずXPCOMサービスを取得する。
gIdleService = Components.classes["@mozilla.org/widget/idleservice;1"] .getService(Components.interfaces.nsIIdleService);
現在のアイドル時間を取得するなら、 idleTime プロパティを調べるだけ。単位はミリ秒である。
setInterval(function() { document.getElementById("idleTime").value = Math.round(gIdleService.idleTime / 1000) + " 秒"; }, 1000);
ユーザが○○分間何もしなかった(マウスを動かしたりキーボードに触れたりしなかった)ことを検知して何らかの処理を実行するためには、 nsIObserver インタフェースを実装したオブザーバを作る。 observe メソッドへ渡される引数は…
aSubject | nsIIdleService 自身 |
aTopic | 指定時間が経過してアイドル状態に突入した場合は「idle」 アイドル状態から通常状態へと戻った場合は「back」 |
aData | 現在のアイドル時間 |
gIdleObserver = { observe: function(aSubject, aTopic, aData) { var status; switch (aTopic) { case "idle": status = " 退席中..."; break; case "back": status = " 戻りました"; break; } document.getElementById("log").value += new Date().toLocaleTimeString() + status + " "; } };
オブザーバを addIdleObserver メソッドで登録する。第2引数はアイドル状態になるまでの時間(単位は分)である。
gIdleService.addIdleObserver(gIdleObserver, 1);
上記サンプルでは、1分間(厳密には+5秒のディレイあり)何も操作しないと「退席中…」が表示され、その後何か操作をすると「戻りました」が表示される。
用が済んだら removeIdleObserver でオブザーバを解除するのをお忘れなく。
gIdleService.removeIdleObserver(gIdleObserver, 1);