the heavenly school #2

そういうわけでいろいろ調べてみると:

  • 言うまでもなく、vimperator/pentadactyl は Firefox の UI を限りなく vim に近づけるエクステンションだ。ちなみにググった限りでは、vimperator は Firefox を「vim みたいな Firefox」にするのがゴールなのに対し、pentadactyl は「web ページを見られる vim」にするのがゴールのようだ
  • この手のエクステンションの宿命として、キーボード入力は誰のものかを常に意識する必要がある。web ページのスクリプトでハンドリングできる以上、本質的には web ページ上のキーボード入力はその web ページのものだ。vimperator のようなエクステンションは、web ページがキーボード入力を処理していない場合のみ成り立つ。wasavi はそれ自身が全てのキーボード入力を処理するので、当然両立し得ない
  • vimperator 側では、liberator.modules.modes.passAllKeys に true を与えることで、vimperator の動作をスルーさせることができる。また、vimperator にはプラグインの機構があり、例えばタブを切り替えたときに任意のスクリプトを走らせることができる。プラグインは ~/.vimperator/plugin(windows 環境では %HOME%\vimperator\plugin)の下に置く
  • wasavi がページ上に生成されたかどうかは、http://wasavi.appsweets.net/ をソースに指す iframe が存在するか、でとりあえず判断できる
  • つまりプラグインとしてのスクリプトで、DOM の変更を監視し、wasavi の iframe が生成されたら passAllKeys = true にするようにすればいいはずだ。

ということでそんな感じでプラグインを書いてみたのだが、うまく行かない。document.body 直下に iframe が追加・削除されたかどうか監視するために、MutationObserver を生成し、observe() する。
ところがこれが失敗する。MutationObserver#observe() するには対象の要素への参照が必要だ。つまりまず対象のページの window への参照が必要だ。そんなわけでこんな関数を:

function getWindow () {
var wnd;
try {
wnd = liberator.modules.Buffer.focusedWindow;
if (!wnd) {
log('target window not found.');
}
}
catch (e) {
log('exception occured while retrieving focusedWindow: ' + e.message);
wnd = null;
}
return wnd;
}

LocationChange に引っ掛けたハンドラ内で動かすと focusedWindow を参照したところで例外が起こる。vimperator 3.5 のソースを見てみると

getFocusedWindow: function (win) {
win = win || config.browser.contentWindow;
let elem = win.document.activeElement;
let doc;
while (doc = elem.contentDocument) {
elem = doc.activeElement;
}
return elem.ownerDocument.defaultView;
},

で、つまり elem が null のとき while の条件節でエラーになる。そりゃそうですね。

うわーん
動かないよー
うーんどうやって window を得たらいいのかな……。

Leave a Reply

Your email address will not be published.