From d6fea79c1adcec5b2f3b6b9a508e878915effc78 Mon Sep 17 00:00:00 2001 From: Rajeev Chamyal Date: Thu, 26 May 2016 16:02:19 +0530 Subject: [PATCH] 8147521: [macosx] Internal API Usage: setPopupType used to force creation of heavyweight popup Reviewed-by: alexsch, serb, prr --- .../classes/javax/swing/PopupFactory.java | 38 +++- .../JPopupMenu/8147521/PopupMenuTest.java | 175 ++++++++++++++++++ 2 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/swing/JPopupMenu/8147521/PopupMenuTest.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java b/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java index 3a5f91afe0e..e3d80064b86 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/PopupFactory.java @@ -175,12 +175,43 @@ public class PopupFactory { * @return Popup containing Contents */ public Popup getPopup(Component owner, Component contents, - int x, int y) throws IllegalArgumentException { + int x, int y) throws IllegalArgumentException { + return getPopup(owner, contents, x, y, false); + } + + /** + * Creates a {@code Popup} for the Component {@code owner} + * containing the Component {@code contents}. + * The window containing the component {@code owner} + * will be used as the parent window. A null {@code owner} implies there + * is no valid parent. {@code x} and {@code y} specify the preferred + * initial location to place the {@code Popup} at. Based on screen size, + * or other parameters, the {@code Popup} may not display at {@code x} and + * {@code y}. {@code isHeavyWeightPopup} specifies if the {@code Popup} + * will be heavyweight. Passing {@code true} will force the {@code Popup} + * type to be heavyweight, otherwise {@code Popup} type will be selected by + * {@code Popup} factory. Lightweight {@code Popup} windows are more + * efficient than heavyweight (native peer) windows, but lightweight + * and heavyweight components do not mix well in a GUI. + * This method is intended to be used only by PopupFactory sub-classes. + * @param owner Component mouse coordinates are relative to, may be null + * @param contents Contents of the Popup + * @param x Initial x screen coordinate + * @param y Initial y screen coordinate + * @param isHeavyWeightPopup true if Popup should be heavy weight, + * otherwise popup type will be selected by popup factory. + * @throws IllegalArgumentException if contents is null + * @return Popup containing Contents + */ + protected Popup getPopup(Component owner, Component contents, int x, int y, + boolean isHeavyWeightPopup) throws IllegalArgumentException { if (contents == null) { throw new IllegalArgumentException( - "Popup.getPopup must be passed non-null contents"); + "Popup.getPopup must be passed non-null contents"); + } + if (isHeavyWeightPopup) { + return getPopup(owner, contents, x, y, HEAVY_WEIGHT_POPUP); } - int popupType = getPopupType(owner, contents, x, y); Popup popup = getPopup(owner, contents, x, y, popupType); @@ -987,3 +1018,4 @@ public class PopupFactory { } } } + diff --git a/jdk/test/javax/swing/JPopupMenu/8147521/PopupMenuTest.java b/jdk/test/javax/swing/JPopupMenu/8147521/PopupMenuTest.java new file mode 100644 index 00000000000..8066f961bc3 --- /dev/null +++ b/jdk/test/javax/swing/JPopupMenu/8147521/PopupMenuTest.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2016, 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 8147521 + * @summary [macosx] Internal API Usage: setPopupType used to force creation of + * heavyweight popup + * @run main PopupMenuTest + */ +import java.awt.Component; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.Popup; +import javax.swing.PopupFactory; +import javax.swing.SwingUtilities; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.basic.BasicPopupMenuUI; + +public class PopupMenuTest { + + private JPopupMenu jpopup; + private static volatile boolean isLightWeight; + private static JFrame frame; + private static Robot robot; + private static JPanel panel; + + public static void main(String s[]) throws Exception { + PopupMenuTest obj = new PopupMenuTest(); + obj.createUI(); + robot = new Robot(); + robot.waitForIdle(); + robot.delay(1000); + obj.exectuteTest(); + obj.dispose(); + if (isLightWeight) { + throw new RuntimeException("Test Failed"); + } + } + + private void createUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Popup Menu"); + jpopup = new JPopupMenu(); + jpopup.setUI(new PopMenuUIExt()); + JMenuItem item = new JMenuItem("Menu Item1"); + jpopup.add(item); + item = new JMenuItem("Menu Item2"); + jpopup.setLabel("Justification"); + jpopup.add(item); + jpopup.setLabel("Justification"); + jpopup.addPopupMenuListener(new PopupListener()); + panel = new JPanel(); + panel.addMouseListener(new MousePopupListener()); + frame.setContentPane(panel); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + } + + private void dispose() throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame.dispose(); + }); + } + + private void exectuteTest() { + Point p = frame.getLocationOnScreen(); + Rectangle rect = frame.getBounds(); + robot.mouseMove(p.x + rect.width / 2, p.y + rect.height / 2); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + robot.delay(1000); + robot.mouseMove(p.x + rect.width / 2 - 10, p.y + rect.height / 2 - 10); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.delay(1000); + } + + class MousePopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { + showPopup(e); + } + + @Override + public void mouseClicked(MouseEvent e) { + showPopup(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + showPopup(e); + } + + private void showPopup(MouseEvent e) { + jpopup.show(panel, e.getX(), e.getY()); + } + } + + class PopupListener implements PopupMenuListener { + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + Popup popup = ((PopMenuUIExt) jpopup.getUI()).getPopup(); + if (popup != null) { + isLightWeight = !popup.getClass().toString(). + contains("HeavyWeightPopup"); + } + } + + public void popupMenuCanceled(PopupMenuEvent e) { + } + } +} + +class PopMenuUIExt extends BasicPopupMenuUI { + + private Popup popup; + + @Override + public Popup getPopup(JPopupMenu popup, int x, int y) { + PopupFactory.setSharedInstance(new PopupFactory() { + + @Override + public Popup getPopup(Component owner, Component contents, + int x, int y) { + return super.getPopup(popup, popup x, y, true); + } + }); + PopupFactory factory = PopupFactory.getSharedInstance(); + popup = factory.getPopup(popup, popup, x, y); + return popup; + } + + + public Popup getPopup() { + return popup; + } +} +