United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-8006417 JComboBox.showPopup(), hidePopup() fails in JRE 1.7 on OS X
JDK-8006417 : JComboBox.showPopup(), hidePopup() fails in JRE 1.7 on OS X

Details
Type:
Bug
Submit Date:
2013-01-16
Status:
Closed
Updated Date:
2013-07-10
Project Name:
JDK
Resolved Date:
2013-01-18
Component:
client-libs
OS:
os_x
Sub-Component:
java.awt
CPU:
generic
Priority:
P1
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:
7u40 (b22)

Related Reports
Backport:
Backport:
Backport:
Backport:
Backport:
Backport:
Backport:

Sub Tasks

Description
FULL PRODUCT VERSION :
JDK 7u9

ADDITIONAL OS VERSION INFORMATION :
Apple Mac OS X 10.7 (Intel) (64-bit)

A DESCRIPTION OF THE PROBLEM :
An immediate call to JComboBox.showPopup() after JComboBox.hidePopup() does not lead to showing of a popup menu in JDK 7 on OS X, instead of this the popup menu just flashes. However the popup menu is always shown in JDK 6.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the attached source code.
2. Click into any place of a displayed frame.

REPRODUCIBILITY :
The bug is reproduced always.

---------- BEGIN SOURCE ---------- 
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

public class TestWTDComboBox {
    static JComboBox kb = null;
    static boolean dataPopulated = false;
    static AWTEvent event = null;
    static JFrame frame;

    public static void main(String[] args) {
        frame = new JFrame("Creating a JComboBox Component");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 400);

        JPanel panel = new JPanel();
        String anArray[] = {"BCA", "MCA", "PPC", "CIC"};
        kb = new JComboBox(anArray) {
            @Override
            public void showPopup() {
                if (!dataPopulated) {
                    frame.dispatchEvent(event);
                }
                super.showPopup();
            }
        };
        kb.addPopupMenuListener(new PopupMenuListener() {
            @Override
            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                System.out.println("hello");
            }

            @Override
            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                kb.setPopupVisible(false);
            }

            @Override
            public void popupMenuCanceled(PopupMenuEvent e) {}
        });
        panel.add(kb);
        frame.add(panel);
        frame.addMouseListener(new MouseListener() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("hello111");
                event = e;
                test();
            }

            @Override
            public void mousePressed(MouseEvent e) {
                System.out.println("hello111");
                event = e;
                test();
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                System.out.println("hello111");
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.println("hello111");
            }

            @Override
            public void mouseExited(MouseEvent e) {
                System.out.println("hello111");
            }
        });

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                frame.setVisible(true);
            }
        });
    }

    public static void test() {
        Object prevSel = kb.getSelectedItem();
        boolean isDropDown = kb.isPopupVisible();
        kb.hidePopup();
        kb.removeAllItems();

        kb.addItem("none");
        kb.addItem("none1");
        kb.addItem("none2");
        kb.addItem("none3");
        dataPopulated = true;
        kb.setSelectedItem(prevSel);

        kb.showPopup();
        dataPopulated = false;
    }
}
---------- END SOURCE ----------
                                    

Comments
The issue was successfully reproduced on:

- JDK 7u12 b06 (latest)
- JDK 7u4 b11 (the first JDK 7 from Oracle)
- JDK 8 b69

This issue happens, because of concurrency between internal processing of calls to JComboBox.hidePopup() and JComboBox.showPopup() methods. A deep research showed the following facts:

1. Processing of "sun.awt.UngrabEvent" cancels JPopupMenu of JComboBox, what is the reason of this bug.
2. A call to JComboBox.hidePopup() generates "sun.awt.UngrabEvent", which is processed asynchronously, in its underlying code (the method "public void stateChanged(ChangeEvent e)" of javax.swing.plaf.basic.BasicPopupMenuUI.MouseGrabber) in JDK 7, JDK 8 on OS X.
3. Behavior from point #2 does not happen neither on Windows OS, nor on Linux OS, because of a particular implementation of "ungrab(Window w)" method of "sun.awt.SunToolkit" for OS X.

A pseudo code which describes a process leading to this bug is presented below.

1. JComboBox.hidePopup() - (the popup menu becomes hidden)
    ...
        ((sun.awt.SunToolkit)tk).ungrab(grabbedWindow)
        ....
            "sun.awt.UngrabEvent" is posted to AWT event queue.
    ....
2. JComboBox.showPopup() - (the popup menu becomes shown)
3. "sun.awt.UngrabEvent" is dispatched to JFrame - (the popup menu becomes hidden again)
    ....
        Any shown popup is closed.
    ....

One of possible solutions could be not posting of "sun.awt.UngrabEvent" by "sun.lwawt.LWWindowPeer.ungrab()", when it is called from "sun.lwawt.LWToolkit". A similar strategy is applied in native code of JDK for Windows OS.
                                     
2013-01-16
URL:   http://hg.openjdk.java.net/jdk7u/jdk7u-dev/jdk/rev/58d44352bbf3
User:  alexp
Date:  2013-01-18 14:37:09 +0000

                                     
2013-01-18
URL:   http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/rev/58d44352bbf3
User:  lana
Date:  2013-01-28 20:08:54 +0000

                                     
2013-01-28
Used supplied java test (source code).
Tested under JDK 7u40 b27 on Mac Mini OSX 10.8.3.
No issues encountered.
Closing this issue as Verified.
                                     
2013-06-05



Hardware and Software, Engineered to Work Together