diff --git a/test/jdk/java/awt/dnd/DropTargetInInternalFrameTest.java b/test/jdk/java/awt/dnd/DropTargetInInternalFrameTest.java new file mode 100644 index 00000000000..6ee0f425724 --- /dev/null +++ b/test/jdk/java/awt/dnd/DropTargetInInternalFrameTest.java @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2000, 2022, 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.Button; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +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.DropTargetContext; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +/* + @test + @bug 4395279 + @summary Tests that a drop target in InternalFrame functions properly + @key headful + @run main DropTargetInInternalFrameTest +*/ +public class DropTargetInInternalFrameTest implements Serializable { + private static final CountDownLatch dropLatch = new CountDownLatch(1); + private static final CountDownLatch focusLatch = new CountDownLatch(1); + private static JFrame frame; + private static JInternalFrame sourceFrame; + private static JInternalFrame targetFrame; + private static DragSourcePanel dragSourcePanel; + private static DropTargetPanel dropTargetPanel; + private static Robot robot; + + private static void createUI() { + frame = new JFrame("Test frame"); + sourceFrame = new JInternalFrame("Source"); + targetFrame = new JInternalFrame("Destination"); + dragSourcePanel = new DragSourcePanel(); + dropTargetPanel = new DropTargetPanel(dropLatch); + JDesktopPane desktopPane = new JDesktopPane(); + + sourceFrame.getContentPane().setLayout(new GridLayout(3, 1)); + + // add panels to content panes + sourceFrame.getContentPane().add(dragSourcePanel); + targetFrame.getContentPane().add(dropTargetPanel); + + sourceFrame.setSize(200, 200); + targetFrame.setSize(200, 200); + targetFrame + .setLocation(sourceFrame.getX() + sourceFrame.getWidth() + 10, + sourceFrame.getY()); + + desktopPane.add(sourceFrame); + desktopPane.add(targetFrame); + + frame.setTitle("Test frame"); + frame.setBounds(200, 200, 450, 250); + frame.getContentPane().add(desktopPane); + frame.setAlwaysOnTop(true); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + + sourceFrame.setVisible(true); + targetFrame.setVisible(true); + frame.setVisible(true); + dragSourcePanel.dragSourceButton.requestFocusInWindow(); + } + + public static void main(String[] argv) throws Exception { + SwingUtilities.invokeAndWait(DropTargetInInternalFrameTest::createUI); + + robot = new Robot(); + robot.setAutoDelay(50); + robot.setAutoWaitForIdle(true); + robot.waitForIdle(); + if (!focusLatch.await(5, TimeUnit.SECONDS)) { + captureScreen(); + SwingUtilities + .invokeAndWait(DropTargetInInternalFrameTest::disposeFrame); + System.out.println( + "Test failed, waited too long for the drag button to gain focus"); + } + final AtomicReference p1Ref = new AtomicReference<>(); + final AtomicReference p2Ref = new AtomicReference<>(); + SwingUtilities.invokeAndWait(() -> { + final Point dragLocation = + dragSourcePanel.dragSourceButton.getLocationOnScreen(); + Dimension d1 = dragSourcePanel.dragSourceButton.getSize(); + dragLocation.translate(d1.width / 2, d1.height / 2); + p1Ref.set(dragLocation); + final Point dropLocation = dropTargetPanel.getLocationOnScreen(); + dropLocation.translate(d1.width / 2, d1.height / 2); + p2Ref.set(dropLocation); + }); + Point p1 = p1Ref.get(); + Point p2 = p2Ref.get(); + + dragAndDrop(p1, p2); + + if (!dropLatch.await(5, TimeUnit.SECONDS)) { + captureScreen(); + System.out.println("Test Failed, Waited too long for the Drop to complete"); + } + int calledMethods = dropTargetPanel.getCalledMethods(); + SwingUtilities + .invokeAndWait(DropTargetInInternalFrameTest::disposeFrame); + System.out.println("CalledMethods = " + calledMethods); + if ((calledMethods & DropTargetPanel.ENTER_CALLED) == 0) { + throw new RuntimeException( + "Test Failed, DropTargetListener.dragEnter() not called"); + } + if ((calledMethods & DropTargetPanel.OVER_CALLED) == 0) { + throw new RuntimeException( + "Test Failed, DropTargetListener.dragOver() not called"); + } + if ((calledMethods & DropTargetPanel.DROP_CALLED) == 0) { + throw new RuntimeException( + "Test Failed, DropTargetListener.drop() not called."); + } + + System.out.println("Test Passed"); + } + + private static void dragAndDrop(final Point p1, final Point p2) { + robot.mouseMove(p1.x, p1.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + int dx = 1; + while (p1.x < p2.x) { + p1.translate(dx, 0); + robot.mouseMove(p1.x, p1.y); + dx++; + } + robot.mouseMove(p2.x, p2.y); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } + + private static void captureScreen() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + try { + ImageIO.write(robot.createScreenCapture( + new Rectangle(0, 0, screenSize.width, screenSize.height)), + "png", new File("screenImage.png")); + } catch (IOException ignore) { + } + } + + private static void disposeFrame() { + sourceFrame.dispose(); + targetFrame.dispose(); + frame.dispose(); + } + + private static class DragSourcePanel extends JPanel { + + final Dimension preferredDimension = new Dimension(200, 100); + final DragSourceButton dragSourceButton = new DragSourceButton(); + + public DragSourcePanel() { + setLayout(new GridLayout(1, 1)); + dragSourceButton.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(final FocusEvent e) { + super.focusGained(e); + focusLatch.countDown(); + } + }); + add(dragSourceButton); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + } + + private static class DropTargetPanel extends JPanel + implements DropTargetListener { + + public static final int ENTER_CALLED = 0x1; + public static final int OVER_CALLED = 0x2; + public static final int DROP_CALLED = 0x4; + private final Dimension preferredDimension = new Dimension(200, 100); + private final CountDownLatch dropLatch; + private volatile int calledMethods = 0; + + public DropTargetPanel(final CountDownLatch dropLatch) { + this.dropLatch = dropLatch; + setDropTarget(new DropTarget(this, this)); + } + + public Dimension getPreferredSize() { + return preferredDimension; + } + + public void dragEnter(DropTargetDragEvent dtde) { + calledMethods |= ENTER_CALLED; + } + + public void dragOver(DropTargetDragEvent dtde) { + calledMethods |= OVER_CALLED; + } + + public void dropActionChanged(DropTargetDragEvent dtde) { + } + + public void dragExit(DropTargetEvent dte) { + } + + public void drop(DropTargetDropEvent dtde) { + System.out.println("Drop!!!!!!!!!!!! "); + calledMethods |= DROP_CALLED; + DropTargetContext dtc = dtde.getDropTargetContext(); + + if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) { + dtde.acceptDrop(DnDConstants.ACTION_COPY); + } else { + dtde.rejectDrop(); + } + + DataFlavor[] dfs = dtde.getCurrentDataFlavors(); + Component comp = null; + + if (dfs != null && dfs.length >= 1) { + Transferable transfer = dtde.getTransferable(); + + try { + comp = (Component) transfer.getTransferData(dfs[0]); + } catch (Throwable e) { + e.printStackTrace(); + dtc.dropComplete(false); + } + } + dtc.dropComplete(true); + add(comp); + dropLatch.countDown(); + } + + public int getCalledMethods() { + return calledMethods; + } + + } + + private static class DragSourceButton extends JButton + implements Serializable, Transferable, DragGestureListener, + DragSourceListener { + private final DataFlavor dataflavor = + new DataFlavor(Button.class, "DragSourceButton"); + + public DragSourceButton() { + this("DragSourceButton"); + } + + public DragSourceButton(String str) { + super(str); + DragSource ds = DragSource.getDefaultDragSource(); + ds.createDefaultDragGestureRecognizer(this, + DnDConstants.ACTION_COPY, + this); + } + + public void dragGestureRecognized(DragGestureEvent dge) { + dge.startDrag(new Cursor(Cursor.HAND_CURSOR), this, this); + } + + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[]{dataflavor}; + } + + public boolean isDataFlavorSupported(DataFlavor dflavor) { + return dataflavor.equals(dflavor); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, IOException { + + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + Object retObj; + ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); + ObjectOutputStream ooStream = new ObjectOutputStream(baoStream); + ooStream.writeObject(this); + + ByteArrayInputStream baiStream = + new ByteArrayInputStream(baoStream.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(baiStream); + try { + retObj = ois.readObject(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + throw new RuntimeException(e.toString()); + } + return retObj; + } + + @Override + public void dragEnter(final DragSourceDragEvent dsde) { + + } + + @Override + public void dragOver(final DragSourceDragEvent dsde) { + + } + + @Override + public void dropActionChanged(final DragSourceDragEvent dsde) { + + } + + @Override + public void dragExit(final DragSourceEvent dse) { + + } + + @Override + public void dragDropEnd(final DragSourceDropEvent dsde) { + + } + + } + +}