JDK-6539458 : JPopupMenu does not display if invoker is instance of JWindow
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-03-27
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u4Fixed 7 b21Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
A call to JPopupMenu.show(Component invoker, int x, int y) will fail to show the JPopupMenu if the invoker passed in is a JWindow.  A call to the JPopupMenu "isVisible()" method will return true, but the popup menu will not actually be displayed.

This problem does not occur with JDK 1.5.0_11.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
The source code provided in "Source code for an executable test case" will reproduce the problem.  Compile and run, then right click in the gray window which appears in the upper left hand corner of the screen.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The test program program should display a popup menu with a single menu option called "quit".  The following message (or similar) should be displayed on stdout:

Showing menu at java.awt.Point[x=71,y=76] isVisible: true isValid: true

ACTUAL -
No popup is displayed.  The message printed out on stdout shows that the "isVisible" method on the popup menu is returning true, and that the location of the menu is right in the middle of the box, where it should be:

Showing menu at java.awt.Point[x=74,y=86] isVisible: true isValid: true


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JWindow;

public class Main {
  
  /** Creates a new instance of Main */
  public Main() {
  }
  
  /**
   * Mouse adapter which listens for mouse events and shows a popup menu as
   * required.
   */
  static public class PopupListener extends MouseAdapter {
    JPopupMenu menu;

    public PopupListener(
      JPopupMenu menu
    ) {
      this.menu = menu;
    }
    
    public void mousePressed(MouseEvent e) {showPopup(e);}
    public void mouseReleased(MouseEvent e) {showPopup(e);}
    private void showPopup(MouseEvent e) {
      if(e.isPopupTrigger()) {
        // This doesnt' work if e.getComponent() is a JWindow
        menu.show(e.getComponent(), e.getX(), e.getY());
        
        System.out.println(
          "Showing menu at " + menu.getLocationOnScreen() +
          " isVisible: " + menu.isVisible() +
          " isValid: " + menu.isValid());
      }
    }
  }

  
  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    JWindow window = new JWindow();
    window.setBounds(10, 10, 100, 100);
    
    JPopupMenu popupMenu = new JPopupMenu();
    JMenuItem quit = new JMenuItem("Quit");
    quit.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    });
    popupMenu.add(quit);
    
    window.addMouseListener(new PopupListener(popupMenu));
    
    window.setFocusable(true);
    
    window.validate();
    window.setVisible(true);
  }
  
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Instead of calling JPopupMenu.show() and passing the JWindow:

private void showPopup(MouseEvent e) {
  Point componentLocation = e.getComponent().getLocationOnScreen();
  menu.show(null, componentLocation.x + e.getX(), componentLocation.y + e.getY());
}

Release Regression From : 5.0u9
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
SUGGESTED FIX webrev for the fix can be found at http://sa.sfbay.sun.com/projects/awt_data/7/6539458.0 --- /export/work/son/tests/java/awt/6539458/v0/webrev/src/windows/native/sun/windows/awt_Window.cpp- 2007-08-02 12:03:34.000000000 +0400 +++ awt_Window.cpp 2007-07-24 12:23:56.000000000 +0400 @@ -201,12 +201,12 @@ if (m_grabbedWindow != NULL) { m_grabbedWindow->Ungrab(); } m_grabbed = TRUE; m_grabbedWindow = this; - if (sm_focusedWindow == NULL) { - // we shouldn't perform grab in this case (see 4841881) + if (sm_focusedWindow == NULL && IsFocusableWindow()) { + // we shouldn't perform grab in this case (see 4841881 & 6539458) Ungrab(); } else if (GetHWnd() != sm_focusedWindow) { _ToFront(env->NewGlobalRef(GetPeer(env))); // Global ref was deleted in _ToFront }
07-08-2007

EVALUATION After discussion with swing I've decided that it will be enough for now to just allow grab for unfocusable toplevels. It will fix this particular problem and wil not affect 6458497.
07-08-2007

EVALUATION tested more and found that after my changes 6458497 (which is almost the same as 4841881) is reproducible :( it looks like I have a nice choice :-/
05-06-2007

EVALUATION Well, I have removed fix for 4841881 and the test works fine, but the test fo 4841881 doesn't :( Sometime frame (from which I'm alt-tabbing) goes back to front and returns foxus to itself. This is because of antoher code in the AwtWindow::Grab(): if (GetHWnd() != sm_focusedWindow) { _ToFront(env->NewGlobalRef(GetPeer(env))); // Global ref was deleted in _ToFront } After I removed these lines both tests work fine. Unfortunately these lines were in the code from the initial implementation of netive grab, so it is not clear why their were added :( Need to discuss this with Swing team.
31-05-2007

EVALUATION it looks like it is a regression of fix for 4841881. We do not perform grab on unfocused window, but the window in the test is unfocusable, and so it is not focused :(
17-04-2007

EVALUATION For some reason after the popup is shown we get UngrabEvent which closes the popup Note that UngrabEvent doesn't get generated for JDialog reassigned to AWT team Here my test case which shows the problem more clearly: import sun.awt.UngrabEvent; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class bug6539458 { private static void createGui() { final Window w = new JWindow(); // For JDialog it works fine // final Window w = new JDialog(); Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { public void eventDispatched(AWTEvent event) { if (event instanceof UngrabEvent) { System.out.println("UngrabEvent !!!"); } } }, 0xFFFFFFFF); final JPopupMenu menu = new JPopupMenu(); JMenuItem item = new JMenuItem("Quit"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); menu.add(item); w.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { menu.show(w, 30, 30); } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { menu.show(w, 30, 30); } } }); w.setSize(200, 200); w.setLocationRelativeTo(null); w.setVisible(true); } public static void main(String[] args) throws Exception { SwingUtilities.invokeLater(new Runnable() { public void run() { bug6539458.createGui(); } }); } }
06-04-2007