提交 ce7424b7 编写于 作者: N neugens

8071705: Java application menu misbehaves when running multiple screen stacked vertically

Summary: JMenu miscalculates the position of the Popup origin when on multiple monitors stacked vertically
Reviewed-by: alexsch
上级 cbdf3e5e
......@@ -475,7 +475,8 @@ public class JMenu extends JMenuItem implements Accessible,MenuElement
}
// Then the y:
y = s.height + yOffset; // Prefer dropping down
if (position.y + y + pmSize.height >= screenBounds.height &&
if (position.y + y + pmSize.height >= screenBounds.height
+ screenBounds.y &&
// popup doesn't fit - place it wherever there's more room
screenBounds.height - s.height < 2*(position.y
- screenBounds.y)) {
......
/*
* Copyright (c) 2015, 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 8071705
* @summary Java application menu misbehaves when running multiple screen stacked vertically
* @build bug8071705
* @run main/othervm bug8071705
*/
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.util.concurrent.CountDownLatch;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class bug8071705 {
public static void main(String[] args) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final boolean [] result = new boolean[1];
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = createGUI();
GraphicsDevice[] devices = checkScreens();
// check if we have more than one and if they are stacked
// vertically
GraphicsDevice device = checkConfigs(devices);
if (device == null) {
// just pass the test
frame.dispose();
result[0] = true;
latch.countDown();
} else {
FrameListener listener =
new FrameListener(device, latch, result);
frame.addComponentListener(listener);
frame.setVisible(true);
}
}
});
latch.await();
if (result[0] == false) {
throw new RuntimeException("popup menu rendered in wrong position");
}
System.out.println("OK");
}
private static GraphicsDevice[] checkScreens() {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
return ge.getScreenDevices();
}
private static JFrame createGUI() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Some menu");
menuBar.add(menu);
for (int i = 0; i < 10; i++) {
menu.add(new JMenuItem("Some menu #" + i));
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setMinimumSize(new Dimension(200, 200));
frame.setJMenuBar(menuBar);
return frame;
}
private static GraphicsDevice checkConfigs(GraphicsDevice[] devices) {
GraphicsDevice correctDevice = null;
if (devices.length < 2) {
return correctDevice;
}
Toolkit toolkit = Toolkit.getDefaultToolkit();
Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
int halfScreen = screenBounds.height/2;
for(int i = 0; i < devices.length; i++) {
if(devices[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
GraphicsConfiguration conf =
devices[i].getDefaultConfiguration();
Rectangle bounds = conf.getBounds();
if (bounds.y >= halfScreen) {
// found
correctDevice = devices[i];
break;
}
}
}
return correctDevice;
}
private static class FrameListener extends ComponentAdapter {
private GraphicsDevice device;
private CountDownLatch latch;
private boolean [] result;
public FrameListener(GraphicsDevice device,
CountDownLatch latch,
boolean [] result)
{
this.device = device;
this.latch = latch;
this.result = result;
}
@Override
public void componentShown(ComponentEvent e) {
JFrame frame = (JFrame) e.getComponent();
runActualTest(device, latch, frame, result);
frame.setVisible(false);
frame.dispose();
latch.countDown();
}
}
private static Rectangle setLocation(JFrame frame, GraphicsDevice device) {
GraphicsConfiguration conf = device.getDefaultConfiguration();
Rectangle bounds = conf.getBounds();
// put just below half screen
int x = bounds.x + bounds.width/2;
int y = bounds.y + bounds.height/2;
frame.setLocation(x, y);
return bounds;
}
private static void runActualTest(GraphicsDevice device,
CountDownLatch latch,
JFrame frame,
boolean [] result)
{
Rectangle screenBounds = setLocation(frame, device);
JMenu menu = frame.getJMenuBar().getMenu(0);
menu.doClick();
Point location = menu.getLocationOnScreen();
JPopupMenu pm = menu.getPopupMenu();
Dimension pmSize = pm.getSize();
int yOffset = UIManager.getInt("Menu.submenuPopupOffsetY");
int height = location.y + yOffset + pmSize.height + menu.getHeight();
int available = screenBounds.y + screenBounds.height - height;
if (available > 0) {
Point origin = pm.getLocationOnScreen();
if (origin.y < location.y) {
// growing upward, wrong!
result[0] = false;
} else {
// growing downward, ok!
result[0] = true;
}
} else {
// there is no space, growing upward would be ok, so we pass
result[0] = true;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册