7072653: JComboBox popup mispositioned if its height exceeds the screen height
Reviewed-by: alexsch, azvegint
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java Fri May 08 15:37:38 2015 +0300
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java Fri May 08 16:46:24 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -204,7 +204,8 @@
if ((p.x + comboBoxBounds.width < 0) || (p.y + comboBoxBounds.height < 0) || (p.x > scrSize.width) || (p.y > scrSize.height)) {
return null;
}
- return new Rectangle(0, 22, scrSize.width, scrSize.height - 22);
+ Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(comboBox.getGraphicsConfiguration());
+ return new Rectangle(0, insets.top, scrSize.width, scrSize.height - insets.top - insets.bottom);
}
for (final GraphicsDevice gd : gs) {
@@ -314,10 +315,17 @@
}
final Rectangle r = new Rectangle(px, py, pw, ph);
- // Check whether it goes below the bottom of the screen, if so flip it
- if (r.y + r.height < top.y + scrBounds.y + scrBounds.height) return r;
-
- return new Rectangle(px, -r.height + comboBoxInsets.top, r.width, r.height);
+ if (py + ph > scrBounds.y + scrBounds.height) {
+ if (ph <= -scrBounds.y ) {
+ // popup goes above
+ r.y = -ph ;
+ } else {
+ // a full screen height popup
+ r.y = scrBounds.y + Math.max(0, (scrBounds.height - ph) / 2 );
+ r.height = Math.min(scrBounds.height, ph);
+ }
+ }
+ return r;
}
// The one to use when itemCount <= maxRowCount. Size never adjusts for arrows
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Fri May 08 15:37:38 2015 +0300
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Fri May 08 16:46:24 2015 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -1287,11 +1287,24 @@
else {
screenBounds = new Rectangle(p, toolkit.getScreenSize());
}
-
- Rectangle rect = new Rectangle(px,py,pw,ph);
- if (py+ph > screenBounds.y+screenBounds.height
- && ph < screenBounds.height) {
- rect.y = -rect.height;
+ int borderHeight = 0;
+ Border popupBorder = getBorder();
+ if (popupBorder != null) {
+ Insets borderInsets = popupBorder.getBorderInsets(this);
+ borderHeight = borderInsets.top + borderInsets.bottom;
+ screenBounds.width -= (borderInsets.left + borderInsets.right);
+ screenBounds.height -= borderHeight;
+ }
+ Rectangle rect = new Rectangle(px, py, pw, ph);
+ if (py + ph > screenBounds.y + screenBounds.height) {
+ if (ph <= -screenBounds.y - borderHeight) {
+ // popup goes above
+ rect.y = -ph - borderHeight;
+ } else {
+ // a full screen height popup
+ rect.y = screenBounds.y + Math.max(0, (screenBounds.height - ph) / 2 );
+ rect.height = Math.min(screenBounds.height, ph);
+ }
}
return rect;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicComboPopup/7072653/bug7072653.java Fri May 08 16:46:24 2015 +0300
@@ -0,0 +1,127 @@
+/*
+ * 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 7072653
+ @summary JComboBox popup mispositioned if its height exceeds the screen height
+ @author Semyon Sadetsky
+ */
+
+
+import javax.swing.*;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+import java.awt.*;
+import java.awt.Toolkit;
+
+public class bug7072653 {
+
+ private static JComboBox combobox;
+ private static JFrame frame;
+
+ public static void main(String[] args) throws Exception {
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame = new JFrame("JComboBox Test");
+ setup(frame);
+ }
+ });
+ test();
+ }
+ finally {
+ frame.dispose();
+ }
+
+ }
+
+ static void setup(JFrame frame) {
+
+
+ frame.setUndecorated(true);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ frame.setSize(320, 200);
+
+ frame.getContentPane().setLayout(new FlowLayout());
+
+ combobox = new JComboBox(new DefaultComboBoxModel() {
+ public Object getElementAt(int index) { return "Element " + index; }
+ public int getSize() {
+ return 1000;
+ }
+ });
+
+
+ combobox.setMaximumRowCount(100);
+ frame.getContentPane().add(combobox);
+
+ frame.setVisible(true);
+
+ }
+
+ static void test() throws Exception{
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ combobox.addPopupMenuListener(new PopupMenuListener() {
+ @Override
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ }
+
+ @Override
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ int height = 0;
+ for (Window window : JFrame.getWindows()) {
+ if (Window.Type.POPUP == window.getType()) {
+ height = window.getSize().height;
+ break;
+ }
+ }
+ GraphicsConfiguration gc =
+ combobox.getGraphicsConfiguration();
+ Insets screenInsets = Toolkit.getDefaultToolkit()
+ .getScreenInsets(gc);
+
+ if (height == gc.getBounds().height - screenInsets.top -
+ screenInsets.bottom ) {
+ System.out.println("ok");
+ return;
+ }
+ throw new RuntimeException(
+ "Popup window height is wrong " + height);
+ }
+
+ @Override
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ }
+ });
+ combobox.setPopupVisible(true);
+ combobox.setPopupVisible(false);
+ }
+ });
+ }
+
+
+}