# HG changeset patch # User neugens # Date 1573570464 -3600 # Tue Nov 12 15:54:24 2019 +0100 # Node ID d5af26ef7b959383e4a79b0aa96f0527fc3a9f4c # Parent 571089680cb28b3c6399f3a95e6ebcb4593b792c 8231991: Mouse wheel change focus on awt/swing windows Summary: Avoid focus logic when only mouse wheel is moved up/down. Reviewed-by: serb, dmarkov diff --git openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java --- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XBaseWindow.java @@ -1004,29 +1004,37 @@ * InputEvent.BUTTON_DOWN_MASK. * One more bit is reserved for FIRST_HIGH_BIT. */ - if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) { + int theButton = xbe.get_button(); + if (theButton > SunToolkit.MAX_BUTTONS_SUPPORTED) { return; } int buttonState = 0; buttonState = xbe.get_state() & XConstants.ALL_BUTTONS_MASK; - switch (xev.get_type()) { - case XConstants.ButtonPress: - if (buttonState == 0) { - XWindowPeer parent = getToplevelXWindow(); - // See 6385277, 6981400. - if (parent != null && parent.isFocusableWindow()) { - // A click in a client area drops the actual focused window retaining. - parent.setActualFocusedWindow(null); - parent.requestWindowFocus(xbe.get_time(), true); - } - XAwtState.setAutoGrabWindow(this); + + boolean isWheel = (theButton != XConstants.MouseWheelUp || + theButton != XConstants.MouseWheelDown); + + // don't give focus if it's just the mouse wheel turning + if (!isWheel) { + switch (xev.get_type()) { + case XConstants.ButtonPress: + if (buttonState == 0) { + XWindowPeer parent = getToplevelXWindow(); + // See 6385277, 6981400. + if (parent != null && parent.isFocusableWindow()) { + // A click in a client area drops the actual focused window retaining. + parent.setActualFocusedWindow(null); + parent.requestWindowFocus(xbe.get_time(), true); + } + XAwtState.setAutoGrabWindow(this); + } + break; + case XConstants.ButtonRelease: + if (isFullRelease(buttonState, xbe.get_button())) { + XAwtState.setAutoGrabWindow(null); + } + break; } - break; - case XConstants.ButtonRelease: - if (isFullRelease(buttonState, xbe.get_button())) { - XAwtState.setAutoGrabWindow(null); - } - break; } } public void handleMotionNotify(XEvent xev) { diff --git openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XConstants.java openjdk/jdk/src/solaris/classes/sun/awt/X11/XConstants.java --- openjdk.orig/jdk/src/solaris/classes/sun/awt/X11/XConstants.java +++ openjdk/jdk/src/solaris/classes/sun/awt/X11/XConstants.java @@ -206,6 +206,11 @@ public static final int buttons [] = new int [] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; + // those should probably be wrapped in a method or such + // as it may be possible to remap them via x11 configuration files + public static final int MouseWheelUp = buttons[4]; + public static final int MouseWheelDown = buttons[5]; + /* Notify modes */ public static final int NotifyNormal = 0 ; diff --git openjdk/jdk/test/java/awt/event/MouseWheelEvent/WheelModifier/MouseWheelOnBackgroundComponent.java openjdk/jdk/test/java/awt/event/MouseWheelEvent/WheelModifier/MouseWheelOnBackgroundComponent.java new file mode 100644 --- /dev/null +++ openjdk/jdk/test/java/awt/event/MouseWheelEvent/WheelModifier/MouseWheelOnBackgroundComponent.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019, 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 + @key headful + @bug 8231991 + @summary Mouse wheel change focus on awt/swing windows + @run main MouseWheelOnBackgroundComponent +*/ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.WindowEvent; + +/** + * MouseWheelOnBackgroundComponent + * + * Tests that wheel events don't change focus on background components + */ +public class MouseWheelOnBackgroundComponent { + + private static final String FG = "Foreground"; + private static final String BG = "Background"; + + private static final String SCROLL_PANE = "scroller_"; + private static final String TEXT_PANE = "text_"; + + private static JFrame background; + private static JFrame foreground; + + private static final String LOREM_IPSUM = "Sed ut perspiciatis unde omnis iste natus " + + "error sit voluptatem accusantium doloremque laudantium, totam " + + "rem aperiam, eaque ipsa quae ab illo inventore veritatis et " + + "quasi architecto beatae vitae dicta sunt explicabo. Nemo enim " + + "ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, " + + "sed quia consequuntur magni dolores eos qui ratione voluptatem sequi " + + "nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit " + + "amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora " + + "incidunt ut labore et dolore magnam aliquam quaerat voluptatem. " + + "Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis " + + "suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis " + + "autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil " + + "molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla " + + "pariatur?"; + + private static class FocusReporter implements FocusListener { + + private JComponent pane; + + Component lastFocusedComponent; + + public FocusReporter() { + } + + @Override + public void focusGained(FocusEvent e) { + lastFocusedComponent = e.getComponent(); + } + + @Override + public void focusLost(FocusEvent e) { + lastFocusedComponent = null; + } + } + + private static FocusReporter reporter; + + public static void main(String[] args) throws Exception { + + boolean passed = false; + + SwingUtilities.invokeAndWait(() -> { + reporter = new FocusReporter(); + + foreground = createFrame(FG, 100, 0, reporter); + background = createFrame(BG, 0, 100, reporter); + + background.pack(); + background.setVisible(true); + + foreground.pack(); + foreground.setVisible(true); + }); + + SwingUtilities.invokeAndWait(() -> { + foreground.toFront(); + }); + + Robot robot = new Robot(); + robot.waitForIdle(); + + robot.mouseMove(50, 300); + robot.waitForIdle(); + + robot.mouseWheel(-100); + robot.waitForIdle(); + + String shouldBeFocusedComponentName = TEXT_PANE + FG; + Component actual = reporter.lastFocusedComponent; + if (reporter.lastFocusedComponent != null && + shouldBeFocusedComponentName.equals(actual.getName())) + { + passed = true; + } + + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + foreground.dispatchEvent(new WindowEvent(foreground, WindowEvent.WINDOW_CLOSING)); + background.dispatchEvent(new WindowEvent(background, WindowEvent.WINDOW_CLOSING)); + }); + + robot.waitForIdle(); + + if (!passed) { + throw new RuntimeException("Wrong component has focus: " + actual); + } + } + + private static JFrame createFrame(String name, int x, int y, FocusReporter reporter) { + JFrame frame = new JFrame(name); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setBounds(x, y, 600, 600); + frame.setPreferredSize(new Dimension(600, 600)); + + JTextArea text = new JTextArea(); + text.setText(LOREM_IPSUM); + for (int i = 0; i < 10; i++) { + text.append(LOREM_IPSUM); + } + + text.setLineWrap(true); + text.setName(TEXT_PANE + name); + text.addFocusListener(reporter); + + JScrollPane scroller = new JScrollPane(text); + scroller.setName(SCROLL_PANE + name); + scroller.setWheelScrollingEnabled(true); + scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + scroller.addFocusListener(reporter); + + frame.add(scroller); + + return frame; + } +}