Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7082955

DnD DragSite receives unexpected drop action after keyboard drop action change

    XMLWordPrintable

Details

    • Bug
    • Resolution: Cannot Reproduce
    • P4
    • 8-pool
    • 7
    • client-libs
    • generic
    • generic

    Backports

      Description

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

        Attachments

          Issue Links

            Activity

              People

                bagiras Oleg Pekhovskiy (Inactive)
                dkorbel David Korbel (Inactive)
                Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: