Dec 02, 2010

ツリー型タブとマルチプルタブハンドラとHTML5のドラッグ&ドロップ

Tree Style TabMultiple Tab Handlerのドラッグ&ドロップ周りのコードを色々書き直した。

Tab Utilitiesとの衝突

発端は、「Tab Utilitiesと一緒に使うとタブのドラッグ&ドロップが期待通りに動かない」という報告だった。しかし、「また衝突かよー」と思いながらメールの内容を読むと、想像していたのとはちょっと状況が違った。

僕はてっきり、Tab Utilitiesのイベント処理とツリー型タブのイベント処理がかちあって変な事になってるんだとばかり思ってたんだけど、そうではなくて、Tab Utilitiesが提供する「複数のタブを選択してまとめてドラッグ&ドロップする」機能で複数のタブを1つのタブの上にドロップしても、選択されていたタブのうち1つしかドロップ先のタブの子タブにならない、という状況だった。その人はすでにTab Utilitiesの作者にも問い合わせていたようで、Tab Utilitiesの作者の回答に「ツリー型タブにマルチプルタブハンドラのためのコードしか含まれていないのがそもそもの問題だ。ツリー型タブの方で修正してもらってくれ。」みたいなコメントがあったそうだ。

それでTab Utilitiesを見てみたら、確かに複数のタブを選択する機能があったんだけど、その時のタブの情報の受け渡しにHTML5のドラッグ&ドロップのイベント複数のデータの指定の仕組みが使われているようだった。

  • マルチプルタブハンドラを最初に作ったときはまだこんなAPIは無かった。
  • タブのドラッグ&ドロップの実装になるべく介入したくなかった。タブがドロップされた時に、そのタブが選択状態だったら、他の選択されているタブも一緒にドラッグされることが意図されていたと判断して、後から他のタブも追従して移動させる、という設計にしていた。

という事情があって、マルチプルタブハンドラではドラッグ操作のイベントそのものには介入しないようにしてたんだけど、Tab Utilitiesがそういう事をやってるんだったら、「複数タブのドラッグ操作」に特化したアドオンであるマルチプルタブハンドラが黙って見てるわけにはいかない。なので、マルチプルタブハンドラではバージョン0.6から、ついでにツリー型タブもバージョン0.11.2010120101から、タブをドラッグ&ドロップするときはドラッグしようとしているすべてのタブをデータトランスファーに渡すようにした。ついでにドラッグフィードバックイメージも自前で生成するようにして、複数タブのドラッグ時はドラッグ中のすべてのタブのサムネイルを重ねて表示するようにしてみた。

それで「ああやっと時代に追いつけたわ」と安心してたんだけど、Windowsでテストしてみたら、せっかく生成したドラッグフィードバックイメージがぜんぜん表示されないんでやんの。どうも、Windows版のFirefox 3.6以前は、mozSetDataAt()で複数のデータを指定するとドラッグフィードバックイメージが表示されないというバグがあるようだ。Ubuntu上のFirefox 3.6や、Windows上でもMinefieldでは問題なかったんだけど。頑張りの報われなさに切なくなった。

ツリー型タブのリファクタリング

ツリー型タブの場合は、タブのドラッグ&ドロップでツリーを編集する場合があるから、マルチプルタブハンドラみたいにTabMoveイベントをトリガーとして後から必要な処理を行うということはできなかった。なので、Firefox自身のドラッグ&ドロップの処理に介入する形の設計にせざるを得なかった。

その後HTML5のドラッグ&ドロップのAPIが実装されて、Firefox 3.5ではFirefoxのタブのドラッグ&ドロップのためのコード自体もそれをベースに書き直された。これはまだFirefox 3.0と同じようなやり方でドラッグ&ドロップの処理に介入できる余地があった。

しかしFirefox 4ではタブのドロップとかドラッグオーバーとかの処理がXBLのイベントハンドラの中にベタ書きされるようになってしまって、メソッドの中に処理を注入するやり方ではドラッグ&ドロップの操作に介入できなくなってしまった。なので、仕方ないからdragstartとかdropとかのイベントにキャプチャリングフェーズで割り込んでツリー型タブの側で全部自分で処理するようにした。

という経緯があって、結果的にツリー型タブのドラッグ&ドロップ周りの処理はFirefox 3.0向けとFirefox 3.5~3.6向けとFirefox 4向けとで3種類の方法が同居してかなりシッチャカメッチャカな状態になっていた。あとタブバー自体のドラッグ&ドロップの処理もあって、それぞれがあちこちに散らばっててだいぶ訳のわからんことになってた。

そんな状態だったから、昨日のリリースでは案の定リグレッションしてドラッグ&ドロップが盛大にぶっ壊れてた。これはもう駄目かもわからんねと思ったので、Firefox 3.0向けのコードを全廃したついでにFirefox 3.5~3.6に対してもFirefox 4向けのやり方を使うようにして、ドラッグ&ドロップのコードを専用のクラスに集めて整理することにした。

安定性とメンテナンス性を取った結果、タブのドラッグ&ドロップのイベント処理はFirefox本体のものを完全に無視する形になっているので、他のアドオンとの機能の両立という点では残念なことになっているかもしれない。タブのドラッグ&ドロップに介入するためのきちんとしたAPIが整理されていれば、こんな思いをしなくて済むのになあ。

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能