« Mac OS X 10.6.3 で samba サーバに書き込み不能 | トップページ | mac の SelectionListener の挙動不審 »

2010年5月13日 (木)

Mac の JPopupMenu の不具合の回避

Popupmenuok

PopupMenu は,通常左のようにマウスポインタがあるメニューが反転表示される。

Popupmenung

ところが,別のウインドウ(この場合シェーマボックス)にフォーカスがある状態で,フォーカスのないウインドウ(この場合スタンプ箱)を右クリックすると,フォーカスはスタンプ箱にうつり,PopupMenu が表示されるが,この PopupMenu ではメニューの反転表示が出ない。この不具合は macintosh のみでおこり,windows ではおこらない。

この不具合の workaround のため,反転表示を無理矢理出そうと思って MouseListener を組み込んでみたが,一旦この状態に陥ると MouseListener が完全に無視されてしまっていることが分かった。

 いろいろ実験してみたところ,JPopupMenu#show の時点で,マウスボタンが押されている状態だとこの現象がおこることが判明した。そこで,JPopupMenu#show の前に MOUSE_RELEASED イベントを待つようにしたらメニューの反転表示が出るようになった。

ui/MyJPopupMenu.java

package open.dolphin.ui;

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.Queue;
import javax.swing.JPopupMenu;

/**
 * Mac の JPopupMenu の問題を回避
 * @author pns
 */
public class MyJPopupMenu extends JPopupMenu {

  @Override
  public void show(Component invoker, int x, int y) {

    EventQueue systemQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
    Queue<AWTEvent> queue = new LinkedList<AWTEvent>(); // event をためておく

    // MOUSE_RELEASED event を待つ,その間に発生した event は queue にためておく
    try {
      while(true) {
        AWTEvent evt = systemQueue.getNextEvent();
        queue.offer(evt); // get した event はためておく
        // mouse で popup した場合
        if (evt.getID() == MouseEvent.MOUSE_RELEASED) break;
        // key 入力で popup した場合
        if (evt.getID() == KeyEvent.KEY_RELEASED) break;
      }
    } catch (InterruptedException ex) {
      System.out.println("MyJPopupMenu.java: " + ex);
    }

    // ためておいた event を post する
    while (true) {
      AWTEvent evt = queue.poll();
      if (evt == null) break;
      systemQueue.postEvent(evt);
    }

    super.show(invoker, x, y);
  }
}

« Mac OS X 10.6.3 で samba サーバに書き込み不能 | トップページ | mac の SelectionListener の挙動不審 »

OpenDolphin」カテゴリの記事