From c4dc05299d8ace10f4e74ce933c860e0a33b455c Mon Sep 17 00:00:00 2001 From: Satyen Subramaniam Date: Wed, 17 Sep 2025 16:41:15 +0000 Subject: [PATCH] Backport 3e3dff6767f467b53c739c34b4350dd6840534a3 --- .../javax/swing/JPopupMenu/bug4188832.java | 82 ++++++ .../javax/swing/JPopupMenu/bug4212464.java | 142 ++++++++++ .../javax/swing/JPopupMenu/bug4234793.java | 242 ++++++++++++++++++ 3 files changed, 466 insertions(+) create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4188832.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4212464.java create mode 100644 test/jdk/javax/swing/JPopupMenu/bug4234793.java diff --git a/test/jdk/javax/swing/JPopupMenu/bug4188832.java b/test/jdk/javax/swing/JPopupMenu/bug4188832.java new file mode 100644 index 00000000000..9c958ebc1ef --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4188832.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @summary Test that medium weight submenus are not hidden by a heavyweight canvas. + * @bug 4188832 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4188832 + */ + +import java.awt.Color; +import java.awt.Panel; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; + +public class bug4188832 { + + static final String INSTRUCTIONS = """ + Select the File menu, then select the "Save As..." submenu. + If you can see the submenu items displayed, press PASS, else press FAIL + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4188832::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + // for Medium Weight menus + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + JFrame frame = new JFrame("bug4188832"); + + // Create the menus + JMenuBar menuBar = new JMenuBar(); + JMenu fileMenu = new JMenu("File"); + menuBar.add(fileMenu); + fileMenu.add(new JMenuItem("New")); + fileMenu.add(new JMenuItem("Open")); + fileMenu.add(new JMenuItem("Save")); + JMenu sm = new JMenu("Save As..."); + // these guys don't show up + sm.add(new JMenuItem("This")); + sm.add(new JMenuItem("That")); + fileMenu.add(sm); + fileMenu.add(new JMenuItem("Exit")); + frame.setJMenuBar(menuBar); + + Panel field = new Panel(); // a heavyweight container + field.setBackground(Color.blue); + frame.add(field); + frame.setSize(400, 400); + return frame; + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4212464.java b/test/jdk/javax/swing/JPopupMenu/bug4212464.java new file mode 100644 index 00000000000..c1c434f6b16 --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4212464.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4212464 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Verify popup menu borders are drawn correctly when switching L&Fs + * @run main/manual bug4212464 + */ + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JApplet; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class bug4212464 extends JFrame implements ActionListener { + + static String strMotif = "Motif"; + static String motifClassName = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + + static String strMetal = "Metal"; + static String metalClassName = "javax.swing.plaf.metal.MetalLookAndFeel"; + + static bug4212464 frame; + static JPopupMenu popup; + + static final String INSTRUCTIONS = """ + This test is to see whether popup menu borders behave properly when switching + back and forth between Motif and Metal L&F. The initial L&F is Metal. + + Pressing the mouse button on the label in the center of the test window brings + up a popup menu. + + In order to test, use the labeled buttons to switch the look and feel. + Clicking a button will cause the menu to be hidden. This is OK. Just click the label again. + Switch back and forth and verify that the popup menu border changes consistently + and there is a title for the menu when using Motif L&F (Metal won't have a title). + + Make sure you switch back and forth several times. + If the change is consistent, press PASS otherwise press FAIL. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(bug4212464::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + try { + UIManager.setLookAndFeel(metalClassName); // initialize to Metal. + } catch (Exception e) { + throw new RuntimeException(e); + } + frame = new bug4212464("bug4212464"); + popup = new JPopupMenu("Test"); + popup.add("Item 1"); + popup.add("Item 2"); + popup.add("Item 3"); + popup.add("Item 4"); + + JPanel p = new JPanel(); + p.setLayout(new FlowLayout()); + JButton motif = (JButton)p.add(new JButton(strMotif)); + JButton metal = (JButton)p.add(new JButton(strMetal)); + motif.setActionCommand(motifClassName); + metal.setActionCommand(metalClassName); + motif.addActionListener(frame); + metal.addActionListener(frame); + frame.add(BorderLayout.NORTH, p); + + JLabel l = new JLabel("Click any mouse button on this big label"); + l.setFont(new Font(Font.DIALOG, Font.PLAIN, 20)); + l.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + }); + frame.add(BorderLayout.CENTER, l); + frame.setSize(500, 400); + return frame; + } + + public bug4212464(String title) { + super(title); + } + + public void actionPerformed(ActionEvent e) { + String str = e.getActionCommand(); + if (str.equals(metalClassName) || str.equals(motifClassName)) { + changeLNF(str); + } else { + System.out.println("ActionEvent: " + str); + } + } + + public void changeLNF(String str) { + System.out.println("Changing LNF to " + str); + try { + UIManager.setLookAndFeel(str); + SwingUtilities.updateComponentTreeUI(frame); + SwingUtilities.updateComponentTreeUI(popup); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/bug4234793.java b/test/jdk/javax/swing/JPopupMenu/bug4234793.java new file mode 100644 index 00000000000..9ad91e5165f --- /dev/null +++ b/test/jdk/javax/swing/JPopupMenu/bug4234793.java @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4234793 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary PopupMenuListener popupMenuCanceled is never called + * @run main/manual bug4234793 + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.KeyStroke; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/** + * For all 3 components (JPopupMenu, JComboBox, JPopup) when the popup is visible, + * the popupMenuCanceled should be invoked in these two circumstances: + * + * 1. The ESCAPE key is pressed while the popup is open. + * + * 2. The mouse is clicked on another component. + * + */ + +public class bug4234793 extends JFrame implements PopupMenuListener { + + static final String INSTRUCTIONS = """ + The test window will contain several kinds of menus. + + * A menu bar with two menus labeled "1 - First Menu" and "2 - Second Menu" + * A drop down combo box - ie a button which pops up a menu when clicked + * Clicking any where on the background of the window will display a popup menu + + That is 4 menus in total. + + For each case, verify that the menu can be cancelled (hidden) in two ways + 1) Click to display the menu, then to hide it, press the ESCAPE key. + 2) Click to display the menu, then to hide it, LEFT click on the window background. + Note : the popup menu must be displayed using RIGHT click, the others use LEFT click. + + Notice each time you perform a hide/cancel action an appropriate message should + appear in the log area + If this is true for all 8 combinations of menus + hide actions the test PASSES + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(bug4234793::createUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static String[] numData = { + "One", "Two", "Three", "Four", "Five", "Six", "Seven" + }; + + private static String[] dayData = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + + private static char[] mnDayData = { + 'M', 'T', 'W', 'R', 'F', 'S', 'U' + }; + + bug4234793(String title) { + super(title); + } + + static volatile JPopupMenu popupMenu; + static volatile bug4234793 frame; + + static JFrame createUI() { + frame = new bug4234793("bug4234793"); + frame.setJMenuBar(createMenuBar()); + JPanel panel = createContentPane(); + frame.add(panel); + + // CTRL-down will show the popup. + panel.getInputMap().put(KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); + panel.getActionMap().put("OPEN_POPUP", new PopupHandler()); + panel.addMouseListener(new PopupListener(popupMenu)); + panel.setPreferredSize(new Dimension(400, 300)); + frame.setSize(400, 300); + return frame; + } + + static class PopupListener extends MouseAdapter { + private JPopupMenu popup; + + public PopupListener(JPopupMenu popup) { + this.popup = popup; + } + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseClicked(MouseEvent ex) { + } + + private void maybeShowPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(e.getComponent(), e.getX(), e.getY()); + } + } + } + + static class PopupHandler extends AbstractAction { + public void actionPerformed(ActionEvent e) { + if (!popupMenu.isVisible()) + popupMenu.show((Component)e.getSource(), 40, 40); + } + } + + static JPanel createContentPane() { + popupMenu = new JPopupMenu(); + JMenuItem item; + for (int i = 0; i < dayData.length; i++) { + item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i])); + } + popupMenu.addPopupMenuListener(frame); + + JComboBox combo = new JComboBox(numData); + combo.addPopupMenuListener(frame); + JPanel comboPanel = new JPanel(); + comboPanel.add(combo); + + JPanel panel = new JPanel(new BorderLayout()); + + panel.add(new JLabel("Right click on the panel to show the PopupMenu"), BorderLayout.NORTH); + panel.add(comboPanel, BorderLayout.CENTER); + + return panel; + } + + static JMenuBar createMenuBar() { + JMenuBar menubar = new JMenuBar(); + JMenuItem menuitem; + + JMenu menu = new JMenu("1 - First Menu"); + menu.setMnemonic('1'); + menu.getPopupMenu().addPopupMenuListener(frame); + + menubar.add(menu); + for (int i = 0; i < 10; i ++) { + menuitem = new JMenuItem("1 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + // second menu + menu = new JMenu("2 - Second Menu"); + menu.getPopupMenu().addPopupMenuListener(frame); + menu.setMnemonic('2'); + + menubar.add(menu); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("2 JMenuItem" + i); + menuitem.setMnemonic('0' + i); + menu.add(menuitem); + } + + JMenu submenu = new JMenu("Sub Menu"); + submenu.setMnemonic('S'); + submenu.getPopupMenu().addPopupMenuListener(frame); + for (int i = 0; i < 5; i++) { + menuitem = new JMenuItem("S JMenuItem" + i); + menuitem.setMnemonic('0' + i); + submenu.add(menuitem); + } + menu.add(new JSeparator()); + menu.add(submenu); + + return menubar; + } + + // PopupMenuListener methods. + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupmenu visible: " + source.getClass().getName()); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("popupMenuWillBecomeInvisible: " + source.getClass().getName()); + } + + public void popupMenuCanceled(PopupMenuEvent e) { + Object source = e.getSource(); + PassFailJFrame.log("POPUPMENU CANCELED: " + source.getClass().getName()); + } +}