Path: blob/master/test/jdk/javax/swing/JMenu/8071705/bug8071705.java
41153 views
/*1* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @key headful26* @bug 807170527* @summary Java application menu misbehaves when running multiple screen stacked vertically28* @build bug807170529* @run main/othervm bug807170530*/3132import java.awt.Dimension;33import java.awt.GraphicsConfiguration;34import java.awt.GraphicsDevice;35import java.awt.GraphicsEnvironment;36import java.awt.Point;37import java.awt.Rectangle;38import java.awt.Toolkit;39import java.awt.event.ComponentAdapter;40import java.awt.event.ComponentEvent;41import java.awt.event.KeyEvent;42import java.util.concurrent.CountDownLatch;4344import javax.swing.JFrame;45import javax.swing.JMenu;46import javax.swing.JMenuBar;47import javax.swing.JMenuItem;48import javax.swing.JPopupMenu;49import javax.swing.SwingUtilities;50import javax.swing.UIManager;5152public class bug8071705 {5354public static void main(String[] args) throws Exception {5556final CountDownLatch latch = new CountDownLatch(1);57final boolean [] result = new boolean[1];5859SwingUtilities.invokeLater(new Runnable() {60@Override61public void run() {62JFrame frame = createGUI();63GraphicsDevice[] devices = checkScreens();6465// check if we have more than one and if they are stacked66// vertically67GraphicsDevice device = checkConfigs(devices);68if (device == null) {69// just pass the test70frame.dispose();71result[0] = true;72latch.countDown();73} else {74FrameListener listener =75new FrameListener(device, latch, result);76frame.addComponentListener(listener);77frame.setVisible(true);78}79}80});8182latch.await();8384if (result[0] == false) {85throw new RuntimeException("popup menu rendered in wrong position");86}8788System.out.println("OK");89}9091private static GraphicsDevice[] checkScreens() {92GraphicsEnvironment ge =93GraphicsEnvironment.getLocalGraphicsEnvironment();94return ge.getScreenDevices();95}9697private static JFrame createGUI() {98JMenuBar menuBar = new JMenuBar();99JMenu menu = new JMenu("Some menu");100menuBar.add(menu);101102for (int i = 0; i < 10; i++) {103menu.add(new JMenuItem("Some menu #" + i));104}105106JFrame frame = new JFrame();107frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);108frame.setMinimumSize(new Dimension(200, 200));109frame.setJMenuBar(menuBar);110return frame;111}112113private static GraphicsDevice checkConfigs(GraphicsDevice[] devices) {114115GraphicsDevice correctDevice = null;116if (devices.length < 2) {117return correctDevice;118}119120Toolkit toolkit = Toolkit.getDefaultToolkit();121Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());122int halfScreen = screenBounds.height/2;123124for(int i = 0; i < devices.length; i++) {125if(devices[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {126GraphicsConfiguration conf =127devices[i].getDefaultConfiguration();128Rectangle bounds = conf.getBounds();129if (bounds.y >= halfScreen) {130// found131correctDevice = devices[i];132break;133}134}135}136return correctDevice;137}138139private static class FrameListener extends ComponentAdapter {140141private GraphicsDevice device;142private CountDownLatch latch;143private boolean [] result;144public FrameListener(GraphicsDevice device,145CountDownLatch latch,146boolean [] result)147{148this.device = device;149this.latch = latch;150this.result = result;151}152153@Override154public void componentShown(ComponentEvent e) {155JFrame frame = (JFrame) e.getComponent();156157runActualTest(device, latch, frame, result);158159frame.setVisible(false);160frame.dispose();161latch.countDown();162}163}164165private static Rectangle setLocation(JFrame frame, GraphicsDevice device) {166GraphicsConfiguration conf = device.getDefaultConfiguration();167Rectangle bounds = conf.getBounds();168169// put just below half screen170int x = bounds.x + bounds.width/2;171int y = bounds.y + bounds.height/2;172frame.setLocation(x, y);173174return bounds;175}176177private static void runActualTest(GraphicsDevice device,178CountDownLatch latch,179JFrame frame,180boolean [] result)181{182Rectangle screenBounds = setLocation(frame, device);183JMenu menu = frame.getJMenuBar().getMenu(0);184menu.doClick();185186Point location = menu.getLocationOnScreen();187JPopupMenu pm = menu.getPopupMenu();188Dimension pmSize = pm.getSize();189190int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");191int height = location.y + yOffset + pmSize.height + menu.getHeight();192int available = screenBounds.y + screenBounds.height - height;193if (available > 0) {194Point origin = pm.getLocationOnScreen();195if (origin.y < location.y) {196// growing upward, wrong!197result[0] = false;198} else {199// growing downward, ok!200result[0] = true;201}202} else {203// there is no space, growing upward would be ok, so we pass204result[0] = true;205}206}207}208209210