提交 42f2bff1 编写于 作者: A azvegint

8061636: Fix for JDK-7079254 changes behavior of MouseListener, MouseMotionListener

Reviewed-by: alexsch, serb
上级 598b02e4
/* /*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1669,15 +1669,6 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -1669,15 +1669,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
/* do nothing */ /* do nothing */
} }
/*
* Delete references from LightweithDispatcher of a heavyweight parent
*/
void clearLightweightDispatcherOnRemove(Component removedComponent) {
if (parent != null) {
parent.clearLightweightDispatcherOnRemove(removedComponent);
}
}
/** /**
* @deprecated As of JDK version 1.1, * @deprecated As of JDK version 1.1,
* replaced by <code>setVisible(boolean)</code>. * replaced by <code>setVisible(boolean)</code>.
...@@ -6180,7 +6171,7 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -6180,7 +6171,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
/** /**
* Indicates whether a class or its superclasses override coalesceEvents. * Indicates whether a class or its superclasses override coalesceEvents.
* Must be called with lock on coalesceMap and privileged. * Must be called with lock on coalesceMap and privileged.
* @see checkCoalsecing * @see checkCoalescing
*/ */
private static boolean isCoalesceEventsOverriden(Class<?> clazz) { private static boolean isCoalesceEventsOverriden(Class<?> clazz) {
assert Thread.holdsLock(coalesceMap); assert Thread.holdsLock(coalesceMap);
...@@ -6986,8 +6977,6 @@ public abstract class Component implements ImageObserver, MenuContainer, ...@@ -6986,8 +6977,6 @@ public abstract class Component implements ImageObserver, MenuContainer,
} }
synchronized (getTreeLock()) { synchronized (getTreeLock()) {
clearLightweightDispatcherOnRemove(this);
if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) {
transferFocus(true); transferFocus(true);
} }
......
/* /*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -41,6 +41,7 @@ import java.io.ObjectStreamField; ...@@ -41,6 +41,7 @@ import java.io.ObjectStreamField;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.security.AccessController; import java.security.AccessController;
import java.util.EventListener; import java.util.EventListener;
...@@ -3310,16 +3311,6 @@ public class Container extends Component { ...@@ -3310,16 +3311,6 @@ public class Container extends Component {
} }
} }
@Override
void clearLightweightDispatcherOnRemove(Component removedComponent) {
if (dispatcher != null) {
dispatcher.removeReferences(removedComponent);
} else {
//It is a Lightweight Container, should clear parent`s Dispatcher
super.clearLightweightDispatcherOnRemove(removedComponent);
}
}
final Container getTraversalRoot() { final Container getTraversalRoot() {
if (isFocusCycleRoot()) { if (isFocusCycleRoot()) {
return findTraversalRoot(); return findTraversalRoot();
...@@ -4413,7 +4404,9 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4413,7 +4404,9 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
LightweightDispatcher(Container nativeContainer) { LightweightDispatcher(Container nativeContainer) {
this.nativeContainer = nativeContainer; this.nativeContainer = nativeContainer;
mouseEventTarget = null; mouseEventTarget = new WeakReference<>(null);
targetLastEntered = new WeakReference<>(null);
targetLastEnteredDT = new WeakReference<>(null);
eventMask = 0; eventMask = 0;
} }
...@@ -4424,9 +4417,9 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4424,9 +4417,9 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
void dispose() { void dispose() {
//System.out.println("Disposing lw dispatcher"); //System.out.println("Disposing lw dispatcher");
stopListeningForOtherDrags(); stopListeningForOtherDrags();
mouseEventTarget = null; mouseEventTarget.clear();
targetLastEntered = null; targetLastEntered.clear();
targetLastEnteredDT = null; targetLastEnteredDT.clear();
} }
/** /**
...@@ -4513,65 +4506,62 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4513,65 +4506,62 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
trackMouseEnterExit(mouseOver, e); trackMouseEnterExit(mouseOver, e);
// 4508327 : MOUSE_CLICKED should only go to the recipient of Component met = mouseEventTarget.get();
// the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a // 4508327 : MOUSE_CLICKED should only go to the recipient of
// MOUSE_CLICKED. // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) { // MOUSE_CLICKED.
mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null; if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
isCleaned = false; met = (mouseOver != nativeContainer) ? mouseOver : null;
mouseEventTarget = new WeakReference<>(met);
} }
if (mouseEventTarget != null) { if (met != null) {
switch (id) { switch (id) {
case MouseEvent.MOUSE_ENTERED: case MouseEvent.MOUSE_ENTERED:
case MouseEvent.MOUSE_EXITED: case MouseEvent.MOUSE_EXITED:
break; break;
case MouseEvent.MOUSE_PRESSED: case MouseEvent.MOUSE_PRESSED:
retargetMouseEvent(mouseEventTarget, id, e); retargetMouseEvent(met, id, e);
break; break;
case MouseEvent.MOUSE_RELEASED: case MouseEvent.MOUSE_RELEASED:
retargetMouseEvent(mouseEventTarget, id, e); retargetMouseEvent(met, id, e);
break; break;
case MouseEvent.MOUSE_CLICKED: case MouseEvent.MOUSE_CLICKED:
// 4508327: MOUSE_CLICKED should never be dispatched to a Component // 4508327: MOUSE_CLICKED should never be dispatched to a Component
// other than that which received the MOUSE_PRESSED event. If the // other than that which received the MOUSE_PRESSED event. If the
// mouse is now over a different Component, don't dispatch the event. // mouse is now over a different Component, don't dispatch the event.
// The previous fix for a similar problem was associated with bug // The previous fix for a similar problem was associated with bug
// 4155217. // 4155217.
if (mouseOver == mouseEventTarget) { if (mouseOver == met) {
retargetMouseEvent(mouseOver, id, e); retargetMouseEvent(mouseOver, id, e);
} }
break; break;
case MouseEvent.MOUSE_MOVED: case MouseEvent.MOUSE_MOVED:
retargetMouseEvent(mouseEventTarget, id, e); retargetMouseEvent(met, id, e);
break; break;
case MouseEvent.MOUSE_DRAGGED: case MouseEvent.MOUSE_DRAGGED:
if (isMouseGrab(e)) { if (isMouseGrab(e)) {
retargetMouseEvent(mouseEventTarget, id, e); retargetMouseEvent(met, id, e);
} }
break; break;
case MouseEvent.MOUSE_WHEEL: case MouseEvent.MOUSE_WHEEL:
// This may send it somewhere that doesn't have MouseWheelEvents // This may send it somewhere that doesn't have MouseWheelEvents
// enabled. In this case, Component.dispatchEventImpl() will // enabled. In this case, Component.dispatchEventImpl() will
// retarget the event to a parent that DOES have the events enabled. // retarget the event to a parent that DOES have the events enabled.
if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) { if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
eventLog.finest("retargeting mouse wheel to " + eventLog.finest("retargeting mouse wheel to " +
mouseOver.getName() + ", " + mouseOver.getName() + ", " +
mouseOver.getClass()); mouseOver.getClass());
}
retargetMouseEvent(mouseOver, id, e);
break;
} }
retargetMouseEvent(mouseOver, id, e); //Consuming of wheel events is implemented in "retargetMouseEvent".
break; if (id != MouseEvent.MOUSE_WHEEL) {
e.consume();
} }
//Consuming of wheel events is implemented in "retargetMouseEvent".
if (id != MouseEvent.MOUSE_WHEEL) {
e.consume();
} }
} else if (isCleaned && id != MouseEvent.MOUSE_WHEEL) { return e.isConsumed();
//After mouseEventTarget was removed and cleaned should consume all events
//until new mouseEventTarget is found
e.consume();
}
return e.isConsumed();
} }
private boolean processDropTargetEvent(SunDropTargetEvent e) { private boolean processDropTargetEvent(SunDropTargetEvent e) {
...@@ -4634,9 +4624,10 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4634,9 +4624,10 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
} else if (id == MouseEvent.MOUSE_EXITED) { } else if (id == MouseEvent.MOUSE_EXITED) {
isMouseDTInNativeContainer = false; isMouseDTInNativeContainer = false;
} }
targetLastEnteredDT = retargetMouseEnterExit(targetOver, e, Component tle = retargetMouseEnterExit(targetOver, e,
targetLastEnteredDT, targetLastEnteredDT.get(),
isMouseDTInNativeContainer); isMouseDTInNativeContainer);
targetLastEnteredDT = new WeakReference<>(tle);
} }
/* /*
...@@ -4662,9 +4653,10 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4662,9 +4653,10 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
isMouseInNativeContainer = false; isMouseInNativeContainer = false;
stopListeningForOtherDrags(); stopListeningForOtherDrags();
} }
targetLastEntered = retargetMouseEnterExit(targetOver, e, Component tle = retargetMouseEnterExit(targetOver, e,
targetLastEntered, targetLastEntered.get(),
isMouseInNativeContainer); isMouseInNativeContainer);
targetLastEntered = new WeakReference<>(tle);
} }
private Component retargetMouseEnterExit(Component targetOver, MouseEvent e, private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,
...@@ -4926,22 +4918,17 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4926,22 +4918,17 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
* is null, there are currently no events being forwarded to * is null, there are currently no events being forwarded to
* a subcomponent. * a subcomponent.
*/ */
private transient Component mouseEventTarget; private transient WeakReference<Component> mouseEventTarget;
/** /**
* The last component entered by the {@code MouseEvent}. * The last component entered by the {@code MouseEvent}.
*/ */
private transient Component targetLastEntered; private transient WeakReference<Component> targetLastEntered;
/** /**
* The last component entered by the {@code SunDropTargetEvent}. * The last component entered by the {@code SunDropTargetEvent}.
*/ */
private transient Component targetLastEnteredDT; private transient WeakReference<Component> targetLastEnteredDT;
/**
* Indicates whether {@code mouseEventTarget} was removed and nulled
*/
private transient boolean isCleaned;
/** /**
* Is the mouse over the native container. * Is the mouse over the native container.
...@@ -4982,17 +4969,4 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener { ...@@ -4982,17 +4969,4 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK; AWTEvent.MOUSE_WHEEL_EVENT_MASK;
void removeReferences(Component removedComponent) {
if (mouseEventTarget == removedComponent) {
isCleaned = true;
mouseEventTarget = null;
}
if (targetLastEntered == removedComponent) {
targetLastEntered = null;
}
if (targetLastEnteredDT == removedComponent) {
targetLastEnteredDT = null;
}
}
} }
/*
* 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 8061636
* @summary fix for 7079254 changes behavior of MouseListener, MouseMotionListener
* @library ../../regtesthelpers
* @build Util
* @author Alexander Zvegintsev
* @run main RemovedComponentMouseListener
*/
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import test.java.awt.regtesthelpers.Util;
public class RemovedComponentMouseListener extends JFrame {
static boolean mouseReleasedReceived;
static JButton button;
public RemovedComponentMouseListener() {
JPanel panel = new JPanel();
JPanel buttonPanel = new JPanel();
button = new JButton("Button");
setSize(300, 300);
buttonPanel.add(button);
panel.add(buttonPanel);
setContentPane(panel);
button.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
buttonPanel.remove(button);
panel.add(button);
button.revalidate();
button.repaint();
}
@Override
public void mouseReleased(MouseEvent e) {
mouseReleasedReceived = true;
}
});
setVisible(true);
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(() -> {
new RemovedComponentMouseListener();
});
Robot r = Util.createRobot();
r.setAutoDelay(100);
r.waitForIdle();
Util.pointOnComp(button, r);
r.waitForIdle();
r.mousePress(InputEvent.BUTTON1_MASK);
r.waitForIdle();
r.mouseRelease(InputEvent.BUTTON1_MASK);
r.waitForIdle();
if (!mouseReleasedReceived) {
throw new RuntimeException("mouseReleased event was not received");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册