Skip to content

Commit c581886

Browse files
Victor RudometovPaul Hohensee
Victor Rudometov
authored and
Paul Hohensee
committedMay 25, 2023
8307128: Open source some drag and drop tests 4
8307799: Newly added java/awt/dnd/MozillaDnDTest.java has invalid jtreg `@requires` clause Reviewed-by: phh Backport-of: 98294242a94c611e2a713c2d520e59dd873ae4a0
1 parent 14779b1 commit c581886

5 files changed

+1680
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import javax.swing.JFrame;
25+
import javax.swing.JPanel;
26+
import javax.swing.JTree;
27+
import java.awt.EventQueue;
28+
import java.awt.Point;
29+
import java.awt.Rectangle;
30+
import java.awt.Robot;
31+
import java.awt.dnd.DnDConstants;
32+
import java.awt.dnd.DragGestureEvent;
33+
import java.awt.dnd.DragGestureListener;
34+
import java.awt.dnd.DragSource;
35+
import java.awt.event.InputEvent;
36+
37+
/*
38+
@test
39+
@bug 4273712 4396746
40+
@summary tests that mouse exit event doesn't trigger drag
41+
@key headful
42+
@run main MouseExitGestureTriggerTest
43+
*/
44+
45+
public class MouseExitGestureTriggerTest {
46+
47+
boolean recognized = false;
48+
volatile JFrame frame;
49+
volatile JPanel panel;
50+
volatile JTree tree;
51+
volatile DragSource dragSource;
52+
volatile Point srcPoint;
53+
volatile Rectangle r;
54+
volatile DragGestureListener dgl;
55+
static final int FRAME_ACTIVATION_TIMEOUT = 2000;
56+
static final int RECOGNITION_TIMEOUT = 1000;
57+
58+
public static void main(String[] args) throws Exception {
59+
MouseExitGestureTriggerTest test = new MouseExitGestureTriggerTest();
60+
EventQueue.invokeAndWait(test::init);
61+
try {
62+
test.start();
63+
} finally {
64+
EventQueue.invokeAndWait(() -> {
65+
if (test.frame != null) {
66+
test.frame.dispose();
67+
}
68+
});
69+
}
70+
}
71+
72+
public void init() {
73+
frame = new JFrame("MouseExitGestureTriggerTest");
74+
panel = new JPanel();
75+
tree = new JTree();
76+
77+
dragSource = DragSource.getDefaultDragSource();
78+
dgl = new DragGestureListener() {
79+
public void dragGestureRecognized(DragGestureEvent dge) {
80+
Thread.dumpStack();
81+
recognized = true;
82+
}
83+
};
84+
85+
tree.setEditable(true);
86+
dragSource.createDefaultDragGestureRecognizer(tree,
87+
DnDConstants.ACTION_MOVE,
88+
dgl);
89+
panel.add(tree);
90+
frame.getContentPane().add(panel);
91+
frame.setLocation(200, 200);
92+
93+
frame.pack();
94+
frame.setVisible(true);
95+
}
96+
97+
public void start() throws Exception {
98+
final Robot robot = new Robot();
99+
Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
100+
101+
clickRootNode(robot);
102+
clickRootNode(robot);
103+
clickRootNode(robot);
104+
105+
Thread.sleep(RECOGNITION_TIMEOUT);
106+
107+
EventQueue.invokeAndWait(() -> {
108+
if (recognized) {
109+
throw new RuntimeException("Mouse exit event triggered drag");
110+
}
111+
});
112+
}
113+
114+
void clickRootNode(final Robot robot) throws Exception {
115+
EventQueue.invokeAndWait(() -> {
116+
srcPoint = tree.getLocationOnScreen();
117+
r = tree.getRowBounds(0);
118+
});
119+
srcPoint.translate(r.x + 2 * r.width /3 , r.y + r.height / 2);
120+
robot.mouseMove(srcPoint.x ,srcPoint.y);
121+
122+
robot.mousePress(InputEvent.BUTTON1_MASK);
123+
Thread.sleep(10);
124+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
125+
Thread.sleep(10);
126+
}
127+
}
+494
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,494 @@
1+
/*
2+
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.AWTEvent;
25+
import java.awt.Component;
26+
import java.awt.Dimension;
27+
import java.awt.EventQueue;
28+
import java.awt.Frame;
29+
import java.awt.Graphics;
30+
import java.awt.Panel;
31+
import java.awt.Point;
32+
import java.awt.Robot;
33+
import java.awt.Toolkit;
34+
import java.awt.datatransfer.DataFlavor;
35+
import java.awt.datatransfer.SystemFlavorMap;
36+
import java.awt.datatransfer.Transferable;
37+
import java.awt.datatransfer.UnsupportedFlavorException;
38+
import java.awt.dnd.DnDConstants;
39+
import java.awt.dnd.DragGestureEvent;
40+
import java.awt.dnd.DragGestureListener;
41+
import java.awt.dnd.DragGestureRecognizer;
42+
import java.awt.dnd.DragSource;
43+
import java.awt.dnd.DragSourceAdapter;
44+
import java.awt.dnd.DragSourceDropEvent;
45+
import java.awt.dnd.DragSourceListener;
46+
import java.awt.dnd.DropTarget;
47+
import java.awt.dnd.DropTargetContext;
48+
import java.awt.dnd.DropTargetDragEvent;
49+
import java.awt.dnd.DropTargetDropEvent;
50+
import java.awt.dnd.DropTargetEvent;
51+
import java.awt.dnd.DropTargetListener;
52+
import java.awt.event.AWTEventListener;
53+
import java.awt.event.InputEvent;
54+
import java.awt.event.KeyEvent;
55+
import java.awt.event.MouseEvent;
56+
import java.io.ByteArrayInputStream;
57+
import java.io.File;
58+
import java.io.IOException;
59+
import java.io.InputStream;
60+
import java.io.InputStreamReader;
61+
import java.io.Reader;
62+
63+
/*
64+
@test
65+
@bug 4746177
66+
@summary tests that data types exported by Netscape 6.2 are supported
67+
@requires (os.family != "windows")
68+
@key headful
69+
@run main MozillaDnDTest
70+
*/
71+
72+
public class MozillaDnDTest {
73+
74+
public static final int CODE_NOT_RETURNED = -1;
75+
public static final int CODE_OK = 0;
76+
public static final int CODE_FAILURE = 1;
77+
public static final String DATA = "www.sun.com";
78+
79+
private int returnCode = CODE_NOT_RETURNED;
80+
81+
volatile Frame frame;
82+
volatile Robot robot;
83+
volatile Panel panel;
84+
volatile Point p;
85+
volatile Dimension d;
86+
87+
public static void main(String[] args) throws Exception {
88+
MozillaDnDTest test = new MozillaDnDTest();
89+
if (args.length > 0) {
90+
test.run(args);
91+
} else {
92+
EventQueue.invokeAndWait(test::init);
93+
try {
94+
test.start();
95+
} finally {
96+
EventQueue.invokeAndWait(() -> {
97+
if (test.frame != null) {
98+
test.frame.dispose();
99+
}
100+
});
101+
}
102+
}
103+
}
104+
105+
public void run(String[] args) {
106+
try {
107+
if (args.length != 4) {
108+
throw new RuntimeException("Incorrect command line arguments.");
109+
}
110+
111+
int x = Integer.parseInt(args[0]);
112+
int y = Integer.parseInt(args[1]);
113+
int w = Integer.parseInt(args[2]);
114+
int h = Integer.parseInt(args[3]);
115+
116+
panel = new DragSourcePanel();
117+
frame = new Frame();
118+
119+
frame.setTitle("DragSource frame");
120+
frame.setLocation(300, 200);
121+
frame.add(panel);
122+
frame.pack();
123+
frame.setVisible(true);
124+
125+
Util.waitForInit();
126+
127+
Point sourcePoint = panel.getLocationOnScreen();
128+
Dimension d = panel.getSize();
129+
sourcePoint.translate(d.width / 2, d.height / 2);
130+
131+
Point targetPoint = new Point(x + w / 2, y + h / 2);
132+
133+
robot = new Robot();
134+
135+
if (!Util.pointInComponent(robot, sourcePoint, panel)) {
136+
System.err.println("WARNING: Couldn't locate " + panel +
137+
" at point " + sourcePoint);
138+
System.exit(MozillaDnDTest.CODE_OK);
139+
}
140+
141+
robot.mouseMove(sourcePoint.x, sourcePoint.y);
142+
robot.keyPress(KeyEvent.VK_CONTROL);
143+
robot.mousePress(InputEvent.BUTTON1_MASK);
144+
for (; !sourcePoint.equals(targetPoint);
145+
sourcePoint.translate(sign(targetPoint.x - sourcePoint.x),
146+
sign(targetPoint.y - sourcePoint.y))) {
147+
robot.mouseMove(sourcePoint.x, sourcePoint.y);
148+
Thread.sleep(50);
149+
}
150+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
151+
robot.keyRelease(KeyEvent.VK_CONTROL);
152+
153+
} catch (Throwable e) {
154+
e.printStackTrace();
155+
System.exit(MozillaDnDTest.CODE_FAILURE);
156+
}
157+
}
158+
159+
public static int sign(int n) {
160+
return n < 0 ? -1 : n == 0 ? 0 : 1;
161+
}
162+
163+
public void init() {
164+
frame = new Frame();
165+
panel = new DropTargetPanel();
166+
167+
frame.setTitle("DropTarget frame");
168+
frame.setLocation(10, 200);
169+
frame.add(panel);
170+
171+
frame.pack();
172+
frame.setVisible(true);
173+
}
174+
175+
public void start() {
176+
// Solaris/Linux-only test
177+
if (System.getProperty("os.name").startsWith("Windows")) {
178+
return;
179+
}
180+
try {
181+
Util.waitForInit();
182+
EventQueue.invokeAndWait(() -> {
183+
p = panel.getLocationOnScreen();
184+
d = panel.getSize();
185+
});
186+
187+
Robot robot = new Robot();
188+
Point pp = new Point(p);
189+
pp.translate(d.width / 2, d.height / 2);
190+
if (!Util.pointInComponent(robot, pp, panel)) {
191+
System.err.println("WARNING: Couldn't locate " + panel +
192+
" at point " + pp);
193+
return;
194+
}
195+
196+
String javaPath = System.getProperty("java.home", "");
197+
String command = javaPath + File.separator + "bin" +
198+
File.separator + "java -cp " + System.getProperty("test.classes", ".") +
199+
" MozillaDnDTest " +
200+
p.x + " " + p.y + " " + d.width + " " + d.height;
201+
202+
Process process = Runtime.getRuntime().exec(command);
203+
ProcessResults pres = ProcessResults.doWaitFor(process);
204+
returnCode = pres.exitValue;
205+
206+
if (pres.stderr != null && pres.stderr.length() > 0) {
207+
System.err.println("========= Child VM System.err ========");
208+
System.err.print(pres.stderr);
209+
System.err.println("======================================");
210+
}
211+
212+
if (pres.stdout != null && pres.stdout.length() > 0) {
213+
System.err.println("========= Child VM System.out ========");
214+
System.err.print(pres.stdout);
215+
System.err.println("======================================");
216+
}
217+
218+
} catch (Throwable e) {
219+
e.printStackTrace();
220+
}
221+
switch (returnCode) {
222+
case CODE_NOT_RETURNED:
223+
System.err.println("Child VM: failed to start");
224+
break;
225+
case CODE_OK:
226+
System.err.println("Child VM: normal termination");
227+
break;
228+
case CODE_FAILURE:
229+
System.err.println("Child VM: abnormal termination");
230+
break;
231+
}
232+
if (returnCode != CODE_OK) {
233+
throw new RuntimeException("The test failed.");
234+
}
235+
}
236+
}
237+
238+
class Util implements AWTEventListener {
239+
private static final Toolkit tk = Toolkit.getDefaultToolkit();
240+
public static final Object SYNC_LOCK = new Object();
241+
private Component clickedComponent = null;
242+
private static final int PAINT_TIMEOUT = 10000;
243+
private static final int MOUSE_RELEASE_TIMEOUT = 10000;
244+
private static final Util util = new Util();
245+
246+
static {
247+
tk.addAWTEventListener(util, 0xFFFFFFFF);
248+
}
249+
250+
private void reset() {
251+
clickedComponent = null;
252+
}
253+
254+
public void eventDispatched(AWTEvent e) {
255+
if (e.getID() == MouseEvent.MOUSE_RELEASED) {
256+
clickedComponent = (Component)e.getSource();
257+
synchronized (SYNC_LOCK) {
258+
SYNC_LOCK.notifyAll();
259+
}
260+
}
261+
}
262+
263+
public static boolean pointInComponent(Robot robot, Point p, Component comp)
264+
throws InterruptedException {
265+
return util.isPointInComponent(robot, p, comp);
266+
}
267+
268+
private boolean isPointInComponent(Robot robot, Point p, Component comp)
269+
throws InterruptedException {
270+
tk.sync();
271+
robot.waitForIdle();
272+
reset();
273+
robot.mouseMove(p.x, p.y);
274+
robot.mousePress(InputEvent.BUTTON1_MASK);
275+
synchronized (SYNC_LOCK) {
276+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
277+
SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
278+
}
279+
280+
Component c = clickedComponent;
281+
282+
while (c != null && c != comp) {
283+
c = c.getParent();
284+
}
285+
286+
return c == comp;
287+
}
288+
289+
public static void waitForInit() throws InterruptedException {
290+
final Frame f = new Frame() {
291+
public void paint(Graphics g) {
292+
dispose();
293+
synchronized (SYNC_LOCK) {
294+
SYNC_LOCK.notifyAll();
295+
}
296+
}
297+
};
298+
f.setBounds(600, 400, 200, 200);
299+
synchronized (SYNC_LOCK) {
300+
f.setVisible(true);
301+
SYNC_LOCK.wait(PAINT_TIMEOUT);
302+
}
303+
tk.sync();
304+
}
305+
}
306+
307+
class ProcessResults {
308+
public int exitValue;
309+
public String stdout;
310+
public String stderr;
311+
312+
public ProcessResults() {
313+
exitValue = -1;
314+
stdout = "";
315+
stderr = "";
316+
}
317+
318+
/**
319+
* Method to perform a "wait" for a process and return its exit value.
320+
* This is a workaround for <code>Process.waitFor()</code> never returning.
321+
*/
322+
public static ProcessResults doWaitFor(Process p) {
323+
ProcessResults pres = new ProcessResults();
324+
325+
InputStream in = null;
326+
InputStream err = null;
327+
328+
try {
329+
in = p.getInputStream();
330+
err = p.getErrorStream();
331+
332+
boolean finished = false;
333+
334+
while (!finished) {
335+
try {
336+
while (in.available() > 0) {
337+
pres.stdout += (char)in.read();
338+
}
339+
while (err.available() > 0) {
340+
pres.stderr += (char)err.read();
341+
}
342+
// Ask the process for its exitValue. If the process
343+
// is not finished, an IllegalThreadStateException
344+
// is thrown. If it is finished, we fall through and
345+
// the variable finished is set to true.
346+
pres.exitValue = p.exitValue();
347+
finished = true;
348+
}
349+
catch (IllegalThreadStateException e) {
350+
// Process is not finished yet;
351+
// Sleep a little to save on CPU cycles
352+
Thread.currentThread().sleep(500);
353+
}
354+
}
355+
if (in != null) in.close();
356+
if (err != null) err.close();
357+
}
358+
catch (Throwable e) {
359+
System.err.println("doWaitFor(): unexpected exception");
360+
e.printStackTrace();
361+
}
362+
return pres;
363+
}
364+
}
365+
366+
class DragSourcePanel extends Panel {
367+
static final Dimension preferredDimension = new Dimension(200, 200);
368+
static final DataFlavor df = new DataFlavor("application/mozilla-test-flavor",
369+
null);
370+
final DragSource ds = DragSource.getDefaultDragSource();
371+
final Transferable t = new Transferable() {
372+
final DataFlavor[] flavors = new DataFlavor[] { df };
373+
public DataFlavor[] getTransferDataFlavors() {
374+
return flavors;
375+
}
376+
public boolean isDataFlavorSupported(DataFlavor flav) {
377+
return df.equals(flav);
378+
}
379+
public Object getTransferData(DataFlavor flav)
380+
throws IOException, UnsupportedFlavorException {
381+
if (!isDataFlavorSupported(flav)) {
382+
throw new UnsupportedFlavorException(flav);
383+
}
384+
byte[] bytes = MozillaDnDTest.DATA.getBytes("ASCII");
385+
return new ByteArrayInputStream(bytes);
386+
}
387+
};
388+
final DragSourceListener dsl = new DragSourceAdapter() {
389+
public void dragDropEnd(DragSourceDropEvent dsde) {
390+
System.exit(MozillaDnDTest.CODE_OK);
391+
}
392+
};
393+
final DragGestureListener dgl = new DragGestureListener() {
394+
public void dragGestureRecognized(DragGestureEvent dge) {
395+
dge.startDrag(null, t, dsl);
396+
}
397+
};
398+
final DragGestureRecognizer dgr =
399+
ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY,
400+
dgl);
401+
static {
402+
SystemFlavorMap sfm =
403+
(SystemFlavorMap)SystemFlavorMap.getDefaultFlavorMap();
404+
String[] natives = new String[] {
405+
"_NETSCAPE_URL",
406+
"text/plain",
407+
"text/unicode",
408+
"text/x-moz-url",
409+
"text/html"
410+
};
411+
sfm.setNativesForFlavor(df, natives);
412+
}
413+
414+
public Dimension getPreferredSize() {
415+
return preferredDimension;
416+
}
417+
}
418+
419+
class DropTargetPanel extends Panel implements DropTargetListener {
420+
421+
final Dimension preferredDimension = new Dimension(200, 200);
422+
final DropTarget dt = new DropTarget(this, this);
423+
424+
public Dimension getPreferredSize() {
425+
return preferredDimension;
426+
}
427+
428+
public void dragEnter(DropTargetDragEvent dtde) {
429+
dtde.acceptDrag(DnDConstants.ACTION_COPY);
430+
}
431+
432+
public void dragExit(DropTargetEvent dte) {}
433+
434+
public void dragOver(DropTargetDragEvent dtde) {
435+
dtde.acceptDrag(DnDConstants.ACTION_COPY);
436+
}
437+
438+
public String getTransferString(Transferable t) {
439+
String string = null;
440+
DataFlavor[] dfs = t.getTransferDataFlavors();
441+
for (int i = 0; i < dfs.length; i++) {
442+
if ("text".equals(dfs[i].getPrimaryType()) ||
443+
DataFlavor.stringFlavor.equals(dfs[i])) {
444+
try {
445+
Object o = t.getTransferData(dfs[i]);
446+
if (o instanceof InputStream ||
447+
o instanceof Reader) {
448+
Reader reader = null;
449+
if (o instanceof InputStream) {
450+
InputStream is = (InputStream)o;
451+
reader = new InputStreamReader(is);
452+
} else {
453+
reader = (Reader)o;
454+
}
455+
StringBuffer buf = new StringBuffer();
456+
for (int c = reader.read(); c != -1; c = reader.read()) {
457+
buf.append((char)c);
458+
}
459+
reader.close();
460+
string = buf.toString();
461+
break;
462+
} else if (o instanceof String) {
463+
string = (String)o;
464+
break;
465+
}
466+
} catch (Exception e) {
467+
// ignore.
468+
}
469+
}
470+
}
471+
return string;
472+
}
473+
474+
public void drop(DropTargetDropEvent dtde) {
475+
DropTargetContext dtc = dtde.getDropTargetContext();
476+
477+
if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) {
478+
dtde.acceptDrop(DnDConstants.ACTION_COPY);
479+
} else {
480+
dtde.rejectDrop();
481+
return;
482+
}
483+
484+
Transferable t = dtde.getTransferable();
485+
String str = getTransferString(t);
486+
dtde.dropComplete(true);
487+
488+
if (!MozillaDnDTest.DATA.equals(str)) {
489+
throw new RuntimeException("Drop data:" + str);
490+
}
491+
}
492+
493+
public void dropActionChanged(DropTargetDragEvent dtde) {}
494+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,415 @@
1+
/*
2+
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.Button;
25+
import java.awt.Color;
26+
import java.awt.Dimension;
27+
import java.awt.EventQueue;
28+
import java.awt.Frame;
29+
import java.awt.GridLayout;
30+
import java.awt.List;
31+
import java.awt.Panel;
32+
import java.awt.Point;
33+
import java.awt.Robot;
34+
import java.awt.datatransfer.DataFlavor;
35+
import java.awt.datatransfer.Transferable;
36+
import java.awt.datatransfer.UnsupportedFlavorException;
37+
import java.awt.dnd.DnDConstants;
38+
import java.awt.dnd.DragGestureEvent;
39+
import java.awt.dnd.DragGestureListener;
40+
import java.awt.dnd.DragSource;
41+
import java.awt.dnd.DragSourceDragEvent;
42+
import java.awt.dnd.DragSourceDropEvent;
43+
import java.awt.dnd.DragSourceEvent;
44+
import java.awt.dnd.DragSourceListener;
45+
import java.awt.dnd.DropTarget;
46+
import java.awt.dnd.DropTargetContext;
47+
import java.awt.dnd.DropTargetDragEvent;
48+
import java.awt.dnd.DropTargetDropEvent;
49+
import java.awt.dnd.DropTargetEvent;
50+
import java.awt.dnd.DropTargetListener;
51+
import java.awt.event.InputEvent;
52+
import java.awt.event.KeyEvent;
53+
import java.io.File;
54+
import java.io.InputStream;
55+
import java.io.Serializable;
56+
57+
/*
58+
@test
59+
@bug 4399700
60+
@summary tests that drop transfer data can be requested in several data flavors.
61+
@key headful
62+
@run main MultiDataFlavorDropTest
63+
*/
64+
65+
public class MultiDataFlavorDropTest {
66+
67+
public static final int CODE_NOT_RETURNED = -1;
68+
public static final int CODE_OK = 0;
69+
public static final int CODE_FAILURE = 1;
70+
public static final int FRAME_ACTIVATION_TIMEOUT = 2000;
71+
public static final int DROP_TIMEOUT = 10000;
72+
public static final int DROP_COMPLETION_TIMEOUT = 1000;
73+
74+
private int returnCode = CODE_NOT_RETURNED;
75+
76+
volatile Frame frame;
77+
volatile Robot robot;
78+
volatile Panel panel;
79+
volatile Point p;
80+
volatile Dimension d;
81+
82+
public static void main(String[] args) throws Exception {
83+
MultiDataFlavorDropTest test = new MultiDataFlavorDropTest();
84+
if (args.length > 0) {
85+
test.run(args);
86+
} else {
87+
EventQueue.invokeAndWait(test::init);
88+
try {
89+
test.start();
90+
} finally {
91+
EventQueue.invokeAndWait(() -> {
92+
if (test.frame != null) {
93+
test.frame.dispose();
94+
}
95+
});
96+
}
97+
}
98+
}
99+
100+
public void run(String[] args) {
101+
try {
102+
if (args.length != 4) {
103+
throw new RuntimeException("Incorrect command line arguments.");
104+
}
105+
106+
int x = Integer.parseInt(args[0]);
107+
int y = Integer.parseInt(args[1]);
108+
int w = Integer.parseInt(args[2]);
109+
int h = Integer.parseInt(args[3]);
110+
111+
Transferable t = new TransferableNumber();
112+
panel = new DragSourcePanel(t);
113+
114+
frame = new Frame();
115+
frame.setTitle("DragSource frame");
116+
frame.setLocation(300, 200);
117+
frame.add(panel);
118+
frame.pack();
119+
frame.setVisible(true);
120+
121+
Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
122+
123+
Point sourcePoint = panel.getLocationOnScreen();
124+
Dimension d = panel.getSize();
125+
sourcePoint.translate(d.width / 2, d.height / 2);
126+
127+
Point targetPoint = new Point(x + w / 2, y + h / 2);
128+
129+
robot = new Robot();
130+
robot.mouseMove(sourcePoint.x, sourcePoint.y);
131+
robot.keyPress(KeyEvent.VK_CONTROL);
132+
robot.mousePress(InputEvent.BUTTON1_MASK);
133+
for (; !sourcePoint.equals(targetPoint);
134+
sourcePoint.translate(sign(targetPoint.x - sourcePoint.x),
135+
sign(targetPoint.y - sourcePoint.y))) {
136+
robot.mouseMove(sourcePoint.x, sourcePoint.y);
137+
Thread.sleep(10);
138+
}
139+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
140+
robot.keyRelease(KeyEvent.VK_CONTROL);
141+
142+
synchronized (t) {
143+
t.wait(DROP_TIMEOUT);
144+
}
145+
146+
Thread.sleep(DROP_COMPLETION_TIMEOUT);
147+
148+
} catch (Throwable e) {
149+
e.printStackTrace();
150+
System.exit(MultiDataFlavorDropTest.CODE_FAILURE);
151+
}
152+
System.exit(MultiDataFlavorDropTest.CODE_OK);
153+
}
154+
155+
public static int sign(int n) {
156+
return n < 0 ? -1 : n == 0 ? 0 : 1;
157+
}
158+
159+
public void init() {
160+
frame = new Frame();
161+
panel = new DropTargetPanel();
162+
163+
frame.setTitle("MultiDataFlavorDropTest");
164+
frame.setLocation(10, 200);
165+
frame.add(panel);
166+
167+
frame.pack();
168+
frame.setVisible(true);
169+
}
170+
171+
public void start() throws Exception {
172+
Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
173+
174+
EventQueue.invokeAndWait(() -> {
175+
p = panel.getLocationOnScreen();
176+
d = panel.getSize();
177+
});
178+
179+
String javaPath = System.getProperty("java.home", "");
180+
String command = javaPath + File.separator + "bin" +
181+
File.separator + "java -cp " + System.getProperty("test.classes", ".") +
182+
" MultiDataFlavorDropTest " +
183+
p.x + " " + p.y + " " + d.width + " " + d.height;
184+
185+
Process process = Runtime.getRuntime().exec(command);
186+
returnCode = process.waitFor();
187+
188+
InputStream errorStream = process.getErrorStream();
189+
int count = errorStream.available();
190+
if (count > 0) {
191+
byte[] b = new byte[count];
192+
errorStream.read(b);
193+
System.err.println("========= Child VM System.err ========");
194+
System.err.print(new String(b));
195+
System.err.println("======================================");
196+
}
197+
198+
switch (returnCode) {
199+
case CODE_NOT_RETURNED:
200+
System.err.println("Child VM: failed to start");
201+
break;
202+
case CODE_OK:
203+
System.err.println("Child VM: normal termination");
204+
break;
205+
case CODE_FAILURE:
206+
System.err.println("Child VM: abnormal termination");
207+
break;
208+
}
209+
if (returnCode != CODE_OK) {
210+
throw new RuntimeException("The test failed.");
211+
}
212+
}
213+
}
214+
215+
class DragSourceButton extends Button implements Serializable,
216+
DragGestureListener,
217+
DragSourceListener {
218+
219+
final Transferable transferable;
220+
221+
public DragSourceButton(Transferable t) {
222+
super("DragSourceButton");
223+
224+
this.transferable = t;
225+
DragSource ds = DragSource.getDefaultDragSource();
226+
ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY,
227+
this);
228+
}
229+
230+
public void dragGestureRecognized(DragGestureEvent dge) {
231+
dge.startDrag(null, transferable, this);
232+
}
233+
234+
public void dragEnter(DragSourceDragEvent dsde) {}
235+
236+
public void dragExit(DragSourceEvent dse) {}
237+
238+
public void dragOver(DragSourceDragEvent dsde) {}
239+
240+
public void dragDropEnd(DragSourceDropEvent dsde) {}
241+
242+
public void dropActionChanged(DragSourceDragEvent dsde) {}
243+
}
244+
245+
class IntegerDataFlavor extends DataFlavor {
246+
247+
private final int number;
248+
249+
public IntegerDataFlavor(int n) throws ClassNotFoundException {
250+
super("application/integer-" + n +
251+
"; class=java.lang.Integer");
252+
this.number = n;
253+
}
254+
255+
public int getNumber() {
256+
return number;
257+
}
258+
}
259+
260+
class TransferableNumber implements Transferable {
261+
262+
private int transferDataRequestCount = 0;
263+
public static final int NUM_DATA_FLAVORS = 5;
264+
static final DataFlavor[] supportedFlavors =
265+
new DataFlavor[NUM_DATA_FLAVORS];
266+
267+
static {
268+
try {
269+
for (int i = 0; i < NUM_DATA_FLAVORS; i++) {
270+
supportedFlavors[i] =
271+
new IntegerDataFlavor(i);
272+
}
273+
} catch (ClassNotFoundException e) {
274+
e.printStackTrace();
275+
}
276+
}
277+
278+
public DataFlavor[] getTransferDataFlavors() {
279+
return supportedFlavors;
280+
}
281+
282+
public boolean isDataFlavorSupported(DataFlavor flavor) {
283+
if (flavor instanceof IntegerDataFlavor) {
284+
IntegerDataFlavor integerFlavor = (IntegerDataFlavor)flavor;
285+
int flavorNumber = integerFlavor.getNumber();
286+
if (flavorNumber >= 0 && flavorNumber < NUM_DATA_FLAVORS) {
287+
return true;
288+
}
289+
}
290+
return false;
291+
}
292+
293+
public Object getTransferData(DataFlavor flavor)
294+
throws UnsupportedFlavorException {
295+
296+
if (!isDataFlavorSupported(flavor)) {
297+
throw new UnsupportedFlavorException(flavor);
298+
}
299+
300+
transferDataRequestCount++;
301+
302+
if (transferDataRequestCount >= NUM_DATA_FLAVORS) {
303+
synchronized (this) {
304+
this.notifyAll();
305+
}
306+
}
307+
308+
IntegerDataFlavor integerFlavor = (IntegerDataFlavor)flavor;
309+
return new Integer(integerFlavor.getNumber());
310+
}
311+
}
312+
313+
class DragSourcePanel extends Panel {
314+
315+
final Dimension preferredDimension = new Dimension(200, 200);
316+
317+
public DragSourcePanel(Transferable t) {
318+
setLayout(new GridLayout(1, 1));
319+
add(new DragSourceButton(t));
320+
}
321+
322+
public Dimension getPreferredSize() {
323+
return preferredDimension;
324+
}
325+
}
326+
327+
class DropTargetPanel extends Panel implements DropTargetListener {
328+
329+
final Dimension preferredDimension = new Dimension(200, 200);
330+
331+
public DropTargetPanel() {
332+
setBackground(Color.green);
333+
setDropTarget(new DropTarget(this, this));
334+
setLayout(new GridLayout(1, 1));
335+
}
336+
337+
public Dimension getPreferredSize() {
338+
return preferredDimension;
339+
}
340+
341+
public void dragEnter(DropTargetDragEvent dtde) {
342+
dtde.acceptDrag(DnDConstants.ACTION_COPY);
343+
}
344+
345+
public void dragExit(DropTargetEvent dte) {}
346+
347+
public void dragOver(DropTargetDragEvent dtde) {
348+
dtde.acceptDrag(DnDConstants.ACTION_COPY);
349+
}
350+
351+
public void drop(DropTargetDropEvent dtde) {
352+
DropTargetContext dtc = dtde.getDropTargetContext();
353+
354+
if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) {
355+
dtde.acceptDrop(DnDConstants.ACTION_COPY);
356+
} else {
357+
dtde.rejectDrop();
358+
return;
359+
}
360+
361+
removeAll();
362+
final List list = new List();
363+
add(list);
364+
365+
Transferable t = dtde.getTransferable();
366+
DataFlavor[] dfs = t.getTransferDataFlavors();
367+
368+
if (dfs.length != TransferableNumber.NUM_DATA_FLAVORS) {
369+
throw new RuntimeException("FAILED: Incorrect number of data flavors.");
370+
}
371+
372+
for (int i = 0; i < dfs.length; i++) {
373+
374+
DataFlavor flavor = dfs[i];
375+
Integer transferNumber = null;
376+
377+
if (flavor.getRepresentationClass().equals(Integer.class)) {
378+
try {
379+
transferNumber = (Integer)t.getTransferData(flavor);
380+
} catch (Exception e) {
381+
e.printStackTrace();
382+
throw new RuntimeException("FAILED: Cannot get data: " +
383+
flavor.getMimeType());
384+
}
385+
}
386+
387+
boolean supportedFlavor = false;
388+
for (int j = 0; j < TransferableNumber.NUM_DATA_FLAVORS; j++) {
389+
int number = (i + j) % TransferableNumber.NUM_DATA_FLAVORS;
390+
try {
391+
if (flavor.equals(new IntegerDataFlavor(number))) {
392+
if (!(new Integer(number).equals(transferNumber))) {
393+
throw new RuntimeException("FAILED: Invalid data \n" +
394+
"\tflavor : " + flavor +
395+
"\tdata : " + transferNumber);
396+
}
397+
supportedFlavor = true;
398+
break;
399+
}
400+
} catch (ClassNotFoundException cannotHappen) {
401+
}
402+
}
403+
if (!supportedFlavor) {
404+
throw new RuntimeException("FAILED: Invalid flavor: " + flavor);
405+
}
406+
407+
list.add(transferNumber + ":" + flavor.getMimeType());
408+
}
409+
410+
dtc.dropComplete(true);
411+
validate();
412+
}
413+
414+
public void dropActionChanged(DropTargetDragEvent dtde) {}
415+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.Dimension;
25+
import java.awt.EventQueue;
26+
import java.awt.Frame;
27+
import java.awt.Label;
28+
import java.awt.Point;
29+
import java.awt.Robot;
30+
import java.awt.datatransfer.DataFlavor;
31+
import java.awt.datatransfer.Transferable;
32+
import java.awt.dnd.DnDConstants;
33+
import java.awt.dnd.DropTarget;
34+
import java.awt.dnd.DropTargetContext;
35+
import java.awt.dnd.DropTargetDragEvent;
36+
import java.awt.dnd.DropTargetDropEvent;
37+
import java.awt.dnd.DropTargetEvent;
38+
import java.awt.dnd.DropTargetListener;
39+
import java.awt.event.InputEvent;
40+
41+
/*
42+
@test
43+
@bug 4399700
44+
@summary tests that Motif drag support for label widget doesn't cause
45+
crash when used for drag and drop from label to Java drop target
46+
@key headful
47+
@run main NativeDragJavaDropTest
48+
*/
49+
50+
public class NativeDragJavaDropTest {
51+
52+
volatile Frame frame;
53+
volatile DropTargetLabel label;
54+
volatile Point p;
55+
volatile Dimension d;
56+
public static final int FRAME_ACTIVATION_TIMEOUT = 1000;
57+
public static final int DRAG_START_TIMEOUT = 500;
58+
public static final int DROP_COMPLETION_TIMEOUT = 2000;
59+
60+
public static void main(String[] args) throws Exception {
61+
NativeDragJavaDropTest test = new NativeDragJavaDropTest();
62+
EventQueue.invokeAndWait(test::init);
63+
try {
64+
test.start();
65+
} finally {
66+
EventQueue.invokeAndWait(() -> {
67+
if (test.frame != null) {
68+
test.frame.dispose();
69+
}
70+
});
71+
}
72+
}
73+
74+
public void init() {
75+
frame = new Frame();
76+
label = new DropTargetLabel();
77+
frame.setTitle("NativeDragJavaDropTest");
78+
frame.setLocation(200, 200);
79+
frame.add(label);
80+
81+
frame.pack();
82+
frame.setVisible(true);
83+
}
84+
85+
public void start() throws Exception {
86+
Robot robot = new Robot();
87+
robot.waitForIdle();
88+
Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
89+
90+
EventQueue.invokeAndWait(() -> {
91+
p = label.getLocationOnScreen();
92+
d = label.getSize();
93+
});
94+
95+
p.translate(d.width / 2, d.height / 2);
96+
97+
robot.mouseMove(p.x, p.y);
98+
robot.mousePress(InputEvent.BUTTON2_MASK);
99+
100+
Thread.sleep(DRAG_START_TIMEOUT);
101+
102+
robot.mouseRelease(InputEvent.BUTTON2_MASK);
103+
104+
Thread.sleep(DROP_COMPLETION_TIMEOUT);
105+
}
106+
}
107+
108+
class DropTargetLabel extends Label implements DropTargetListener {
109+
110+
final Dimension preferredDimension = new Dimension(200, 100);
111+
112+
public DropTargetLabel() {
113+
super("Label");
114+
setDropTarget(new DropTarget(this, this));
115+
}
116+
117+
public Dimension getPreferredSize() {
118+
return preferredDimension;
119+
}
120+
121+
public void dragEnter(DropTargetDragEvent dtde) {}
122+
123+
public void dragExit(DropTargetEvent dte) {}
124+
125+
public void dragOver(DropTargetDragEvent dtde) {}
126+
127+
public void dropActionChanged(DropTargetDragEvent dtde) {}
128+
129+
public void drop(DropTargetDropEvent dtde) {
130+
DropTargetContext dtc = dtde.getDropTargetContext();
131+
132+
if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) {
133+
dtde.acceptDrop(DnDConstants.ACTION_COPY);
134+
} else {
135+
dtde.rejectDrop();
136+
}
137+
138+
DataFlavor[] dfs = dtde.getCurrentDataFlavors();
139+
140+
if (dfs != null && dfs.length >= 1) {
141+
Transferable transfer = dtde.getTransferable();
142+
143+
try {
144+
Object obj = (Object)transfer.getTransferData(dfs[0]);
145+
} catch (Throwable e) {
146+
e.printStackTrace();
147+
dtc.dropComplete(false);
148+
}
149+
}
150+
dtc.dropComplete(true);
151+
}
152+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,492 @@
1+
/*
2+
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.AWTEvent;
25+
import java.awt.BorderLayout;
26+
import java.awt.Button;
27+
import java.awt.Color;
28+
import java.awt.Component;
29+
import java.awt.Dimension;
30+
import java.awt.EventQueue;
31+
import java.awt.Frame;
32+
import java.awt.Graphics;
33+
import java.awt.GridLayout;
34+
import java.awt.Panel;
35+
import java.awt.Point;
36+
import java.awt.Robot;
37+
import java.awt.Toolkit;
38+
import java.awt.datatransfer.DataFlavor;
39+
import java.awt.datatransfer.Transferable;
40+
import java.awt.datatransfer.UnsupportedFlavorException;
41+
import java.awt.dnd.DnDConstants;
42+
import java.awt.dnd.DragGestureEvent;
43+
import java.awt.dnd.DragGestureListener;
44+
import java.awt.dnd.DragSource;
45+
import java.awt.dnd.DragSourceDragEvent;
46+
import java.awt.dnd.DragSourceDropEvent;
47+
import java.awt.dnd.DragSourceEvent;
48+
import java.awt.dnd.DragSourceListener;
49+
import java.awt.dnd.DropTarget;
50+
import java.awt.dnd.DropTargetContext;
51+
import java.awt.dnd.DropTargetDragEvent;
52+
import java.awt.dnd.DropTargetDropEvent;
53+
import java.awt.dnd.DropTargetEvent;
54+
import java.awt.dnd.DropTargetListener;
55+
import java.awt.event.AWTEventListener;
56+
import java.awt.event.InputEvent;
57+
import java.awt.event.KeyEvent;
58+
import java.awt.event.MouseEvent;
59+
import java.io.ByteArrayInputStream;
60+
import java.io.ByteArrayOutputStream;
61+
import java.io.IOException;
62+
import java.io.ObjectInputStream;
63+
import java.io.ObjectOutputStream;
64+
import java.io.Serializable;
65+
66+
/*
67+
@test
68+
@bug 4389284
69+
@summary tests that drop targets registered on nested heavyweight
70+
components work properly
71+
@key headful
72+
@run main NestedHeavyweightDropTargetTest
73+
*/
74+
75+
public class NestedHeavyweightDropTargetTest {
76+
77+
volatile Frame frame;
78+
volatile DragSourceButton dragSourceButton;
79+
volatile DropTargetPanel dropTargetPanel;
80+
volatile InnerDropTargetPanel innerDropTargetPanel;
81+
volatile Button button;
82+
volatile Dimension d;
83+
volatile Point srcPoint;
84+
volatile Point dstPoint;
85+
86+
static final int DROP_COMPLETION_TIMEOUT = 1000;
87+
88+
public static void main(String[] args) throws Exception {
89+
NestedHeavyweightDropTargetTest test = new NestedHeavyweightDropTargetTest();
90+
EventQueue.invokeAndWait(test::init);
91+
try {
92+
test.start();
93+
} finally {
94+
EventQueue.invokeAndWait(() -> {
95+
if (test.frame != null) {
96+
test.frame.dispose();
97+
}
98+
});
99+
}
100+
}
101+
102+
public void init() {
103+
frame = new Frame();
104+
dragSourceButton = new DragSourceButton();
105+
dropTargetPanel = new DropTargetPanel();
106+
innerDropTargetPanel = new InnerDropTargetPanel();
107+
button = new Button("button");
108+
button.setBackground(Color.red);
109+
110+
innerDropTargetPanel.setLayout(new GridLayout(3, 1));
111+
innerDropTargetPanel.add(button);
112+
innerDropTargetPanel.setBackground(Color.yellow);
113+
114+
dropTargetPanel.setLayout(new GridLayout(2, 1));
115+
dropTargetPanel.add(innerDropTargetPanel);
116+
dropTargetPanel.setBackground(Color.green);
117+
118+
frame.setTitle("NestedHeavyweightDropTargetTest");
119+
frame.setLocation(200, 200);
120+
frame.setLayout(new BorderLayout());
121+
frame.add(dropTargetPanel, BorderLayout.CENTER);
122+
frame.add(dragSourceButton, BorderLayout.SOUTH);
123+
124+
frame.pack();
125+
126+
innerDropTargetPanel.setDropTarget(new DropTarget(innerDropTargetPanel, innerDropTargetPanel));
127+
dropTargetPanel.setDropTarget(new DropTarget(dropTargetPanel, dropTargetPanel));
128+
129+
frame.setVisible(true);
130+
}
131+
132+
public void start() throws Exception {
133+
Robot robot = new Robot();
134+
Util.waitForInit();
135+
136+
test1(robot);
137+
test2(robot);
138+
}
139+
140+
public static int sign(int n) {
141+
return n < 0 ? -1 : n == 0 ? 0 : 1;
142+
}
143+
144+
public void test1(Robot robot) throws Exception {
145+
innerDropTargetPanel.setDragEnterTriggered(false);
146+
innerDropTargetPanel.setDragOverTriggered(false);
147+
innerDropTargetPanel.setDragExitTriggered(false);
148+
innerDropTargetPanel.setDropTriggered(false);
149+
150+
EventQueue.invokeAndWait(() -> {
151+
srcPoint = dragSourceButton.getLocationOnScreen();
152+
d = dragSourceButton.getSize();
153+
});
154+
155+
srcPoint.translate(d.width / 2, d.height / 2);
156+
157+
if (!Util.pointInComponent(robot, srcPoint, dragSourceButton)) {
158+
System.err.println("WARNING: Couldn't locate " + dragSourceButton +
159+
" at point " + srcPoint);
160+
return;
161+
}
162+
163+
EventQueue.invokeAndWait(() -> {
164+
dstPoint = innerDropTargetPanel.getLocationOnScreen();
165+
d = innerDropTargetPanel.getSize();
166+
});
167+
168+
dstPoint.translate(d.width / 2, d.height / 2);
169+
170+
if (!Util.pointInComponent(robot, dstPoint, innerDropTargetPanel)) {
171+
System.err.println("WARNING: Couldn't locate " + innerDropTargetPanel +
172+
" at point " + dstPoint);
173+
return;
174+
}
175+
176+
robot.mouseMove(srcPoint.x, srcPoint.y);
177+
robot.keyPress(KeyEvent.VK_CONTROL);
178+
robot.mousePress(InputEvent.BUTTON1_MASK);
179+
for (;!srcPoint.equals(dstPoint);
180+
srcPoint.translate(sign(dstPoint.x - srcPoint.x),
181+
sign(dstPoint.y - srcPoint.y))) {
182+
robot.mouseMove(srcPoint.x, srcPoint.y);
183+
Thread.sleep(10);
184+
}
185+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
186+
robot.keyRelease(KeyEvent.VK_CONTROL);
187+
188+
Thread.sleep(DROP_COMPLETION_TIMEOUT);
189+
190+
if (!innerDropTargetPanel.isDragEnterTriggered()) {
191+
throw new RuntimeException("child dragEnter() not triggered");
192+
}
193+
194+
if (!innerDropTargetPanel.isDragOverTriggered()) {
195+
throw new RuntimeException("child dragOver() not triggered");
196+
}
197+
198+
if (!innerDropTargetPanel.isDropTriggered()) {
199+
throw new RuntimeException("child drop() not triggered");
200+
}
201+
}
202+
203+
public void test2(Robot robot) throws Exception {
204+
innerDropTargetPanel.setDragEnterTriggered(false);
205+
innerDropTargetPanel.setDragOverTriggered(false);
206+
innerDropTargetPanel.setDragExitTriggered(false);
207+
innerDropTargetPanel.setDropTriggered(false);
208+
209+
EventQueue.invokeAndWait(() -> {
210+
srcPoint = dragSourceButton.getLocationOnScreen();
211+
d = dragSourceButton.getSize();
212+
});
213+
srcPoint.translate(d.width / 2, d.height / 2);
214+
215+
if (!Util.pointInComponent(robot, srcPoint, dragSourceButton)) {
216+
System.err.println("WARNING: Couldn't locate " + dragSourceButton +
217+
" at point " + srcPoint);
218+
return;
219+
}
220+
221+
EventQueue.invokeAndWait(() -> {
222+
dstPoint = button.getLocationOnScreen();
223+
d = button.getSize();
224+
});
225+
226+
dstPoint.translate(d.width / 2, d.height / 2);
227+
228+
if (!Util.pointInComponent(robot, dstPoint, button)) {
229+
System.err.println("WARNING: Couldn't locate " + button +
230+
" at point " + dstPoint);
231+
return;
232+
}
233+
234+
robot.mouseMove(srcPoint.x, srcPoint.y);
235+
robot.keyPress(KeyEvent.VK_CONTROL);
236+
robot.mousePress(InputEvent.BUTTON1_MASK);
237+
for (;!srcPoint.equals(dstPoint);
238+
srcPoint.translate(sign(dstPoint.x - srcPoint.x),
239+
sign(dstPoint.y - srcPoint.y))) {
240+
robot.mouseMove(srcPoint.x, srcPoint.y);
241+
Thread.sleep(10);
242+
}
243+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
244+
robot.keyRelease(KeyEvent.VK_CONTROL);
245+
246+
Thread.sleep(DROP_COMPLETION_TIMEOUT);
247+
248+
if (!innerDropTargetPanel.isDragEnterTriggered()) {
249+
throw new RuntimeException("child dragEnter() not triggered");
250+
}
251+
252+
if (!innerDropTargetPanel.isDragOverTriggered()) {
253+
throw new RuntimeException("child dragOver() not triggered");
254+
}
255+
256+
if (!innerDropTargetPanel.isDropTriggered()) {
257+
throw new RuntimeException("child drop() not triggered");
258+
}
259+
}
260+
}
261+
262+
class Util implements AWTEventListener {
263+
private static final Toolkit tk = Toolkit.getDefaultToolkit();
264+
public static final Object SYNC_LOCK = new Object();
265+
private Component clickedComponent = null;
266+
private static final int PAINT_TIMEOUT = 10000;
267+
private static final int MOUSE_RELEASE_TIMEOUT = 10000;
268+
private static final Util util = new Util();
269+
270+
static {
271+
tk.addAWTEventListener(util, 0xFFFFFFFF);
272+
}
273+
274+
private void reset() {
275+
clickedComponent = null;
276+
}
277+
278+
public void eventDispatched(AWTEvent e) {
279+
if (e.getID() == MouseEvent.MOUSE_RELEASED) {
280+
clickedComponent = (Component)e.getSource();
281+
synchronized (SYNC_LOCK) {
282+
SYNC_LOCK.notifyAll();
283+
}
284+
}
285+
}
286+
287+
public static boolean pointInComponent(Robot robot, Point p, Component comp)
288+
throws InterruptedException {
289+
return util.isPointInComponent(robot, p, comp);
290+
}
291+
292+
private boolean isPointInComponent(Robot robot, Point p, Component comp)
293+
throws InterruptedException {
294+
tk.sync();
295+
robot.waitForIdle();
296+
reset();
297+
robot.mouseMove(p.x, p.y);
298+
robot.mousePress(InputEvent.BUTTON1_MASK);
299+
synchronized (SYNC_LOCK) {
300+
robot.mouseRelease(InputEvent.BUTTON1_MASK);
301+
SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
302+
}
303+
304+
Component c = clickedComponent;
305+
306+
while (c != null && c != comp) {
307+
c = c.getParent();
308+
}
309+
310+
return c == comp;
311+
}
312+
313+
public static void waitForInit() throws InterruptedException {
314+
final Frame f = new Frame() {
315+
public void paint(Graphics g) {
316+
dispose();
317+
synchronized (SYNC_LOCK) {
318+
SYNC_LOCK.notifyAll();
319+
}
320+
}
321+
};
322+
f.setBounds(600, 400, 200, 200);
323+
synchronized (SYNC_LOCK) {
324+
f.setVisible(true);
325+
SYNC_LOCK.wait(PAINT_TIMEOUT);
326+
}
327+
tk.sync();
328+
}
329+
}
330+
331+
class DragSourceButton extends Button implements Serializable,
332+
Transferable,
333+
DragGestureListener,
334+
DragSourceListener {
335+
private final DataFlavor dataflavor =
336+
new DataFlavor(Button.class, "DragSourceButton");
337+
338+
public DragSourceButton() {
339+
this("DragSourceButton");
340+
}
341+
342+
public DragSourceButton(String str) {
343+
super(str);
344+
345+
DragSource ds = DragSource.getDefaultDragSource();
346+
ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY,
347+
this);
348+
}
349+
350+
public void dragGestureRecognized(DragGestureEvent dge) {
351+
dge.startDrag(null, this, this);
352+
}
353+
354+
public void dragEnter(DragSourceDragEvent dsde) {}
355+
356+
public void dragExit(DragSourceEvent dse) {}
357+
358+
public void dragOver(DragSourceDragEvent dsde) {}
359+
360+
public void dragDropEnd(DragSourceDropEvent dsde) {}
361+
362+
public void dropActionChanged(DragSourceDragEvent dsde) {}
363+
364+
public Object getTransferData(DataFlavor flavor)
365+
throws UnsupportedFlavorException, IOException {
366+
367+
if (!isDataFlavorSupported(flavor)) {
368+
throw new UnsupportedFlavorException(flavor);
369+
}
370+
371+
Object retObj = null;
372+
373+
ByteArrayOutputStream baoStream = new ByteArrayOutputStream();
374+
ObjectOutputStream ooStream = new ObjectOutputStream(baoStream);
375+
ooStream.writeObject(this);
376+
377+
ByteArrayInputStream baiStream = new ByteArrayInputStream(baoStream.toByteArray());
378+
ObjectInputStream ois = new ObjectInputStream(baiStream);
379+
try {
380+
retObj = ois.readObject();
381+
} catch (ClassNotFoundException e) {
382+
e.printStackTrace();
383+
throw new RuntimeException(e.toString());
384+
}
385+
386+
return retObj;
387+
}
388+
389+
public DataFlavor[] getTransferDataFlavors() {
390+
return new DataFlavor[] { dataflavor };
391+
}
392+
393+
public boolean isDataFlavorSupported(DataFlavor dflavor) {
394+
return dataflavor.equals(dflavor);
395+
}
396+
}
397+
398+
class InnerDropTargetPanel extends DropTargetPanel {
399+
private boolean dragEnterTriggered = false;
400+
private boolean dragOverTriggered = false;
401+
private boolean dragExitTriggered = false;
402+
private boolean dropTriggered = false;
403+
404+
public void dragEnter(DropTargetDragEvent dtde) {
405+
setDragEnterTriggered(true);
406+
}
407+
408+
public void dragExit(DropTargetEvent dte) {
409+
setDragExitTriggered(true);
410+
}
411+
412+
public void dragOver(DropTargetDragEvent dtde) {
413+
setDragOverTriggered(true);
414+
}
415+
416+
public void dropActionChanged(DropTargetDragEvent dtde) {}
417+
418+
public void drop(DropTargetDropEvent dtde) {
419+
setDropTriggered(true);
420+
dtde.rejectDrop();
421+
}
422+
423+
public boolean isDragEnterTriggered() {
424+
return dragEnterTriggered;
425+
}
426+
427+
public boolean isDragOverTriggered() {
428+
return dragOverTriggered;
429+
}
430+
431+
public boolean isDragExitTriggered() {
432+
return dragExitTriggered;
433+
}
434+
435+
public boolean isDropTriggered() {
436+
return dropTriggered;
437+
}
438+
439+
public void setDragEnterTriggered(boolean b) {
440+
dragEnterTriggered = b;
441+
}
442+
443+
public void setDragOverTriggered(boolean b) {
444+
dragOverTriggered = b;
445+
}
446+
447+
public void setDragExitTriggered(boolean b) {
448+
dragExitTriggered = b;
449+
}
450+
451+
public void setDropTriggered(boolean b) {
452+
dropTriggered = b;
453+
}
454+
}
455+
456+
class DropTargetPanel extends Panel implements DropTargetListener {
457+
458+
public void dragEnter(DropTargetDragEvent dtde) {}
459+
460+
public void dragExit(DropTargetEvent dte) {}
461+
462+
public void dragOver(DropTargetDragEvent dtde) {}
463+
464+
public void dropActionChanged(DropTargetDragEvent dtde) {}
465+
466+
public void drop(DropTargetDropEvent dtde) {
467+
DropTargetContext dtc = dtde.getDropTargetContext();
468+
469+
if ((dtde.getSourceActions() & DnDConstants.ACTION_COPY) != 0) {
470+
dtde.acceptDrop(DnDConstants.ACTION_COPY);
471+
} else {
472+
dtde.rejectDrop();
473+
}
474+
475+
DataFlavor[] dfs = dtde.getCurrentDataFlavors();
476+
Component comp = null;
477+
478+
if (dfs != null && dfs.length >= 1) {
479+
Transferable transfer = dtde.getTransferable();
480+
481+
try {
482+
comp = (Component)transfer.getTransferData(dfs[0]);
483+
} catch (Throwable e) {
484+
e.printStackTrace();
485+
dtc.dropComplete(false);
486+
}
487+
}
488+
dtc.dropComplete(true);
489+
490+
add(comp);
491+
}
492+
}

0 commit comments

Comments
 (0)
Please sign in to comment.