/* * 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(). *

* 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; } } }