RFR: 8290399: [macos] Aqua LAF does not fire an action event if combo box menu is displayed

Prasanta Sadhukhan psadhukhan at openjdk.org
Tue Jul 19 08:30:41 UTC 2022


On Tue, 19 Jul 2022 08:13:23 GMT, Prasanta Sadhukhan <psadhukhan at openjdk.org> wrote:

> When the user types Enter in an editable combo box, Aqua LAF fails to fire an action event if the menu is displayed.
> It seems actionEvent is fired when popup menu is not visible. 
> Fix is to make sure ActionEvent is fired irrespective of popup visiblity as is done in other L&F 
> (for ex, in MetalL&F it calls "ENTER", JTextField.notifyAction, where it calls postActionEvent irrespectively)

test/jdk/javax/swing/JComboBox/JComboBoxActionEvent.java line 91:

> 89:         pfjFrame.awaitAndCheck();
> 90:     }
> 91: }

Tried automating the test but it seems to call BasicComboBoxUI#focusLost when ENTER key is pressed, which calls actionPerformed thus defeating the purpose.




public class TestEditableComboBox
{
    private static JFrame fr;
    private static JComboBox<String> cb;
    private static Point loc;
    private static Dimension dim;
    private static volatile boolean actionDone = false;

    public TestEditableComboBox()
    {
        // Instructions:
        // Click the arrow to display the menu.
        // While the menu is displayed, edit the text to create a new value.
        // Type return.
        // The action listener should be invoked.

        // Using Aqua LAF, the return dismisses the menu but does invoke action listeners.
        // A second return is needed to invoke actions listeners.
        // This behavior is inconsistent with other LAFs and native NSComboBox.

//        if (true) {
//            try {
//                //UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
//                UIManager.setLookAndFeel("com.apple.laf.AquaLookAndFeel");
//            } catch (Exception e) {
//                System.err.println(e.toString());
//            }
//        }

        fr = new JFrame("Test Editable Combo Box");
        String[] values = new String[] { "Apple", "Orange", "Pear" };
        cb = new JComboBox<>(values);
        cb.setEditable(true);
        cb.addActionListener(e -> {
            //actionDone = true;
                System.err.println("Action listener called: " + e.getActionCommand());
                });

        Container c = fr.getContentPane();
        c.setLayout(new FlowLayout());
        c.add(cb);
        fr.pack();
        //fr.setBounds(400, 100, 400, 80);
        fr.setLocationRelativeTo(null);
        fr.setVisible(true);
    }

    public static void main(String[] args) throws Exception {

        java.util.List<String> lafs = Arrays.stream(UIManager.getInstalledLookAndFeels())
                                  .map(UIManager.LookAndFeelInfo::getClassName)
                                  .collect(Collectors.toList());
        for (final String laf : lafs) {
            try {
                try {
                    UIManager.setLookAndFeel(laf);
                    System.out.println("Testing L&F: " + laf);
                } catch (UnsupportedLookAndFeelException e) {
                    System.out.println("Skipping unsupported L&F: " + laf);
                }
                SwingUtilities.invokeAndWait(TestEditableComboBox::new);
                SwingUtilities.invokeAndWait(() -> {
                    loc = cb.getLocationOnScreen();
                    dim = cb.getSize();
                });
                Robot robot = new Robot();
                robot.waitForIdle();
                robot.delay(1000);
                robot.mouseMove(loc.x + dim.width - 2, loc.y);
                robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
                robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
                robot.waitForIdle();
                robot.delay(1000);
                robot.keyPress(KeyEvent.VK_A);
                robot.keyRelease(KeyEvent.VK_A);
                robot.waitForIdle();
                robot.delay(1000);
                robot.keyPress(KeyEvent.VK_ENTER);
                robot.keyRelease(KeyEvent.VK_ENTER);
                robot.waitForIdle();
                robot.delay(1000);
//                if (!actionDone) {
//                    throw new RuntimeException("ActionEvent not fired");
//                }
            } finally {
                SwingUtilities.invokeAndWait(() -> {
                    if (fr != null) {
                        fr.dispose();
                    }
                });
            }
        }
    }
}

-------------

PR: https://git.openjdk.org/jdk/pull/9551



More information about the client-libs-dev mailing list