1/* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @key headful 27 * @bug 7072653 8144161 8176448 28 * @summary JComboBox popup mispositioned if its height exceeds the screen height 29 * @run main bug7072653 30 */ 31 32import java.awt.FlowLayout; 33import java.awt.GraphicsConfiguration; 34import java.awt.GraphicsDevice; 35import java.awt.GraphicsEnvironment; 36import java.awt.Insets; 37import java.awt.Rectangle; 38import java.awt.Robot; 39import java.awt.Toolkit; 40import java.awt.Window; 41 42import javax.swing.DefaultComboBoxModel; 43import javax.swing.JComboBox; 44import javax.swing.JFrame; 45import javax.swing.SwingUtilities; 46import javax.swing.UIManager; 47import javax.swing.UnsupportedLookAndFeelException; 48import javax.swing.event.PopupMenuEvent; 49import javax.swing.event.PopupMenuListener; 50 51public class bug7072653 { 52 53 private static JComboBox combobox; 54 private static JFrame frame; 55 private static Robot robot; 56 57 public static void main(String[] args) throws Exception { 58 robot = new Robot(); 59 GraphicsEnvironment ge = 60 GraphicsEnvironment.getLocalGraphicsEnvironment(); 61 UIManager.LookAndFeelInfo[] lookAndFeelArray = 62 UIManager.getInstalledLookAndFeels(); 63 for (GraphicsDevice sd : ge.getScreenDevices()) { 64 for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { 65 executeCase(lookAndFeelItem.getClassName(), sd); 66 robot.waitForIdle(); 67 } 68 } 69 } 70 71 private static void executeCase(String lookAndFeelString, GraphicsDevice sd) 72 throws Exception { 73 if (tryLookAndFeel(lookAndFeelString)) { 74 SwingUtilities.invokeAndWait(() -> { 75 try { 76 setup(lookAndFeelString, sd); 77 test(); 78 } catch (Exception ex) { 79 throw new RuntimeException(ex); 80 } finally { 81 frame.dispose(); 82 } 83 }); 84 } 85 } 86 87 private static void setup(String lookAndFeelString, GraphicsDevice sd) 88 throws Exception { 89 GraphicsConfiguration gc = sd.getDefaultConfiguration(); 90 Rectangle gcBounds = gc.getBounds(); 91 frame = new JFrame("JComboBox Test " + lookAndFeelString, gc); 92 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 93 frame.setSize(400, 200); 94 frame.getContentPane().setLayout(new FlowLayout()); 95 frame.setLocation( 96 gcBounds.x + gcBounds.width / 2 - frame.getWidth() / 2, 97 gcBounds.y + gcBounds.height / 2 - frame.getHeight() / 2); 98 99 combobox = new JComboBox(new DefaultComboBoxModel() { 100 @Override 101 public Object getElementAt(int index) { 102 return "Element " + index; 103 } 104 105 @Override 106 public int getSize() { 107 return 100; 108 } 109 }); 110 111 combobox.setMaximumRowCount(100); 112 combobox.putClientProperty("JComboBox.isPopDown", true); 113 frame.getContentPane().add(combobox); 114 frame.setVisible(true); 115 combobox.addPopupMenuListener(new PopupMenuListener() { 116 @Override 117 public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 118 } 119 120 @Override 121 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 122 int height = 0; 123 for (Window window : JFrame.getWindows()) { 124 if (Window.Type.POPUP == window.getType()) { 125 if (window.getOwner().isVisible()) { 126 height = window.getSize().height; 127 break; 128 } 129 } 130 } 131 GraphicsConfiguration gc = combobox.getGraphicsConfiguration(); 132 Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); 133 int gcHeight = gc.getBounds().height; 134 gcHeight = gcHeight - insets.top - insets.bottom; 135 if (height == gcHeight) { 136 return; 137 } 138 139 String exception = "Popup window height " 140 + "For LookAndFeel" + lookAndFeelString + " is wrong" 141 + "\nShould be " + gcHeight + ", Actually " + height; 142 throw new RuntimeException(exception); 143 } 144 145 @Override 146 public void popupMenuCanceled(PopupMenuEvent e) { 147 } 148 149 }); 150 151 } 152 153 private static void test() throws Exception { 154 combobox.setPopupVisible(true); 155 combobox.setPopupVisible(false); 156 } 157 158 private static boolean tryLookAndFeel(String lookAndFeelString) 159 throws Exception { 160 try { 161 UIManager.setLookAndFeel( 162 lookAndFeelString); 163 164 } catch (UnsupportedLookAndFeelException 165 | ClassNotFoundException 166 | InstantiationException 167 | IllegalAccessException e) { 168 return false; 169 } 170 return true; 171 } 172} 173