1 /* 2 * Copyright (c) 2013, 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 import java.awt.*; 25 import java.awt.event.*; 26 import javax.swing.*; 27 import javax.swing.event.*; 28 29 /** 30 * @test @bug 4245587 4474813 4425878 4767478 8015599 31 * @author Mark Davidson 32 * @summary Tests the location of the heavy weight popup portion of JComboBox, 33 * JMenu and JPopupMenu. 34 * @library ../regtesthelpers 35 * @build Util 36 * @run main TaskbarPositionTest 37 */ 38 public class TaskbarPositionTest extends JFrame implements ActionListener { 39 40 private boolean done; 41 private Throwable error; 42 private static TaskbarPositionTest test; 43 private static JPopupMenu popupMenu; 44 private static JPanel panel; 45 private static JComboBox<String> combo1; 46 private static JComboBox<String> combo2; 47 private static JMenuBar menubar; 48 private static JMenu menu1; 49 private static JMenu menu2; 50 private static Rectangle fullScreenBounds; 51 // The usable desktop space: screen size - screen insets. 52 private static Rectangle screenBounds; 53 private static String[] numData = { 54 "One", "Two", "Three", "Four", "Five", "Six", "Seven" 55 }; 56 private static String[] dayData = { 57 "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" 58 }; 59 private static char[] mnDayData = { 60 'M', 'T', 'W', 'R', 'F', 'S', 'U' 61 }; 62 63 public TaskbarPositionTest() { 64 super("Use CTRL-down to show a JPopupMenu"); 65 setContentPane(panel = createContentPane()); 66 setJMenuBar(createMenuBar("1 - First Menu", true)); 67 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 68 69 // CTRL-down will show the popup. 70 panel.getInputMap().put(KeyStroke.getKeyStroke( 71 KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); 72 panel.getActionMap().put("OPEN_POPUP", new PopupHandler()); 73 74 pack(); 75 76 Toolkit toolkit = Toolkit.getDefaultToolkit(); 77 fullScreenBounds = new Rectangle(new Point(), toolkit.getScreenSize()); 78 screenBounds = new Rectangle(new Point(), toolkit.getScreenSize()); 79 80 // Place the frame near the bottom. This is a pretty wild guess. 81 this.setLocation(0, (int) screenBounds.getHeight() - 2 * this.getHeight()); 82 83 // Reduce the screen bounds by the insets. 84 GraphicsConfiguration gc = this.getGraphicsConfiguration(); 85 if (gc != null) { 86 Insets screenInsets = toolkit.getScreenInsets(gc); 87 screenBounds = gc.getBounds(); 88 screenBounds.width -= (screenInsets.left + screenInsets.right); 89 screenBounds.height -= (screenInsets.top + screenInsets.bottom); 90 screenBounds.x += screenInsets.left; 91 screenBounds.y += screenInsets.top; 92 } 93 94 setVisible(true); 95 } 96 97 public static class ComboPopupCheckListener implements PopupMenuListener { 98 99 public void popupMenuCanceled(PopupMenuEvent ev) { 100 } 101 102 public void popupMenuWillBecomeVisible(PopupMenuEvent ev) { 103 } 104 105 public void popupMenuWillBecomeInvisible(PopupMenuEvent ev) { 106 Point cpos = combo1.getLocation(); 107 SwingUtilities.convertPointToScreen(cpos, panel); 108 109 JPopupMenu pm = (JPopupMenu) combo1.getUI().getAccessibleChild(combo1, 0); 110 111 if (pm != null) { 112 Point p = pm.getLocation(); 113 SwingUtilities.convertPointToScreen(p, pm); 114 if (p.y < cpos.y) { 115 throw new RuntimeException("ComboBox popup is wrongly aligned"); 116 } // check that popup was opened down 117 } 118 } 119 } 120 121 private class PopupHandler extends AbstractAction { 122 123 public void actionPerformed(ActionEvent e) { 124 if (!popupMenu.isVisible()) { 125 popupMenu.show((Component) e.getSource(), 40, 40); 126 } 127 isPopupOnScreen(popupMenu, fullScreenBounds); 128 } 129 } 130 131 class PopupListener extends MouseAdapter { 132 133 private JPopupMenu popup; 134 135 public PopupListener(JPopupMenu popup) { 136 this.popup = popup; 137 } 138 139 public void mousePressed(MouseEvent e) { 140 maybeShowPopup(e); 141 } 142 143 public void mouseReleased(MouseEvent e) { 144 maybeShowPopup(e); 145 } 146 147 private void maybeShowPopup(MouseEvent e) { 148 if (e.isPopupTrigger()) { 149 popup.show(e.getComponent(), e.getX(), e.getY()); 150 isPopupOnScreen(popup, fullScreenBounds); 151 } 152 } 153 } 154 155 /** 156 * Tests if the popup is on the screen. 157 */ 158 public static void isPopupOnScreen(JPopupMenu popup, Rectangle checkBounds) { 159 Dimension dim = popup.getSize(); 160 Point pt = new Point(); 161 SwingUtilities.convertPointToScreen(pt, popup); 162 Rectangle bounds = new Rectangle(pt, dim); 163 164 if (!SwingUtilities.isRectangleContainingRectangle(checkBounds, bounds)) { 165 throw new RuntimeException("We do not match! " + checkBounds + " / " + bounds); 166 } 167 168 } 169 170 private JPanel createContentPane() { 171 JPanel panel = new JPanel(); 172 173 combo1 = new JComboBox<>(numData); 174 panel.add(combo1); 175 combo2 = new JComboBox<>(dayData); 176 combo2.setEditable(true); 177 panel.add(combo2); 178 panel.setSize(300, 200); 179 180 popupMenu = new JPopupMenu(); 181 JMenuItem item; 182 for (int i = 0; i < dayData.length; i++) { 183 item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i])); 184 item.addActionListener(this); 185 } 186 panel.addMouseListener(new PopupListener(popupMenu)); 187 188 JTextField field = new JTextField("CTRL+down for Popup"); 189 // CTRL-down will show the popup. 190 field.getInputMap().put(KeyStroke.getKeyStroke( 191 KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); 192 field.getActionMap().put("OPEN_POPUP", new PopupHandler()); 193 194 panel.add(field); 195 196 return panel; 197 } 198 199 /** 200 * @param str name of Menu 201 * @param bFlag set mnemonics on menu items 202 */ 203 private JMenuBar createMenuBar(String str, boolean bFlag) { 204 menubar = new JMenuBar(); 205 206 menu1 = new JMenu(str); 207 menu1.setMnemonic(str.charAt(0)); 208 menu1.addActionListener(this); 209 210 menubar.add(menu1); 211 for (int i = 0; i < 8; i++) { 212 JMenuItem menuitem = new JMenuItem("1 JMenuItem" + i); 213 menuitem.addActionListener(this); 214 if (bFlag) { 215 menuitem.setMnemonic('0' + i); 216 } 217 menu1.add(menuitem); 218 } 219 220 // second menu 221 menu2 = new JMenu("2 - Second Menu"); 222 menu2.addActionListener(this); 223 menu2.setMnemonic('2'); 224 225 menubar.add(menu2); 226 for (int i = 0; i < 5; i++) { 227 JMenuItem menuitem = new JMenuItem("2 JMenuItem" + i); 228 menuitem.addActionListener(this); 229 230 if (bFlag) { 231 menuitem.setMnemonic('0' + i); 232 } 233 menu2.add(menuitem); 234 } 235 JMenu submenu = new JMenu("Sub Menu"); 236 submenu.setMnemonic('S'); 237 submenu.addActionListener(this); 238 for (int i = 0; i < 5; i++) { 239 JMenuItem menuitem = new JMenuItem("S JMenuItem" + i); 240 menuitem.addActionListener(this); 241 if (bFlag) { 242 menuitem.setMnemonic('0' + i); 243 } 244 submenu.add(menuitem); 245 } 246 menu2.add(new JSeparator()); 247 menu2.add(submenu); 248 249 return menubar; 250 } 251 252 public void actionPerformed(ActionEvent evt) { 253 Object obj = evt.getSource(); 254 if (obj instanceof JMenuItem) { 255 // put the focus on the noneditable combo. 256 combo1.requestFocus(); 257 } 258 } 259 260 public static void main(String[] args) throws Throwable { 261 262 sun.awt.SunToolkit toolkit = (sun.awt.SunToolkit) Toolkit.getDefaultToolkit(); 263 264 SwingUtilities.invokeAndWait(new Runnable() { 265 public void run() { 266 test = new TaskbarPositionTest(); 267 } 268 }); 269 270 // Use Robot to automate the test 271 Robot robot; 272 robot = new Robot(); 273 robot.setAutoDelay(125); 274 275 // 1 - menu 276 Util.hitMnemonics(robot, KeyEvent.VK_1); 277 278 toolkit.realSync(); 279 isPopupOnScreen(menu1.getPopupMenu(), screenBounds); 280 281 // 2 menu with sub menu 282 robot.keyPress(KeyEvent.VK_RIGHT); 283 robot.keyRelease(KeyEvent.VK_RIGHT); 284 Util.hitMnemonics(robot, KeyEvent.VK_S); 285 286 toolkit.realSync(); 287 isPopupOnScreen(menu2.getPopupMenu(), screenBounds); 288 289 robot.keyPress(KeyEvent.VK_ENTER); 290 robot.keyRelease(KeyEvent.VK_ENTER); 291 292 // Focus should go to non editable combo box 293 toolkit.realSync(); 294 Thread.sleep(500); 295 296 robot.keyPress(KeyEvent.VK_DOWN); 297 298 // How do we check combo boxes? 299 300 // Editable combo box 301 robot.keyPress(KeyEvent.VK_TAB); 302 robot.keyRelease(KeyEvent.VK_TAB); 303 robot.keyPress(KeyEvent.VK_DOWN); 304 robot.keyRelease(KeyEvent.VK_DOWN); 305 306 // combo1.getUI(); 307 308 // Popup from Text field 309 robot.keyPress(KeyEvent.VK_TAB); 310 robot.keyRelease(KeyEvent.VK_TAB); 311 robot.keyPress(KeyEvent.VK_CONTROL); 312 robot.keyPress(KeyEvent.VK_DOWN); 313 robot.keyRelease(KeyEvent.VK_DOWN); 314 robot.keyRelease(KeyEvent.VK_CONTROL); 315 316 // Popup from a mouse click. 317 Point pt = new Point(2, 2); 318 SwingUtilities.convertPointToScreen(pt, panel); 319 robot.mouseMove((int) pt.getX(), (int) pt.getY()); 320 robot.mousePress(InputEvent.BUTTON3_MASK); 321 robot.mouseRelease(InputEvent.BUTTON3_MASK); 322 323 toolkit.realSync(); 324 SwingUtilities.invokeAndWait(new Runnable() { 325 public void run() { 326 test.setLocation(-30, 100); 327 combo1.addPopupMenuListener(new ComboPopupCheckListener()); 328 combo1.requestFocus(); 329 } 330 }); 331 332 robot.keyPress(KeyEvent.VK_DOWN); 333 robot.keyRelease(KeyEvent.VK_DOWN); 334 robot.keyPress(KeyEvent.VK_ESCAPE); 335 robot.keyRelease(KeyEvent.VK_ESCAPE); 336 337 toolkit.realSync(); 338 Thread.sleep(500); 339 } 340 }