diff --git a/test/jdk/java/awt/dnd/DnDAWTLockTest.java b/test/jdk/java/awt/dnd/DnDAWTLockTest.java
new file mode 100644
index 00000000000..1db4be45ccc
--- /dev/null
+++ b/test/jdk/java/awt/dnd/DnDAWTLockTest.java
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2003, 2023, 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 4913349
+ @summary verifies that AWT_LOCK is properly taken during DnD
+ @key headful
+ @run main DnDAWTLockTest
+*/
+
+import java.awt.AWTEvent;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.AWTEventListener;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.io.File;
+import java.io.InputStream;
+import java.util.StringTokenizer;
+
+
+public class DnDAWTLockTest implements ClipboardOwner {
+ public static final int STARTUP_TIMEOUT = 2000;
+ volatile Frame frame;
+
+ static final Clipboard clipboard =
+ Toolkit.getDefaultToolkit().getSystemClipboard();
+
+ volatile Process process = null;
+ volatile Point sourcePoint = null;
+
+ public static void main(String[] args) throws Exception {
+ DnDAWTLockTest test = new DnDAWTLockTest();
+ EventQueue.invokeAndWait(test::init);
+ try {
+ test.start();
+ } finally {
+ EventQueue.invokeAndWait(() -> test.frame.dispose());
+ }
+ }
+
+ public void init() {
+ frame = new Frame("Drop target frame");
+ frame.setLocation(200, 200);
+ Panel panel = new DragSourcePanel();
+ frame.add(panel);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public void start() throws Exception {
+ String stderr = null;
+
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(1000);
+
+ Point p = frame.getLocationOnScreen();
+ Dimension d = frame.getSize();
+
+ Point pp = new Point(p);
+ pp.translate(d.width / 2, d.height / 2);
+
+ if (!Util.pointInComponent(robot, pp, frame)) {
+ System.err.println("WARNING: Couldn't locate " + frame +
+ " at point " + pp);
+ return;
+ }
+
+ sourcePoint = pp;
+ clipboard.setContents(new StringSelection(Util.TRANSFER_DATA),
+ this);
+
+ String javaPath = System.getProperty("java.home", "");
+ String[] command = {
+ javaPath + File.separator + "bin" + File.separator + "java",
+ "-cp", System.getProperty("test.classes", "."),
+ "Child"
+ };
+
+ process = Runtime.getRuntime().exec(command);
+ ProcessResults pres = ProcessResults.doWaitFor(process);
+
+ stderr = pres.stderr;
+
+ if (pres.stderr != null && pres.stderr.length() > 0) {
+ System.err.println("========= Child VM System.err ========");
+ System.err.print(pres.stderr);
+ System.err.println("======================================");
+ }
+
+ if (pres.stdout != null && pres.stdout.length() > 0) {
+ System.err.println("========= Child VM System.out ========");
+ System.err.print(pres.stdout);
+ System.err.println("======================================");
+ }
+
+ System.err.println("Child VM return code: " + pres.exitValue);
+
+ if (stderr != null && stderr.contains("InternalError")) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+
+ public void lostOwnership(Clipboard c, Transferable trans) {
+ Runnable r = new Runnable() {
+ public void run() {
+ try {
+ if (process == null) {
+ throw new RuntimeException("Null process");
+ }
+
+ if (sourcePoint == null) {
+ throw new RuntimeException("Null point");
+ }
+
+ Thread.sleep(STARTUP_TIMEOUT);
+ Transferable t = clipboard.getContents(null);
+
+ String s =
+ (String) t.getTransferData(DataFlavor.stringFlavor);
+ StringTokenizer st = new StringTokenizer(s);
+
+ int x = Integer.parseInt(st.nextToken());
+ int y = Integer.parseInt(st.nextToken());
+
+ Point targetPoint = new Point(x, y);
+
+ Robot robot = new Robot();
+
+ robot.mouseMove(sourcePoint.x, sourcePoint.y);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ for (; !sourcePoint.equals(targetPoint);
+ sourcePoint.translate(
+ sign(targetPoint.x - sourcePoint.x),
+ sign(targetPoint.y - sourcePoint.y)
+ )) {
+ robot.mouseMove(sourcePoint.x, sourcePoint.y);
+ robot.delay(25);
+ }
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ } catch (Exception e) {
+ e.printStackTrace();
+ process.destroy();
+ }
+ }
+ };
+ new Thread(r).start();
+ }
+
+ public static int sign(int n) {
+ return Integer.compare(n, 0);
+ }
+}
+
+class Child {
+ public static final int ACTION_TIMEOUT = 30000;
+
+ volatile Frame frame;
+ volatile Panel panel;
+
+
+ public void init() {
+ panel = new DropTargetPanel();
+
+ frame = new Frame("Drag source frame");
+ frame.setLocation(500, 200);
+ frame.add(panel);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public void run() {
+ try {
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(1000);
+
+ Point targetPoint = panel.getLocationOnScreen();
+ Dimension d = panel.getSize();
+ targetPoint.translate(d.width / 2, d.height / 2);
+
+ if (!Util.pointInComponent(robot, targetPoint, panel)) {
+ System.err.println("WARNING: Couldn't locate " + panel +
+ " at point " + targetPoint);
+ System.exit(0);
+ }
+
+ String positionData = "" + targetPoint.x + " " + targetPoint.y;
+ DnDAWTLockTest.clipboard.setContents(
+ new StringSelection(positionData), null);
+
+ Thread.sleep(ACTION_TIMEOUT);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ System.exit(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ Child child = new Child();
+ EventQueue.invokeAndWait(child::init);
+ try {
+ child.run();
+ } finally {
+ EventQueue.invokeAndWait(() -> child.frame.dispose());
+ }
+ }
+}
+
+class Util implements AWTEventListener {
+ private static final Toolkit tk = Toolkit.getDefaultToolkit();
+ public static final Object SYNC_LOCK = new Object();
+ private Component clickedComponent = null;
+ private static final int PAINT_TIMEOUT = 10000;
+ private static final int MOUSE_RELEASE_TIMEOUT = 10000;
+ private static final Util util = new Util();
+ public static final String TRANSFER_DATA = "TRANSFER_DATA";
+
+ static {
+ tk.addAWTEventListener(util, 0xFFFFFFFF);
+ }
+
+ private void reset() {
+ clickedComponent = null;
+ }
+
+ public void eventDispatched(AWTEvent e) {
+ if (e.getID() == MouseEvent.MOUSE_RELEASED) {
+ clickedComponent = (Component)e.getSource();
+ synchronized (SYNC_LOCK) {
+ SYNC_LOCK.notifyAll();
+ }
+ }
+ }
+
+ public static boolean pointInComponent(Robot robot, Point p, Component comp)
+ throws InterruptedException {
+ return util.isPointInComponent(robot, p, comp);
+ }
+
+ private boolean isPointInComponent(Robot robot, Point p, Component comp)
+ throws InterruptedException {
+ tk.sync();
+ robot.waitForIdle();
+ reset();
+ robot.mouseMove(p.x, p.y);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ synchronized (SYNC_LOCK) {
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
+ }
+
+ Component c = clickedComponent;
+
+ while (c != null && c != comp) {
+ c = c.getParent();
+ }
+
+ return c == comp;
+ }
+}
+
+class DragSourcePanel extends Panel {
+ public DragSourcePanel() {
+ final Transferable t = new StringSelection(Util.TRANSFER_DATA);
+ final DragGestureListener dgl = new DragGestureListener() {
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ dge.startDrag(null, t);
+ }
+ };
+ final DragSource ds = DragSource.getDefaultDragSource();
+ final DragGestureRecognizer dgr =
+ ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY,
+ dgl);
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(100, 100);
+ }
+}
+
+class DropTargetPanel extends Panel {
+ public DropTargetPanel() {
+ final DropTargetListener dtl = new DropTargetAdapter() {
+ public void drop(DropTargetDropEvent dtde) {
+ Transferable t = dtde.getTransferable();
+ dtde.acceptDrop(dtde.getDropAction());
+ try {
+ t.getTransferData(DataFlavor.stringFlavor);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ dtde.dropComplete(true);
+ EventQueue.invokeLater(new Runnable() {
+ public void run() {
+ System.exit(0);
+ }
+ });
+ }
+ };
+ final DropTarget dt = new DropTarget(this, dtl);
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(100, 100);
+ }
+}
+
+class ProcessResults {
+ public int exitValue;
+ public String stdout;
+ public String stderr;
+
+ public ProcessResults() {
+ exitValue = -1;
+ stdout = "";
+ stderr = "";
+ }
+
+ /**
+ * Method to perform a "wait" for a process and return its exit value.
+ * This is a workaround for Process.waitFor() never returning.
+ */
+ public static ProcessResults doWaitFor(Process p) {
+ ProcessResults pres = new ProcessResults();
+
+ InputStream in = null;
+ InputStream err = null;
+
+ try {
+ in = p.getInputStream();
+ err = p.getErrorStream();
+
+ boolean finished = false;
+
+ while (!finished) {
+ try {
+ while (in.available() > 0) {
+ pres.stdout += (char)in.read();
+ }
+ while (err.available() > 0) {
+ pres.stderr += (char)err.read();
+ }
+ // Ask the process for its exitValue. If the process
+ // is not finished, an IllegalThreadStateException
+ // is thrown. If it is finished, we fall through and
+ // the variable finished is set to true.
+ pres.exitValue = p.exitValue();
+ finished = true;
+ }
+ catch (IllegalThreadStateException e) {
+ // Process is not finished yet;
+ // Sleep a little to save on CPU cycles
+ Thread.sleep(500);
+ }
+ }
+ if (in != null) in.close();
+ if (err != null) err.close();
+ }
+ catch (Throwable e) {
+ System.err.println("doWaitFor(): unexpected exception");
+ e.printStackTrace();
+ }
+ return pres;
+ }
+}
diff --git a/test/jdk/java/awt/dnd/DragGestureInvokeLaterTest.java b/test/jdk/java/awt/dnd/DragGestureInvokeLaterTest.java
new file mode 100644
index 00000000000..aba465a5693
--- /dev/null
+++ b/test/jdk/java/awt/dnd/DragGestureInvokeLaterTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2001, 2023, 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 4354044
+ @summary tests that a drag can be initiated with MOUSE_MOVED event
+ @key headful
+*/
+
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.datatransfer.StringSelection;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+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.InvalidDnDOperationException;
+import java.awt.event.InputEvent;
+
+public class DragGestureInvokeLaterTest {
+
+ volatile Frame frame;
+ volatile DragSourcePanel panel;
+
+ public static void main(String[] args) throws Exception {
+ DragGestureInvokeLaterTest test =
+ new DragGestureInvokeLaterTest();
+ EventQueue.invokeAndWait(test::init);
+ try {
+ test.start();
+ } finally {
+ EventQueue.invokeAndWait(() -> test.frame.dispose());
+ }
+ }
+
+ public void init() {
+ panel = new DragSourcePanel();
+ frame = new Frame("DragGestureInvokeLaterTest frame");
+ frame.setSize(200, 200);
+ frame.setLocation(200, 200);
+ frame.add(panel);
+ frame.setVisible(true);
+ }
+
+ public void start() throws Exception {
+ Robot robot = new Robot();
+
+ robot.waitForIdle();
+ robot.delay(1000);
+
+ Point loc = panel.getLocationOnScreen();
+
+ robot.mouseMove(loc.x + 2, loc.y + 2);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+
+ for (int i = 0; i < 10; i++) {
+ robot.delay(100);
+ robot.mouseMove(loc.x + 2 + i, loc.y + 2 + i);
+ }
+
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.delay(1000);
+ }
+}
+
+class DragSourcePanel extends Panel
+ implements DragSourceListener, DragGestureListener {
+
+ DragSource ds;
+ DragGestureRecognizer dgr;
+
+ public DragSourcePanel() {
+ ds = new DragSource();
+ dgr = ds.createDefaultDragGestureRecognizer(this,
+ DnDConstants.ACTION_COPY_OR_MOVE, this);
+ }
+
+ public void dragGestureRecognized(DragGestureEvent e) {
+ Runnable dragThread = new DragThread(e);
+ EventQueue.invokeLater(dragThread);
+ }
+
+ class DragThread implements Runnable {
+
+ DragGestureEvent event;
+
+ public DragThread(DragGestureEvent e) {
+ event = e;
+ }
+
+ public void run() {
+ try {
+ event.startDrag(DragSource.DefaultCopyNoDrop,
+ new StringSelection("Test"), DragSourcePanel.this);
+ } catch (InvalidDnDOperationException e) {
+ System.out.println("The test PASSED");
+ return;
+ }
+ throw new RuntimeException(
+ "Test failed, InvalidDnDOperationException is not thrown");
+ }
+ }
+
+ public void dragEnter(DragSourceDragEvent e) {}
+
+ public void dragOver(DragSourceDragEvent e) {}
+
+ public void dropActionChanged(DragSourceDragEvent e) {}
+
+ public void dragExit(DragSourceEvent e) {}
+
+ public void dragDropEnd(DragSourceDropEvent e) {}
+}
diff --git a/test/jdk/java/awt/dnd/DragOverDropTargetPerformanceTest.java b/test/jdk/java/awt/dnd/DragOverDropTargetPerformanceTest.java
new file mode 100644
index 00000000000..886165637b0
--- /dev/null
+++ b/test/jdk/java/awt/dnd/DragOverDropTargetPerformanceTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2001, 2023, 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 4445747
+ @summary tests that drag over drop target is not very slow on Win9X/WinME
+ @key headful
+*/
+
+import java.awt.Button;
+import java.awt.Dimension;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+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.DropTargetAdapter;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.dnd.InvalidDnDOperationException;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.io.Serializable;
+
+public class DragOverDropTargetPerformanceTest {
+
+ Frame frame;
+ volatile DragSourceButton dragSourceButton;
+ volatile DropTargetPanel dropTargetPanel;
+
+ static final int FRAME_ACTIVATION_TIMEOUT = 1000;
+ static final int DROP_COMPLETION_TIMEOUT = 1000;
+
+ public static void main(String[] args) throws Exception {
+ DragOverDropTargetPerformanceTest test =
+ new DragOverDropTargetPerformanceTest();
+
+ EventQueue.invokeAndWait(test::init);
+ try {
+ test.start();
+ } finally {
+ EventQueue.invokeAndWait(()-> test.frame.dispose());
+ }
+ }
+
+ public void init() {
+ dragSourceButton = new DragSourceButton();
+ dropTargetPanel = new DropTargetPanel();
+
+ frame = new Frame();
+ frame.setTitle("DragOverDropTargetPerformanceTest frame");
+ frame.setLocation(200, 200);
+ frame.setLayout(new GridLayout(2, 1));
+ frame.add(dragSourceButton);
+ frame.add(dropTargetPanel);
+
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+ public static int sign(int n) {
+ return Integer.compare(n, 0);
+ }
+
+ public void start() throws Exception {
+ Robot robot = new Robot();
+ robot.setAutoDelay(10);
+ robot.waitForIdle();
+ robot.delay(FRAME_ACTIVATION_TIMEOUT);
+
+ Point srcPoint = dragSourceButton.getLocationOnScreen();
+ Dimension d = dragSourceButton.getSize();
+ srcPoint.translate(d.width / 2, d.height / 2);
+
+ Point dstPoint = dropTargetPanel.getLocationOnScreen();
+ d = dropTargetPanel.getSize();
+ dstPoint.translate(d.width / 2, d.height / 2);
+
+ robot.mouseMove(srcPoint.x, srcPoint.y);
+ robot.keyPress(KeyEvent.VK_CONTROL);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+
+ for (;!srcPoint.equals(dstPoint);
+ srcPoint.translate(sign(dstPoint.x - srcPoint.x),
+ sign(dstPoint.y - srcPoint.y))) {
+ robot.mouseMove(srcPoint.x, srcPoint.y);
+ robot.delay(10);
+ }
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ robot.keyRelease(KeyEvent.VK_CONTROL);
+
+ robot.delay(DROP_COMPLETION_TIMEOUT);
+
+ long dstime = dragSourceButton.getDragSourceTime();
+ long dttime = dragSourceButton.getDropTargetTime();
+ if (dstime == 0 || dttime == 0) {
+ System.err.println(
+ "WARNING: couldn't emulate DnD to measure performance.");
+ } else if (dttime > dstime * 4) {
+ throw new RuntimeException("The test failed." +
+ "Over drag source: " + dstime + "." +
+ "Over drop target: " + dttime);
+ }
+ }
+}
+
+class DragSourceButton extends Button implements Serializable,
+ Transferable,
+ DragGestureListener,
+ DragSourceListener {
+ private final DataFlavor dataflavor =
+ new DataFlavor(Button.class, "DragSourceButton");
+ private volatile long dsTime = 0;
+ private volatile long dtTime = 0;
+
+ 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) {
+ try {
+ dge.startDrag(null, this, this);
+ dsTime = System.currentTimeMillis();
+ } catch (InvalidDnDOperationException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void dragEnter(DragSourceDragEvent dsde) {
+ long currentTime = System.currentTimeMillis();
+ dsTime = currentTime - dsTime;
+ dtTime = currentTime;
+ }
+
+ public void dragExit(DragSourceEvent dse) {}
+
+ public void dragOver(DragSourceDragEvent dsde) {}
+
+ public void dragDropEnd(DragSourceDropEvent dsde) {
+ long currentTime = System.currentTimeMillis();
+ dtTime = currentTime - dtTime;
+ }
+
+ public void dropActionChanged(DragSourceDragEvent dsde) {}
+
+ public Object getTransferData(DataFlavor flavor)
+ throws UnsupportedFlavorException, IOException {
+
+ if (!isDataFlavorSupported(flavor)) {
+ throw new UnsupportedFlavorException(flavor);
+ }
+
+ return this;
+ }
+
+ public DataFlavor[] getTransferDataFlavors() {
+ return new DataFlavor[] { dataflavor };
+ }
+
+ public boolean isDataFlavorSupported(DataFlavor dflavor) {
+ return dataflavor.equals(dflavor);
+ }
+
+ public long getDragSourceTime() {
+ return dsTime;
+ }
+
+ public long getDropTargetTime() {
+ return dtTime;
+ }
+}
+
+class DropTargetPanel extends Panel {
+
+ final Dimension preferredDimension = new Dimension(200, 200);
+ final DropTargetListener dtl = new DropTargetAdapter() {
+ public void drop(DropTargetDropEvent dtde) {
+ dtde.rejectDrop();
+ }
+ };
+
+ public DropTargetPanel() {
+ setDropTarget(new DropTarget(this, dtl));
+ }
+
+ public Dimension getPreferredSize() {
+ return preferredDimension;
+ }
+
+}
diff --git a/test/jdk/java/awt/dnd/DragSourceDragEventModifiersTest.java b/test/jdk/java/awt/dnd/DragSourceDragEventModifiersTest.java
new file mode 100644
index 00000000000..ac7d31b6b94
--- /dev/null
+++ b/test/jdk/java/awt/dnd/DragSourceDragEventModifiersTest.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2003, 2023, 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 4924527
+ @summary tests DragSourceDragEvent.getGestureModifiers[Ex]() \
+ for valid and invalid modifiers
+ @key headful
+*/
+
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragGestureRecognizer;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceContext;
+import java.awt.dnd.DragSourceDragEvent;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.event.InputEvent;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+
+public class DragSourceDragEventModifiersTest {
+ boolean failed;
+
+ static class DummyImage extends Image {
+ public DummyImage() {}
+ public int getWidth(ImageObserver observer) {return 0;}
+ public int getHeight(ImageObserver observer){return 0;}
+ public ImageProducer getSource() {return null;}
+ public Graphics getGraphics() {return null;}
+ public void flush() {}
+
+ public Object getProperty(String name, ImageObserver observer) {
+ return null;
+ }
+ }
+
+ static class DummyDGRecognizer extends DragGestureRecognizer {
+ private final DragSource dragSource;
+ private final Component component;
+
+ public DummyDGRecognizer(DragSource ds,Component c) {
+ super(ds,c);
+ component = c;
+ dragSource = ds;
+ }
+
+ public void addDragGestureListener(DragGestureListener dgl) {}
+ public void appendEvent(InputEvent awtie) {}
+ public void fireDragGestureRecognized(int dragAction, Point p) {}
+ public Component getComponent() {return component;}
+ public DragSource getDragSource() {return dragSource;}
+ public int getSourceActions() {return DnDConstants.ACTION_COPY_OR_MOVE;}
+ public InputEvent getTriggerEvent() {return null;}
+ public void registerListeners() {}
+ public void removeDragGestureListener(DragGestureListener dgl) {}
+ public void resetRecognizer() {}
+ public void setComponent(Component c) {}
+ public void setSourceActions(int actions) {}
+ public void unregisterListeners() {}
+ }
+
+
+ DragSource ds = new DragSource();
+
+ int[] actions = {
+ DnDConstants.ACTION_NONE,
+ DnDConstants.ACTION_COPY,
+ DnDConstants.ACTION_MOVE,
+ DnDConstants.ACTION_COPY_OR_MOVE,
+ DnDConstants.ACTION_LINK,
+ DnDConstants.ACTION_REFERENCE
+ };
+
+ Cursor[] cursors = {
+ DragSource.DefaultCopyDrop,
+ DragSource.DefaultMoveDrop,
+ DragSource.DefaultLinkDrop,
+ DragSource.DefaultCopyNoDrop,
+ DragSource.DefaultMoveNoDrop,
+ DragSource.DefaultLinkNoDrop
+ };
+
+ DummyImage image = new DummyImage();
+
+ Point point = new Point(0,0);
+
+ Transferable transferable = new Transferable() {
+ public DataFlavor[] getTransferDataFlavors() {return null;}
+ public boolean isDataFlavorSupported(DataFlavor flavor) {return false;}
+ public Object getTransferData(DataFlavor flavor) {return null;}
+ };
+
+ DragSourceListener dsl = new DragSourceListener() {
+ public void dragEnter(DragSourceDragEvent dsde) {}
+ public void dragOver(DragSourceDragEvent dsde) {}
+ public void dropActionChanged(DragSourceDragEvent dsde) {}
+ public void dragExit(DragSourceEvent dsde) {}
+ public void dragDropEnd(DragSourceDropEvent dsde) {}
+ };
+ /*
+ int modifiers[] = {
+ InputEvent.ALT_GRAPH_MASK,
+ InputEvent.ALT_MASK,
+ InputEvent.BUTTON1_MASK,
+ InputEvent.BUTTON2_MASK,
+ InputEvent.BUTTON3_MASK,
+ InputEvent.CTRL_MASK,
+ InputEvent.META_MASK,
+ InputEvent.SHIFT_MASK
+ };
+
+ int exModifiers[] = {
+ InputEvent.SHIFT_DOWN_MASK,
+ InputEvent.ALT_DOWN_MASK,
+ InputEvent.BUTTON1_DOWN_MASK,
+ InputEvent.BUTTON2_DOWN_MASK,
+ InputEvent.BUTTON3_DOWN_MASK,
+ InputEvent.CTRL_DOWN_MASK,
+ InputEvent.META_DOWN_MASK,
+ InputEvent.ALT_GRAPH_DOWN_MASK,
+ };
+ */
+ DragGestureEvent getDragGestureEvent() {
+ java.util.Vector vector = new java.util.Vector();
+ vector.add(new java.lang.Integer(0));
+ return new DragGestureEvent(new DummyDGRecognizer(ds, new Button()),
+ actions[1],
+ new java.awt.Point(0,0),
+ vector);
+ }
+ DragGestureEvent dge = getDragGestureEvent();
+
+ DragSourceContext dsc = new DragSourceContext(dge,
+ cursors[0],
+ image,
+ point,
+ transferable,
+ dsl);
+
+ public static void main(String[] args) {
+ new DragSourceDragEventModifiersTest().start();
+ }
+
+ public void start() {
+ try {
+ // valid modifiers:
+
+ check(InputEvent.BUTTON1_MASK, InputEvent.BUTTON1_MASK,
+ InputEvent.BUTTON1_DOWN_MASK);
+
+ check(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK,
+ InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK,
+ InputEvent.BUTTON1_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+
+ check(InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON1_MASK,
+ InputEvent.BUTTON1_DOWN_MASK);
+
+ check(InputEvent.BUTTON1_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK,
+ InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK,
+ InputEvent.BUTTON1_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+
+ // invalid modifiers:
+
+ int invalidMods = 0;
+ check(invalidMods, invalidMods, invalidMods);
+
+ invalidMods = InputEvent.BUTTON1_DOWN_MASK | InputEvent.SHIFT_MASK;
+ check(invalidMods, invalidMods, invalidMods);
+
+ invalidMods = (InputEvent.ALT_GRAPH_DOWN_MASK << 1);
+ check(invalidMods, invalidMods, invalidMods);
+
+ invalidMods = InputEvent.BUTTON1_DOWN_MASK
+ | (InputEvent.ALT_GRAPH_DOWN_MASK << 1);
+ check(invalidMods, invalidMods, invalidMods);
+
+ invalidMods = InputEvent.BUTTON1_MASK
+ | (InputEvent.ALT_GRAPH_DOWN_MASK << 1);
+ check(invalidMods, invalidMods, invalidMods);
+
+ invalidMods = InputEvent.BUTTON1_DOWN_MASK
+ | InputEvent.SHIFT_MASK
+ | (InputEvent.ALT_GRAPH_DOWN_MASK << 1);
+ check(invalidMods, invalidMods, invalidMods);
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ if (failed) {
+ throw new RuntimeException("wrong behavior of " +
+ "DragSourceDragEvent.getModifiers[Ex]()," +
+ " see error messages above");
+ }
+
+ System.err.println("test passed!");
+ }
+
+ void check(int mods, int expectedMods, int expectedExMods) {
+ System.err.println("testing DragSourceDragEvent " +
+ "created with 1st constructor");
+ System.err.println("modifiers passed to the constructor: "
+ + Integer.toBinaryString(mods));
+ verify(create1(mods), expectedMods, expectedExMods);
+
+ System.err.println("testing DragSourceDragEvent " +
+ "created with 2nd constructor");
+ System.err.println("modifiers passed to the constructor: "
+ + Integer.toBinaryString(mods));
+ verify(create2(mods), expectedMods, expectedExMods);
+ }
+
+ void verify(DragSourceDragEvent dsde, int expectedMods, int expectedExMods) {
+ if (dsde.getGestureModifiers() != expectedMods) {
+ failed = true;
+ System.err.print("ERROR: ");
+ }
+ System.err.println("getGestureModifiers() returned: "
+ + Integer.toBinaryString(dsde.getGestureModifiers()) +
+ " ; expected: " + Integer.toBinaryString(expectedMods));
+
+ if (dsde.getGestureModifiersEx() != expectedExMods) {
+ failed = true;
+ System.err.print("ERROR: ");
+ }
+ System.err.println("getGestureModifiersEx() returned: "
+ + Integer.toBinaryString(dsde.getGestureModifiersEx()) +
+ " ; expected: " + Integer.toBinaryString(expectedExMods));
+
+ System.err.println();
+ }
+
+ DragSourceDragEvent create1(int mods) {
+ return new DragSourceDragEvent(dsc, actions[0], actions[0], mods);
+ }
+
+ DragSourceDragEvent create2(int mods) {
+ return new DragSourceDragEvent(dsc, actions[0], actions[0], mods, 0, 0);
+ }
+}
diff --git a/test/jdk/java/awt/dnd/DragSourceGCrashTest.java b/test/jdk/java/awt/dnd/DragSourceGCrashTest.java
new file mode 100644
index 00000000000..ddfbf40c4c0
--- /dev/null
+++ b/test/jdk/java/awt/dnd/DragSourceGCrashTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2003, 2023, 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 4888520
+ @summary tests that drag source application invoked via debug java does not
+ crash on exit after drop on other Java drop target application
+ @key headful
+*/
+
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.dnd.DnDConstants;
+import java.awt.dnd.DragGestureEvent;
+import java.awt.dnd.DragGestureListener;
+import java.awt.dnd.DragSource;
+import java.awt.dnd.DragSourceAdapter;
+import java.awt.dnd.DragSourceDropEvent;
+import java.awt.dnd.DragSourceListener;
+import java.awt.dnd.DropTarget;
+import java.awt.dnd.DropTargetAdapter;
+import java.awt.dnd.DropTargetDropEvent;
+import java.awt.dnd.DropTargetListener;
+import java.awt.event.InputEvent;
+import java.io.File;
+import java.io.InputStream;
+import java.io.Reader;
+
+
+public class DragSourceGCrashTest {
+
+ volatile Frame frame;
+ volatile Panel panel;
+
+ public static void main(String[] args) throws Exception {
+ DragSourceGCrashTest test = new DragSourceGCrashTest();
+ EventQueue.invokeAndWait(test::init);
+ try {
+ test.start();
+ } finally {
+ EventQueue.invokeAndWait(()-> test.frame.dispose());
+ }
+ }
+
+ public void init() {
+ frame = new Frame("target - DragSourceGCrashTest");
+ panel = new Panel();
+ frame.add(panel);
+ frame.setBounds(100, 100, 100, 100);
+
+ DropTargetListener dtl = new DropTargetAdapter() {
+ public void drop(DropTargetDropEvent dtde) {
+ dtde.acceptDrop(DnDConstants.ACTION_MOVE);
+ Transferable t = dtde.getTransferable();
+ try {
+ DataFlavor df = new DataFlavor(
+ "text/plain;class=java.io.Reader");
+ Reader r = df.getReaderForText(t);
+ // To verify the bug do not close the reader!
+ dtde.dropComplete(true);
+ } catch (Exception e) {
+ e.printStackTrace();
+ dtde.dropComplete(false);
+ }
+ }
+ };
+
+ new DropTarget(frame, dtl);
+
+ frame.setVisible(true);
+ }
+
+ public void start() throws Exception {
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(1000);
+
+ ProcessResults pres = null;
+
+ Point endPoint = panel.getLocationOnScreen();
+
+ endPoint.translate(panel.getWidth() / 2, panel.getHeight() / 2);
+
+ String jdkPath = System.getProperty("java.home");
+ String javaPath = jdkPath + File.separator + "bin" +
+ File.separator + "java";
+
+ String[] cmd = {
+ javaPath, "-cp",
+ System.getProperty("test.classes", "."),
+ "Child",
+ String.valueOf(endPoint.x),
+ String.valueOf(endPoint.y)
+ };
+ Process process = Runtime.getRuntime().exec(cmd);
+ pres = ProcessResults.doWaitFor(process);
+
+ if (pres.stderr != null && pres.stderr.length() > 0) {
+ System.err.println("========= Child VM System.err ========");
+ System.err.print(pres.stderr);
+ System.err.println("======================================");
+ }
+
+ if (pres.stdout != null && pres.stdout.length() > 0) {
+ System.err.println("========= Child VM System.out ========");
+ System.err.print(pres.stdout);
+ System.err.println("======================================");
+ }
+
+ if (pres.exitValue != 0) {
+ throw new RuntimeException("FAILURE: child java exited " +
+ "with code " + pres.exitValue);
+ }
+ }
+}
+
+class Child {
+ volatile Frame frame;
+ volatile Panel panel;
+
+ public static void main(String[] args) throws Exception {
+ int endX = Integer.parseInt(args[0]);
+ int endY = Integer.parseInt(args[1]);
+ Point endPoint = new Point(endX, endY);
+
+ Child child = new Child();
+ EventQueue.invokeAndWait(child::init);
+ try {
+ child.start(endPoint);
+ } finally {
+ EventQueue.invokeAndWait(() -> child.frame.dispose());
+ }
+ }
+
+ public void init() {
+ frame = new Frame("source - DragSourceGCrashTest");
+ panel = new Panel();
+ frame.add(panel);
+ frame.setBounds(200, 100, 100, 100);
+
+ final DragSourceListener dsl = new DragSourceAdapter() {
+ public void dragDropEnd(DragSourceDropEvent dsde) {
+ System.err.println("DragSourceListener.dragDropEnd(): " +
+ "exiting application");
+ System.exit(0);
+ }
+ };
+ DragGestureListener dgl = new DragGestureListener() {
+ public void dragGestureRecognized(DragGestureEvent dge) {
+ dge.startDrag(null,
+ new StringSelection("test"), dsl);
+ }
+ };
+
+ new DragSource().createDefaultDragGestureRecognizer(panel,
+ DnDConstants.ACTION_MOVE, dgl);
+
+ frame.setVisible(true);
+ }
+
+ public void start(Point endPoint) throws Exception {
+ Robot robot = new Robot();
+
+ robot.waitForIdle();
+ robot.delay(1000);
+
+ Point startPoint = panel.getLocationOnScreen();
+
+ startPoint.translate(
+ panel.getWidth() / 2,
+ panel.getHeight() / 2
+ );
+
+ robot.mouseMove(startPoint.x, startPoint.y);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ for (Point p = new Point(startPoint); !p.equals(endPoint);
+ p.translate(
+ Integer.compare(endPoint.x - p.x, 0),
+ Integer.compare(endPoint.y - p.y, 0)
+ )) {
+ robot.mouseMove(p.x, p.y);
+ robot.delay(50);
+ }
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+
+ long timeout = 30000;
+ Object LOCK = new Object();
+ synchronized (LOCK) {
+ LOCK.wait(timeout);
+ System.err.println(System.currentTimeMillis() + " end");
+ }
+ System.err.println("WARNING: drop has not ended within " + timeout +
+ " ms, exiting application!");
+ System.exit(0);
+ }
+}
+
+class ProcessResults {
+ final static long TIMEOUT = 60000;
+
+ public int exitValue;
+ public String stdout;
+ public String stderr;
+
+ public ProcessResults() {
+ exitValue = -1;
+ stdout = "";
+ stderr = "";
+ }
+
+ /**
+ * Method to perform a "wait" for a process and return its exit value.
+ * This is a workaround for Process.waitFor() never returning.
+ */
+ public static ProcessResults doWaitFor(Process p) {
+ ProcessResults pres = new ProcessResults();
+
+ InputStream in = null;
+ InputStream err = null;
+
+ long startTime = System.currentTimeMillis();
+
+ try {
+ in = p.getInputStream();
+ err = p.getErrorStream();
+
+ boolean finished = false;
+
+ while (!finished) {
+ try {
+ while (in.available() > 0) {
+ pres.stdout += (char)in.read();
+ }
+ while (err.available() > 0) {
+ pres.stderr += (char)err.read();
+ }
+ // Ask the process for its exitValue. If the process
+ // is not finished, an IllegalThreadStateException
+ // is thrown. If it is finished, we fall through and
+ // the variable finished is set to true.
+ pres.exitValue = p.exitValue();
+ finished = true;
+ }
+ catch (IllegalThreadStateException e) {
+ if (System.currentTimeMillis() > startTime + TIMEOUT) {
+ System.err.println("WARNING: child process has not " +
+ "exited within " + TIMEOUT + " ms, returning" +
+ " from ProcessResults.doWaitFor()");
+ pres.exitValue = 0;
+ return pres;
+ }
+ // Process is not finished yet;
+ // Sleep a little to save on CPU cycles
+ Thread.currentThread().sleep(500);
+ }
+ }
+ if (in != null) in.close();
+ if (err != null) err.close();
+ }
+ catch (Throwable e) {
+ System.err.println("doWaitFor(): unexpected exception");
+ e.printStackTrace();
+ }
+ return pres;
+ }
+}