Mozilla Flux

Mozilla関係の情報に特化したブログです。

ブックマークメニューが正常化

ブックマークメニューの不審な挙動』で紹介した、ユーザーが意図しないタイミングで「ブックマークに追加しました」というメニューがポップアップするバグ。これがついに、最新のShiretoko(3.1b4pre, ID:20090317050332)で解消された。つまり、Firefox 3.5ではこのバグに悩まされなくて済む。さらに、Firefox 3.0.x系列向けのパッチも作成されており、投入の承認を待っているところだ。うまくいけば、Firefox 3.0.9でもこの問題が解消される。

原因と対処法を詳しく見てみよう。「Bug 406646 - Clicking to open slow menu (e.g. Bookmarks) invokes first item in menu (e.g. "Bookmark This Page")」のコメント#156で、MozillaのRobert O'Callahan氏が解説を加えている。それによると、次のようなプロセスを経て従来のバグが発生していたという。

  1. mouse-downイベントが発動し、ブックマークのポップアップメニューでnsXULPopupManager::ShowMenuのトリガーとなる。
  2. それがnsXULPopupManager::ShowPopupCallbackのトリガーとなり、非同期のnsXULPopupManager::FirePopupShowingEventを待ち行列(キュー)に入れる。
  3. nsXULPopupManager::FirePopupShowingEventが、nsXULPopupManager::ShowPopupCallbackを呼び出し、ポップアップにnsXULPopupManager::mPopupsを加える。
  4. ポップアップのポジションがセットされる前にmouse-upイベントが届く。nsMenuPopupFrame::SetPopupPositionはまだnsMenuFrame::DoLayoutから呼び出されていない。ポップアップを開くことがどのようにしてnsMenuFrame::DoLayoutのトリガーになるかは定かではないが、非同期であることは間違いなく、DoLayoutの前にmouse-upが紛れ込むのを許してしまっている。
  5. mouse-upはルートウィジェットをターゲットにしていて、それはいい。イベントはPresShellに送られる。
  6. PresShell::HandleEventは、すべての開かれたポップアップを検索して、このマウスイベントを処理すべきかを見るよう記述されている。そのためにnsXULPopupManager::GetOpenPopupsを呼び出し、それが、開かれてはいるが目には見えないポップアップを返す。
  7. 開かれてはいるが目には見えないポップアップが検出され、それに対してイベントが発行される。

このような分析に基づき、PresShell::HandleEventの検索で、開かれてはいるが目には見えないポップアップを除くようにすれば問題は解決する、というのがO'Callahan氏の見立てだ。

専門的で難しい内容なため、筆者もその内容をちゃんと理解できているわけではないのだが、コメント#148も参照すると、何を言っているのかおぼろげながら見えてくる。重要なのは上記リストの後半部分だ。

まず、ブックマークメニューが位置調整される前に、mouse-upイベントが実行されていることが問題の根幹といえよう。いったん左クリックで押し下げられたマウスボタンが、元の位置に戻るとき、Firefoxにその情報を伝えるわけだが、位置調整が未了のため、「このページをブックマーク」という最初の項目をクリックしたかのように扱われてしまう。もちろん、通常のメニュー処理でもmouse-upを感知してイベント処理を進めていることが背景にある。

次に、メニューは、ふつう、オープン→位置調整→可視化という手順を経ている。したがって、可視化されたメニューでだけmouse-upイベントを処理する形に変えれば、位置調整未了の場面で起こる、上記のような問題は防止できる。なぜなら、mouse-upの情報を検出しても、イベントを処理すべきメニューが発見されないからだ。

最後に、この一連の処理は、ブックマークメニューを開く場合に限られない。メニューバー内の他のメニューはもちろん、ページ内でコンテクストメニューを開くときも該当する。おそらく、ブックマークメニューは、Placesデータベース(履歴とブックマークを蓄積)とのやりとりがあるので位置調整が遅れ、不具合が目立ってしまっていたのだろう。だが、原理的には他のメニューでも発生しうる問題であり、本バグのパッチも、これらすべてに対処するものとなっている。

というわけで、ブックマークメニューだけでなく、コンテクストメニューも含め、クリックした覚えのないメニューをクリックしたことになるバグは消えた。ただ、何事にも100%ということはないので、なお同じ問題が発生するケースは存在するだろう。それでも、ほとんどのユーザーはこの悩ましい現象から解放されるはずだ。