Flex3.5では、stageにリスナ登録したmouseUpイベントハンドラが二重に動作することがある

またFlex3.2とFlex3.5の違いを発見したのでメモ。

事象

stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler); という形で application領域外で起こったmouseUpイベントを拾う実装をしていた。
Flex3.2 では問題なかった。しかし Flex3.5 になると、mouseUpイベントがapplication領域外で起こった場合、stage_mouseUpHandlerが2度呼ばれるという問題が発生した。この問題は、mouseUpイベントの前にデータグリッドを操作(マウス押下による行選択などを)したときのみ発生する。

実装イメージ

public function init():void {
  // ...
  obj.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
  stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
}
public function mouseDownHandler(event:MouseEvent):void {
  // ...
  obj.startDrag();
}
public function stage_mouseUpHandler(event:MouseEvent):void {
  trace("event.target: " + event.target);
  obj.stopDrag();
  // ...
}

原因は分かっていないが、event.targetを調査したところ以下のことが分かった。

■データグリッド操作をしていない場合

event.target: stage

■データグリッド操作をした場合

event.target: mouseCatcher
event.target: stage

…mouseCatcherってなにもの?とデバッグしたところ、systemManager.mouseCatcherがstageのイベントハンドラを動かしていることを確認。枠外のmouseUpイベントを二重で拾ってしまっている模様。

更にmouseCatcherについて調べたところ、ネット上では以下の記述しか見つからず。データグリッド操作との関連は結局分からなかった。

mouseCatcher は application 領域外の MOUSE_UP イベントを拾うためのもののようなので、...

http://www.fxug.net/modules/xhnewbb/viewtopic.php?topic_id=1816&forum=16&post_id=7565

対処

原因が分からずすっきりしないところですが…、mouseCatcherからの呼び出しが余分である以上、抑止すれば直ります。。

対処イメージ

public function stage_mouseUpHandler(event:MouseEvent):void {
  if (event.target.name == 'mouseCatcher') {
    return;
  }
  obj.stopDrag();
  // ...
}