8136998: JComboBox prevents wheel mouse scrolling of JScrollPane
Reviewed-by: serb, alexp
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Wed May 18 11:33:04 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Wed May 18 15:51:19 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -150,8 +150,6 @@
*/
protected KeyListener popupKeyListener;
- private MouseWheelListener mouseWheelListener;
-
// This is used for knowing when to cache the minimum preferred size.
// If the data in the list changes, the cached value get marked for recalc.
// Added to the current JComboBox model
@@ -415,10 +413,6 @@
comboBox.getModel().addListDataListener( listDataListener );
}
}
-
- if ((mouseWheelListener = createMouseWheelListener()) != null) {
- comboBox.addMouseWheelListener(mouseWheelListener);
- }
}
/**
@@ -465,9 +459,6 @@
comboBox.getModel().removeListDataListener( listDataListener );
}
}
- if (mouseWheelListener != null) {
- comboBox.removeMouseWheelListener(mouseWheelListener);
- }
}
/**
@@ -581,10 +572,6 @@
return handler;
}
- private MouseWheelListener createMouseWheelListener() {
- return getHandler();
- }
-
//
// end UI Initialization
//======================
@@ -1737,8 +1724,7 @@
//
private class Handler implements ActionListener, FocusListener,
KeyListener, LayoutManager,
- ListDataListener, PropertyChangeListener,
- MouseWheelListener {
+ ListDataListener, PropertyChangeListener {
//
// PropertyChangeListener
//
@@ -2026,10 +2012,6 @@
}
}
}
-
- public void mouseWheelMoved(MouseWheelEvent e) {
- e.consume();
- }
}
class DefaultKeySelectionManager implements JComboBox.KeySelectionManager, UIResource {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Wed May 18 11:33:04 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Wed May 18 15:51:19 2016 +0300
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -379,17 +379,26 @@
// PopupMenuListeners.
protected void firePopupMenuWillBecomeVisible() {
+ if (scrollerMouseWheelListener != null) {
+ comboBox.addMouseWheelListener(scrollerMouseWheelListener);
+ }
super.firePopupMenuWillBecomeVisible();
// comboBox.firePopupMenuWillBecomeVisible() is called from BasicComboPopup.show() method
// to let the user change the popup menu from the PopupMenuListener.popupMenuWillBecomeVisible()
}
protected void firePopupMenuWillBecomeInvisible() {
+ if (scrollerMouseWheelListener != null) {
+ comboBox.removeMouseWheelListener(scrollerMouseWheelListener);
+ }
super.firePopupMenuWillBecomeInvisible();
comboBox.firePopupMenuWillBecomeInvisible();
}
protected void firePopupMenuCanceled() {
+ if (scrollerMouseWheelListener != null) {
+ comboBox.removeMouseWheelListener(scrollerMouseWheelListener);
+ }
super.firePopupMenuCanceled();
comboBox.firePopupMenuCanceled();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComboBox/8136998/bug8136998.java Wed May 18 15:51:19 2016 +0300
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.awt.AWTException;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UIManager.LookAndFeelInfo;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.WindowConstants;
+
+/* @test
+ * @bug 8136998
+ * @summary Checks that JComboBox does not prevent mouse-wheel scrolling JScrollPane.
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main bug8136998
+ * @author Alexey Ivanov
+ */
+public class bug8136998 {
+
+ private static final String[] ITEMS = new String[] {
+ "A", "B", "C", "D", "E", "F"
+ };
+
+ private final Robot robot;
+
+ private JFrame frame;
+ private JComboBox comboBox;
+ private JScrollPane scrollPane;
+
+ public static void main(String[] args) throws Exception {
+ iterateLookAndFeels(new bug8136998());
+ }
+
+ protected static void iterateLookAndFeels(final bug8136998 test) throws Exception {
+ LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels();
+ for (LookAndFeelInfo info : lafInfo) {
+ try {
+ UIManager.setLookAndFeel(info.getClassName());
+ System.out.println("Look and Feel: " + info.getClassName());
+ test.runTest();
+ } catch (UnsupportedLookAndFeelException e) {
+ System.out.println("Skipping unsupported LaF: " + info);
+ }
+ }
+ }
+
+ public bug8136998() throws AWTException {
+ robot = new Robot();
+ robot.setAutoDelay(200);
+ }
+
+ private void setupUI() {
+ frame = new JFrame();
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ comboBox = new JComboBox<>(ITEMS);
+
+ JPanel scrollable = new JPanel();
+ scrollable.setLayout(new BoxLayout(scrollable, BoxLayout.Y_AXIS));
+
+ scrollable.add(Box.createVerticalStrut(200));
+ scrollable.add(comboBox);
+ scrollable.add(Box.createVerticalStrut(200));
+
+ scrollPane = new JScrollPane(scrollable);
+
+ frame.add(scrollPane);
+
+ frame.setSize(100, 200);
+ frame.setVisible(true);
+ }
+
+ public void runTest() throws Exception {
+ try {
+ SwingUtilities.invokeAndWait(this::setupUI);
+
+ robot.waitForIdle();
+
+ SwingUtilities.invokeAndWait(() ->
+ scrollPane.getViewport().scrollRectToVisible(comboBox.getBounds())
+ );
+ robot.waitForIdle();
+
+ // Move mouse pointer to the center of the combo box
+ Point p = comboBox.getLocationOnScreen();
+ Dimension d = comboBox.getSize();
+ robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
+
+ // The currently visible rectangle in scrollPane
+ Rectangle viewRect0 = Util.invokeOnEDT(scrollPane.getViewport()::getViewRect);
+
+ // Scroll the scrollPane with mouse wheel
+ robot.mouseWheel(1);
+ robot.waitForIdle();
+
+ // The updated rectangle
+ Rectangle viewRect1 = Util.invokeOnEDT(scrollPane.getViewport()::getViewRect);
+
+ if (viewRect0.y == viewRect1.y) {
+ throw new RuntimeException("Mouse wheel should have scrolled the JScrollPane");
+ }
+ } finally {
+ if (frame != null) {
+ frame.dispose();
+ }
+ }
+
+ System.out.println("Test passed");
+ }
+}