-
Bug
-
Resolution: Cannot Reproduce
-
P4
-
7
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-2214112 | 7u6 | Denis Fokin | P4 | Closed | Won't Fix | |
JDK-2213386 | 6-pool | Unassigned | P4 | Closed | Won't Fix |
SYNOPSIS
--------
DnD DragSite receives unexpected drop action after keyboard drop action change
OPERATING SYSTEM
----------------
Windows (tested with Windows XP SP3)
Linux (tested with RHEL 5)
FULL JDK VERSIONS
-----------------
Java 7 (tested with GA / b147)
Java 6 (tested with 1.6.0_26)
PROBLEM DESCRIPTION from LICENSEE
---------------------------------
CR 4869264 fixed DnD negotiation, but drop action is changed by keyboard operation, and the application cannot receive the expected drop action data
REPRODUCTION INSTRUCTIONS
-------------------------
1. Compile and run DnDButtonTest as follows:
$ java DnDButtonTest abc xyz
2. Drag "abc" from Button1 and move mouse cursor to the "xyz" button.
(Don't drop it. If you drop it, press "Put" button to restore the
text.) You will see the following output:
=========================================================
DropSite: dragEnter: dropAction=MOVE, sourceActions=COPY_OR_MOVE
DragSite: dragEnter: userAction=MOVE, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Button1
=========================================================
Note that both dropAction values are the same. The response order is DropSite, DragSite.
3. Press Ctrl key to change drop action from MOVE to COPY and keep it
pressed, you will see the following output:
=========================================================
DragSite: dropActionChanged: userAction=COPY, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Ctrl+Button1
DropSite: dropActionChanged: dropAction=COPY, sourceActions=COPY_OR_MOVE
=========================================================
Note that the dropAction values are NOT the same. The response order is DragSite, DropSite i.e. it seems DragSite's DragSourceDragEvent event was created before DropSite's DropTargetDragEvent event. Also, the dropAction value should be the same because DragSite can detect DropSite's drop action via dropActionChanged().
The expected result is:
=========================================================
DropSite: dropActionChanged: dropAction=COPY, sourceActions=COPY_OR_MOVE
DragSite: dropActionChanged: userAction=COPY, dropAction=COPY, targetActions=COPY, gestureModifiers=Ctrl+Button1
=========================================================
4. Release Ctrl key to change drop action from COPY to MOVE. You will
see the following output:
=========================================================
DragSite: dropActionChanged: userAction=MOVE, dropAction=COPY, targetActions=COPY, gestureModifiers=Button1
DropSite: dropActionChanged: dropAction=MOVE, sourceActions=COPY_OR_MOVE
=========================================================
The expected result is:
=========================================================
DropSite: dropActionChanged: dropAction=MOVE, sourceActions=COPY_OR_MOVE
DragSite: dropActionChanged: userAction=MOVE, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Button1
=========================================================
5. Move the mouse cursor to the TextField on "xyz". Mouse pointer says
"drop action is rejected", you will see the following output:
=========================================================
DropSite: dragExit
DragSite: dragExit
=========================================================
6. Press Ctrl key and release Ctrl key, you will see the following
output:
=========================================================
DragSite: dropActionChanged: userAction=COPY, dropAction=NONE, targetActions=NONE, gestureModifiers=Ctrl+Button1
DragSite: dropActionChanged: userAction=MOVE, dropAction=NONE, targetActions=NONE, gestureModifiers=Button1
=========================================================
It received the expected dropAction since dragExit had been called, as expected.
TESTCASE
--------
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.beans.*;
public class DnDButtonTest extends Frame implements ActionListener, DragGestureListener, DragSourceListener, Transferable, DropTargetListener {
private static DataFlavor flavors[] = {DataFlavor.stringFlavor};
private Button btn = null;
private TextField textf = null;
private static Hashtable<Integer,String> dndAction = new Hashtable<Integer,String>(){{
put(new Integer(DnDConstants.ACTION_COPY), new String("COPY"));
put(new Integer(DnDConstants.ACTION_COPY_OR_MOVE), new String("COPY_OR_MOVE"));
put(new Integer(DnDConstants.ACTION_LINK), new String("LINK"));
put(new Integer(DnDConstants.ACTION_MOVE), new String("MOVE"));
put(new Integer(DnDConstants.ACTION_NONE), new String("NONE"));
}};
public DnDButtonTest(String s){
setTitle("DnDButtonTest");
setLayout(new BorderLayout());
btn = new Button(s);
btn.setPreferredSize(new Dimension(300, 100));
add(btn, BorderLayout.CENTER);
Panel p = new Panel();
p.setLayout(new FlowLayout());
textf = new TextField(s, 15);
p.add(textf);
Button copyBtn = new Button("Put");
copyBtn.addActionListener(this);
p.add(copyBtn);
add(p, BorderLayout.SOUTH);
DragSource ds = DragSource.getDefaultDragSource();
ds.createDefaultDragGestureRecognizer(btn, DnDConstants.ACTION_COPY_OR_MOVE, this);
DropTarget dt = new DropTarget(btn, this);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) { System.exit(0);}
});
pack();
setLocationByPlatform(true);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
btn.setLabel(textf.getText());
}
public void dragGestureRecognized(DragGestureEvent dge){
dge.startDrag(null, this, this);
}
public void dragEnter(DragSourceDragEvent dsde){
System.out.printf("DragSite: dragEnter: userAction=%s, dropAction=%s, targetActions=%s, gestureModifiers=%s%n",
dndAction.get(dsde.getUserAction()), dndAction.get(dsde.getDropAction()),
dndAction.get(dsde.getTargetActions()), KeyEvent.getKeyModifiersText(dsde.getGestureModifiers()));
}
public void dragOver(DragSourceDragEvent dsde){}
public void dropActionChanged(DragSourceDragEvent dsde){
System.out.printf("DragSite: dropActionChanged: userAction=%s, dropAction=%s, targetActions=%s, gestureModifiers=%s%n",
dndAction.get(dsde.getUserAction()), dndAction.get(dsde.getDropAction()),
dndAction.get(dsde.getTargetActions()), KeyEvent.getKeyModifiersText(dsde.getGestureModifiers()));
}
public void dragExit(DragSourceEvent dsde){
System.out.println("DragSite: dragExit");
}
public void dragDropEnd(DragSourceDropEvent dsde){
System.out.printf("DragSite: dragDropEnd: dropSuccess=%s, dropAction=%s%n",
dsde.getDropSuccess() ? "true" : "false", dndAction.get(dsde.getDropAction()));
}
public synchronized DataFlavor[] getTransferDataFlavors(){
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor){
return(flavor.equals(flavors[0]));
}
public synchronized Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.equals(flavors[0])) {
System.out.printf("DragSite: getTransferData=[%s]%n", btn.getLabel());
return(Object)btn.getLabel();
}
throw new UnsupportedFlavorException(flavor);
}
public void dragEnter(DropTargetDragEvent dtde) {
int action = dtde.getDropAction();
System.out.printf("DropSite: dragEnter: dropAction=%s, sourceActions=%s%n",
dndAction.get(action), dndAction.get(dtde.getSourceActions()));
if (action == DnDConstants.ACTION_COPY || action == DnDConstants.ACTION_MOVE) {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrag(action);
return;
}
} else {
dtde.rejectDrag();
return;
}
dtde.rejectDrag();
}
public void dragOver(DropTargetDragEvent dtde) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
System.out.printf("DropSite: dropActionChanged: dropAction=%s, sourceActions=%s%n",
dndAction.get(dtde.getDropAction()), dndAction.get(dtde.getSourceActions()));
}
public void dragExit(DropTargetEvent dte) {
System.out.println("DropSite: dragExit");
}
public void drop(DropTargetDropEvent dtde) {
int action = dtde.getDropAction();
if (action == DnDConstants.ACTION_COPY) {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
} else if (action == DnDConstants.ACTION_MOVE) {
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
} else {
dtde.dropComplete(false);
return;
}
try {
Transferable content = dtde.getTransferable();
if (content.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String s = (String)content.getTransferData(DataFlavor.stringFlavor);
btn.setLabel(s);
System.out.printf("DropSite: drop: getTransferData=[%s], dropAction=%s%n",
s, dndAction.get(action));
dtde.dropComplete(true);
} else {
dtde.dropComplete(false);
}
} catch (Exception e) {
e.printStackTrace();
dtde.dropComplete(false);
}
}
public static void main(String args[]){
for (String s : args) new DnDButtonTest(s);
}
}
--------
DnD DragSite receives unexpected drop action after keyboard drop action change
OPERATING SYSTEM
----------------
Windows (tested with Windows XP SP3)
Linux (tested with RHEL 5)
FULL JDK VERSIONS
-----------------
Java 7 (tested with GA / b147)
Java 6 (tested with 1.6.0_26)
PROBLEM DESCRIPTION from LICENSEE
---------------------------------
CR 4869264 fixed DnD negotiation, but drop action is changed by keyboard operation, and the application cannot receive the expected drop action data
REPRODUCTION INSTRUCTIONS
-------------------------
1. Compile and run DnDButtonTest as follows:
$ java DnDButtonTest abc xyz
2. Drag "abc" from Button1 and move mouse cursor to the "xyz" button.
(Don't drop it. If you drop it, press "Put" button to restore the
text.) You will see the following output:
=========================================================
DropSite: dragEnter: dropAction=MOVE, sourceActions=COPY_OR_MOVE
DragSite: dragEnter: userAction=MOVE, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Button1
=========================================================
Note that both dropAction values are the same. The response order is DropSite, DragSite.
3. Press Ctrl key to change drop action from MOVE to COPY and keep it
pressed, you will see the following output:
=========================================================
DragSite: dropActionChanged: userAction=COPY, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Ctrl+Button1
DropSite: dropActionChanged: dropAction=COPY, sourceActions=COPY_OR_MOVE
=========================================================
Note that the dropAction values are NOT the same. The response order is DragSite, DropSite i.e. it seems DragSite's DragSourceDragEvent event was created before DropSite's DropTargetDragEvent event. Also, the dropAction value should be the same because DragSite can detect DropSite's drop action via dropActionChanged().
The expected result is:
=========================================================
DropSite: dropActionChanged: dropAction=COPY, sourceActions=COPY_OR_MOVE
DragSite: dropActionChanged: userAction=COPY, dropAction=COPY, targetActions=COPY, gestureModifiers=Ctrl+Button1
=========================================================
4. Release Ctrl key to change drop action from COPY to MOVE. You will
see the following output:
=========================================================
DragSite: dropActionChanged: userAction=MOVE, dropAction=COPY, targetActions=COPY, gestureModifiers=Button1
DropSite: dropActionChanged: dropAction=MOVE, sourceActions=COPY_OR_MOVE
=========================================================
The expected result is:
=========================================================
DropSite: dropActionChanged: dropAction=MOVE, sourceActions=COPY_OR_MOVE
DragSite: dropActionChanged: userAction=MOVE, dropAction=MOVE, targetActions=MOVE, gestureModifiers=Button1
=========================================================
5. Move the mouse cursor to the TextField on "xyz". Mouse pointer says
"drop action is rejected", you will see the following output:
=========================================================
DropSite: dragExit
DragSite: dragExit
=========================================================
6. Press Ctrl key and release Ctrl key, you will see the following
output:
=========================================================
DragSite: dropActionChanged: userAction=COPY, dropAction=NONE, targetActions=NONE, gestureModifiers=Ctrl+Button1
DragSite: dropActionChanged: userAction=MOVE, dropAction=NONE, targetActions=NONE, gestureModifiers=Button1
=========================================================
It received the expected dropAction since dragExit had been called, as expected.
TESTCASE
--------
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.beans.*;
public class DnDButtonTest extends Frame implements ActionListener, DragGestureListener, DragSourceListener, Transferable, DropTargetListener {
private static DataFlavor flavors[] = {DataFlavor.stringFlavor};
private Button btn = null;
private TextField textf = null;
private static Hashtable<Integer,String> dndAction = new Hashtable<Integer,String>(){{
put(new Integer(DnDConstants.ACTION_COPY), new String("COPY"));
put(new Integer(DnDConstants.ACTION_COPY_OR_MOVE), new String("COPY_OR_MOVE"));
put(new Integer(DnDConstants.ACTION_LINK), new String("LINK"));
put(new Integer(DnDConstants.ACTION_MOVE), new String("MOVE"));
put(new Integer(DnDConstants.ACTION_NONE), new String("NONE"));
}};
public DnDButtonTest(String s){
setTitle("DnDButtonTest");
setLayout(new BorderLayout());
btn = new Button(s);
btn.setPreferredSize(new Dimension(300, 100));
add(btn, BorderLayout.CENTER);
Panel p = new Panel();
p.setLayout(new FlowLayout());
textf = new TextField(s, 15);
p.add(textf);
Button copyBtn = new Button("Put");
copyBtn.addActionListener(this);
p.add(copyBtn);
add(p, BorderLayout.SOUTH);
DragSource ds = DragSource.getDefaultDragSource();
ds.createDefaultDragGestureRecognizer(btn, DnDConstants.ACTION_COPY_OR_MOVE, this);
DropTarget dt = new DropTarget(btn, this);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent event) { System.exit(0);}
});
pack();
setLocationByPlatform(true);
setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
btn.setLabel(textf.getText());
}
public void dragGestureRecognized(DragGestureEvent dge){
dge.startDrag(null, this, this);
}
public void dragEnter(DragSourceDragEvent dsde){
System.out.printf("DragSite: dragEnter: userAction=%s, dropAction=%s, targetActions=%s, gestureModifiers=%s%n",
dndAction.get(dsde.getUserAction()), dndAction.get(dsde.getDropAction()),
dndAction.get(dsde.getTargetActions()), KeyEvent.getKeyModifiersText(dsde.getGestureModifiers()));
}
public void dragOver(DragSourceDragEvent dsde){}
public void dropActionChanged(DragSourceDragEvent dsde){
System.out.printf("DragSite: dropActionChanged: userAction=%s, dropAction=%s, targetActions=%s, gestureModifiers=%s%n",
dndAction.get(dsde.getUserAction()), dndAction.get(dsde.getDropAction()),
dndAction.get(dsde.getTargetActions()), KeyEvent.getKeyModifiersText(dsde.getGestureModifiers()));
}
public void dragExit(DragSourceEvent dsde){
System.out.println("DragSite: dragExit");
}
public void dragDropEnd(DragSourceDropEvent dsde){
System.out.printf("DragSite: dragDropEnd: dropSuccess=%s, dropAction=%s%n",
dsde.getDropSuccess() ? "true" : "false", dndAction.get(dsde.getDropAction()));
}
public synchronized DataFlavor[] getTransferDataFlavors(){
return flavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor){
return(flavor.equals(flavors[0]));
}
public synchronized Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.equals(flavors[0])) {
System.out.printf("DragSite: getTransferData=[%s]%n", btn.getLabel());
return(Object)btn.getLabel();
}
throw new UnsupportedFlavorException(flavor);
}
public void dragEnter(DropTargetDragEvent dtde) {
int action = dtde.getDropAction();
System.out.printf("DropSite: dragEnter: dropAction=%s, sourceActions=%s%n",
dndAction.get(action), dndAction.get(dtde.getSourceActions()));
if (action == DnDConstants.ACTION_COPY || action == DnDConstants.ACTION_MOVE) {
if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
dtde.acceptDrag(action);
return;
}
} else {
dtde.rejectDrag();
return;
}
dtde.rejectDrag();
}
public void dragOver(DropTargetDragEvent dtde) {
}
public void dropActionChanged(DropTargetDragEvent dtde) {
System.out.printf("DropSite: dropActionChanged: dropAction=%s, sourceActions=%s%n",
dndAction.get(dtde.getDropAction()), dndAction.get(dtde.getSourceActions()));
}
public void dragExit(DropTargetEvent dte) {
System.out.println("DropSite: dragExit");
}
public void drop(DropTargetDropEvent dtde) {
int action = dtde.getDropAction();
if (action == DnDConstants.ACTION_COPY) {
dtde.acceptDrop(DnDConstants.ACTION_COPY);
} else if (action == DnDConstants.ACTION_MOVE) {
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
} else {
dtde.dropComplete(false);
return;
}
try {
Transferable content = dtde.getTransferable();
if (content.isDataFlavorSupported(DataFlavor.stringFlavor)) {
String s = (String)content.getTransferData(DataFlavor.stringFlavor);
btn.setLabel(s);
System.out.printf("DropSite: drop: getTransferData=[%s], dropAction=%s%n",
s, dndAction.get(action));
dtde.dropComplete(true);
} else {
dtde.dropComplete(false);
}
} catch (Exception e) {
e.printStackTrace();
dtde.dropComplete(false);
}
}
public static void main(String args[]){
for (String s : args) new DnDButtonTest(s);
}
}
- backported by
-
JDK-2213386 DnD DragSite receives unexpected drop action after keyboard drop action change
-
- Closed
-
-
JDK-2214112 DnD DragSite receives unexpected drop action after keyboard drop action change
-
- Closed
-
- relates to
-
JDK-4869264 drag & drop action negotiation does not honor the targets supported actions
-
- Resolved
-