mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-19 01:47:52 +00:00
8024061: Exception thrown when drag and drop between two components is executed quickly
Reviewed-by: pchelko, serb
This commit is contained in:
parent
704f4dc113
commit
c6886100be
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2014, 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
|
||||
@ -239,6 +239,13 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer,
|
||||
|
||||
if (localTransferable != null) {
|
||||
return localTransferable.getTransferData(df);
|
||||
} else if (df.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType)) {
|
||||
// Workaround to JDK-8024061: Exception thrown when drag and drop
|
||||
// between two components is executed quickly.
|
||||
// It is expected localTransferable is not null if javaJVMLocalObjectMimeType
|
||||
// is used. Executing further results in ClassCastException, so null is
|
||||
// returned here as no transfer data is available in this case.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (dropStatus != STATUS_ACCEPT || dropComplete) {
|
||||
|
||||
357
jdk/test/sun/awt/dnd/8024061/bug8024061.java
Normal file
357
jdk/test/sun/awt/dnd/8024061/bug8024061.java
Normal file
@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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 8024061
|
||||
* @summary Checks that no exception is thrown if dragGestureRecognized
|
||||
* takes a while to complete.
|
||||
*/
|
||||
import sun.awt.OSInfo;
|
||||
import sun.awt.OSInfo.OSType;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.dnd.DragGestureEvent;
|
||||
import java.awt.dnd.DragGestureListener;
|
||||
import java.awt.dnd.DragSource;
|
||||
import java.awt.dnd.DragSourceDragEvent;
|
||||
import java.awt.dnd.DragSourceDropEvent;
|
||||
import java.awt.dnd.DragSourceEvent;
|
||||
import java.awt.dnd.DragSourceListener;
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.DropTargetDragEvent;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.awt.dnd.DropTargetEvent;
|
||||
import java.awt.dnd.DropTargetListener;
|
||||
import java.awt.event.InputEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* If dragGestureRecognized() takes a while to complete and if user performs a drag quickly,
|
||||
* an exception is thrown from DropTargetListener.dragEnter when it calls
|
||||
* DropTargetDragEvent.getTransferable().
|
||||
* <p>
|
||||
* This class introduces a delay in dragGestureRecognized() to cause the exception.
|
||||
*/
|
||||
public class bug8024061 {
|
||||
private static final DataFlavor DropObjectFlavor;
|
||||
private static final int DELAY = 1000;
|
||||
|
||||
private final DnDPanel panel1 = new DnDPanel(Color.yellow);
|
||||
private final DnDPanel panel2 = new DnDPanel(Color.pink);
|
||||
private final JFrame frame;
|
||||
|
||||
private static final CountDownLatch lock = new CountDownLatch(1);
|
||||
private static volatile Exception dragEnterException = null;
|
||||
|
||||
static {
|
||||
DataFlavor flavor = null;
|
||||
try {
|
||||
flavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
DropObjectFlavor = flavor;
|
||||
}
|
||||
|
||||
bug8024061() {
|
||||
frame = new JFrame("DnDWithRobot");
|
||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
||||
|
||||
Dimension d = new Dimension(100, 100);
|
||||
|
||||
panel1.setPreferredSize(d);
|
||||
panel2.setPreferredSize(d);
|
||||
|
||||
Container content = frame.getContentPane();
|
||||
content.setLayout(new GridLayout(1, 2, 5, 5));
|
||||
content.add(panel1);
|
||||
content.add(panel2);
|
||||
|
||||
frame.pack();
|
||||
|
||||
DropObject drop = new DropObject();
|
||||
drop.place(panel1, new Point(10, 10));
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws AWTException, InvocationTargetException, InterruptedException {
|
||||
OSType type = OSInfo.getOSType();
|
||||
if (type != OSType.LINUX && type != OSType.SOLARIS) {
|
||||
System.out.println("This test is for Linux and Solaris only... " +
|
||||
"skipping!");
|
||||
return;
|
||||
}
|
||||
|
||||
final bug8024061[] dnd = {null};
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dnd[0] = new bug8024061();
|
||||
}
|
||||
});
|
||||
final Robot robot = new Robot();
|
||||
robot.setAutoDelay(10);
|
||||
SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
|
||||
toolkit.realSync();
|
||||
|
||||
JFrame frame = dnd[0].frame;
|
||||
Point point = frame.getLocationOnScreen();
|
||||
Point here = new Point(point.x + 35, point.y + 45);
|
||||
Point there = new Point(point.x + 120, point.y + 45);
|
||||
here.x += 25;
|
||||
robot.mouseMove(here.x, here.y);
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
while (here.x < there.x) {
|
||||
here.x += 20;
|
||||
robot.mouseMove(here.x, here.y);
|
||||
System.out.println("x = " + here.x);
|
||||
}
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
toolkit.realSync();
|
||||
robot.mousePress(InputEvent.BUTTON1_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON1_MASK);
|
||||
System.out.println("finished");
|
||||
|
||||
try {
|
||||
if (lock.await(5, TimeUnit.SECONDS)) {
|
||||
if (dragEnterException == null) {
|
||||
System.out.println("Test passed.");
|
||||
} else {
|
||||
System.out.println("Test failed.");
|
||||
dragEnterException.printStackTrace();
|
||||
throw new RuntimeException(dragEnterException);
|
||||
}
|
||||
} else {
|
||||
System.out.println("Test failed. Timeout reached");
|
||||
throw new RuntimeException("Timed out waiting for dragEnter()");
|
||||
}
|
||||
} finally {
|
||||
frame.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class DropObject implements Transferable {
|
||||
DnDPanel panel;
|
||||
Color color = Color.CYAN;
|
||||
int width = 50;
|
||||
int height = 50;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
void draw(Graphics2D g) {
|
||||
Color savedColor = g.getColor();
|
||||
g.setColor(color);
|
||||
g.fillRect(x, y, width, height);
|
||||
g.setColor(Color.lightGray);
|
||||
g.drawRect(x, y, width, height);
|
||||
g.setColor(savedColor);
|
||||
}
|
||||
|
||||
boolean contains(int x, int y) {
|
||||
return (x > this.x && x < this.x + width)
|
||||
&& (y > this.y && y < this.y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[]{DropObjectFlavor};
|
||||
}
|
||||
|
||||
void place(DnDPanel panel, Point location) {
|
||||
if (panel != this.panel) {
|
||||
x = location.x;
|
||||
y = location.y;
|
||||
if (this.panel != null) {
|
||||
this.panel.setDropObject(null);
|
||||
this.panel.repaint();
|
||||
}
|
||||
this.panel = panel;
|
||||
this.panel.setDropObject(this);
|
||||
this.panel.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return DropObjectFlavor.equals(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor)
|
||||
throws UnsupportedFlavorException, IOException {
|
||||
if (isDataFlavorSupported(flavor)) {
|
||||
return this;
|
||||
} else {
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DnDPanel extends JPanel {
|
||||
DropObject dropObject;
|
||||
final DragSource dragSource;
|
||||
final DropTarget dropTarget;
|
||||
final Color color;
|
||||
final DragGestureListener dgListener;
|
||||
final DragSourceListener dsListener;
|
||||
final DropTargetListener dtListener;
|
||||
|
||||
DnDPanel(Color color) {
|
||||
this.color = color;
|
||||
this.dragSource = DragSource.getDefaultDragSource();
|
||||
dgListener = new DragGestureListener() {
|
||||
@Override
|
||||
public void dragGestureRecognized(DragGestureEvent dge) {
|
||||
Point location = dge.getDragOrigin();
|
||||
if (dropObject != null && dropObject.contains(location.x, location.y)) {
|
||||
dragSource.startDrag(dge, DragSource.DefaultCopyNoDrop, dropObject, dsListener);
|
||||
try {
|
||||
Thread.sleep(DELAY);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dsListener = new DragSourceListener() {
|
||||
@Override
|
||||
public void dragEnter(DragSourceDragEvent dsde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOver(DragSourceDragEvent dsde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropActionChanged(DragSourceDragEvent dsde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragExit(DragSourceEvent dse) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragDropEnd(DragSourceDropEvent dsde) {
|
||||
}
|
||||
};
|
||||
|
||||
dtListener = new DropTargetListener() {
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent dtde) {
|
||||
if (dropObject != null) {
|
||||
dtde.rejectDrag();
|
||||
return;
|
||||
}
|
||||
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
|
||||
try {
|
||||
Transferable t = dtde.getTransferable();
|
||||
Object data = t.getTransferData(DropObjectFlavor);
|
||||
if (data != null) {
|
||||
throw new Exception("getTransferData returned non-null");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
dragEnterException = e;
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
lock.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent dtde) {
|
||||
if (dropObject != null) {
|
||||
dtde.rejectDrag();
|
||||
return;
|
||||
}
|
||||
dtde.acceptDrag(DnDConstants.ACTION_MOVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropActionChanged(DropTargetDragEvent dtde) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent dte) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drop(DropTargetDropEvent dtde) {
|
||||
if (dropObject != null) {
|
||||
dtde.rejectDrop();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
|
||||
Transferable t = dtde.getTransferable();
|
||||
DropObject dropObject = (DropObject) t.getTransferData(DropObjectFlavor);
|
||||
Point location = dtde.getLocation();
|
||||
dropObject.place(DnDPanel.this, location);
|
||||
dtde.dropComplete(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
dragSource.createDefaultDragGestureRecognizer(this,
|
||||
DnDConstants.ACTION_MOVE, dgListener);
|
||||
|
||||
dropTarget = new DropTarget(this, DnDConstants.ACTION_MOVE, dtListener, true);
|
||||
|
||||
}
|
||||
|
||||
public void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
Color savedColor = g.getColor();
|
||||
g.setColor(color);
|
||||
g.fillRect(0, 0, getWidth(), getHeight());
|
||||
g.setColor(savedColor);
|
||||
if (dropObject != null) {
|
||||
dropObject.draw((Graphics2D) g);
|
||||
}
|
||||
}
|
||||
|
||||
void setDropObject(DropObject dropObject) {
|
||||
this.dropObject = dropObject;
|
||||
}
|
||||
|
||||
DropObject findDropObject(int x, int y) {
|
||||
if (dropObject != null && dropObject.contains(x, y)) {
|
||||
return dropObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user