1 /**
   2  * @test
   3  * @key headful
   4  * @bug 4494085 8158366
   5  * @summary verifies that the recognized action matches modifiers state
   6  * @compile RecognizedActionTest.java
   7  * @run main RecognizedActionTest
   8  */
   9 
  10 import java.awt.Frame;
  11 import java.awt.Component;
  12 import java.awt.Robot;
  13 import java.awt.Point;
  14 import java.awt.Dimension;
  15 import java.awt.AWTEvent;
  16 import java.awt.event.AWTEventListener;
  17 import java.awt.event.InputEvent;
  18 import java.awt.event.KeyEvent;
  19 import java.awt.event.MouseEvent;
  20 import java.awt.dnd.DnDConstants;
  21 import java.awt.dnd.DragSource;
  22 import java.awt.dnd.DragGestureListener;
  23 import java.awt.dnd.DragGestureEvent;
  24 
  25 public class RecognizedActionTest implements AWTEventListener {
  26 
  27     final Frame frame = new Frame();
  28     boolean dragGestureRecognized = false;
  29     int currentDragAction = DnDConstants.ACTION_NONE;
  30 
  31     final int[] modifiers = {
  32             0,
  33             InputEvent.CTRL_DOWN_MASK,
  34             InputEvent.SHIFT_DOWN_MASK,
  35             InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK
  36     };
  37 
  38     final DragSource dragSource = DragSource.getDefaultDragSource();
  39     final DragGestureListener dragGestureListener = new DragGestureListener() {
  40 
  41         public void dragGestureRecognized(DragGestureEvent dge) {
  42             dragGestureRecognized = true;
  43 
  44             if (dge.getDragAction() != currentDragAction) {
  45                 throw new RuntimeException("Expected: " +
  46                         Integer.toHexString(currentDragAction) +
  47                         " recognized: " +
  48                         Integer.toHexString(dge.getDragAction()));
  49             }
  50         }
  51     };
  52 
  53     final Object SYNC_LOCK = new Object();
  54     final int FRAME_ACTIVATION_TIMEOUT = 2000;
  55     final int MOUSE_RELEASE_TIMEOUT = 1000;
  56 
  57     Component clickedComponent = null;
  58 
  59     public void init() {
  60         try {
  61             frame.setTitle("Test frame");
  62             frame.setBounds(100, 100, 200, 200);
  63             dragSource.createDefaultDragGestureRecognizer(frame,
  64                     DnDConstants.ACTION_COPY |
  65                             DnDConstants.ACTION_MOVE |
  66                             DnDConstants.ACTION_LINK,
  67                     dragGestureListener);
  68 
  69             frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK);
  70             frame.setVisible(true);
  71             Thread.sleep(100);
  72 
  73             final Robot robot = new Robot();
  74             robot.waitForIdle();
  75 
  76             Thread.sleep(FRAME_ACTIVATION_TIMEOUT);
  77 
  78             final Point srcPoint = frame.getLocationOnScreen();
  79             Dimension d = frame.getSize();
  80             srcPoint.translate(d.width / 2, d.height / 2);
  81 
  82             if (!pointInComponent(robot, srcPoint, frame)) {
  83                 System.err.println("WARNING: Couldn't locate source frame.");
  84                 return;
  85             }
  86 
  87             final Point dstPoint = new Point(srcPoint);
  88             dstPoint.translate(d.width / 4, d.height / 4);
  89 
  90             if (!pointInComponent(robot, dstPoint, frame)) {
  91                 System.err.println("WARNING: Couldn't locate target frame.");
  92                 return;
  93             }
  94 
  95             for (int i = 0; i < modifiers.length; i++) {
  96                 currentDragAction = convertModifiersToDropAction(modifiers[i]);
  97                 dragGestureRecognized = false;
  98                 final Point curPoint = new Point(srcPoint);
  99                 robot.mouseMove(curPoint.x, curPoint.y);
 100 
 101                 switch (modifiers[i]) {
 102                     case InputEvent.SHIFT_DOWN_MASK:
 103                         robot.keyPress(KeyEvent.VK_SHIFT);
 104                         robot.waitForIdle();
 105                         break;
 106 
 107                     case InputEvent.CTRL_DOWN_MASK:
 108                         robot.keyPress(KeyEvent.VK_CONTROL);
 109                         robot.waitForIdle();
 110                         break;
 111 
 112                     case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
 113                         robot.keyPress(KeyEvent.VK_CONTROL);
 114                         robot.waitForIdle();
 115                         robot.keyPress(KeyEvent.VK_SHIFT);
 116                         robot.waitForIdle();
 117                         break;
 118 
 119                     default:
 120                         break;
 121                 }
 122                 robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
 123                 Thread.sleep(100);
 124 
 125                 for (; !curPoint.equals(dstPoint) && !dragGestureRecognized;
 126                      curPoint.translate(sign(dstPoint.x - curPoint.x),
 127                              sign(dstPoint.y - curPoint.y))) {
 128                     robot.mouseMove(curPoint.x, curPoint.y);
 129                     Thread.sleep(50);
 130                 }
 131                 Thread.sleep(100);
 132 
 133                 robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
 134 
 135                 switch (modifiers[i]) {
 136                     case InputEvent.SHIFT_DOWN_MASK:
 137                         robot.keyRelease(KeyEvent.VK_SHIFT);
 138                         robot.waitForIdle();
 139                         break;
 140 
 141                     case InputEvent.CTRL_DOWN_MASK:
 142                         robot.keyRelease(KeyEvent.VK_CONTROL);
 143                         robot.waitForIdle();
 144                         break;
 145 
 146                     case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
 147                         robot.keyRelease(KeyEvent.VK_CONTROL);
 148                         robot.waitForIdle();
 149                         robot.keyRelease(KeyEvent.VK_SHIFT);
 150                         robot.waitForIdle();
 151                         break;
 152 
 153                     default:
 154                         break;
 155                 }
 156                 Thread.sleep(100);
 157             }
 158 
 159         } catch (Exception e) {
 160             e.printStackTrace();
 161             throw new RuntimeException("The test failed.");
 162         }
 163     }
 164 
 165     public int sign(int n) {
 166         return n < 0 ? -1 : n == 0 ? 0 : 1;
 167     }
 168 
 169     public void reset() {
 170         clickedComponent = null;
 171     }
 172 
 173     public void eventDispatched(AWTEvent e) {
 174         if (e.getID() == MouseEvent.MOUSE_RELEASED) {
 175             clickedComponent = (Component) e.getSource();
 176             synchronized (SYNC_LOCK) {
 177                 SYNC_LOCK.notifyAll();
 178             }
 179         }
 180     }
 181 
 182     public boolean pointInComponent(Robot robot, Point p, Component comp)
 183             throws InterruptedException {
 184         reset();
 185         robot.mouseMove(p.x, p.y);
 186         robot.waitForIdle();
 187         robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
 188         robot.waitForIdle();
 189         synchronized (SYNC_LOCK) {
 190             robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
 191             SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
 192         }
 193 
 194         Component c = clickedComponent;
 195 
 196         while (c != null && c != comp) {
 197             c = c.getParent();
 198         }
 199 
 200         return c == comp;
 201     }
 202 
 203     public void dispose() {
 204         frame.dispose();
 205     }
 206 
 207     public int convertModifiersToDropAction(int modifiers) {
 208         int dropAction = DnDConstants.ACTION_NONE;
 209 
 210         switch (modifiers & (InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) {
 211             case InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK:
 212                 dropAction = DnDConstants.ACTION_LINK;
 213                 break;
 214 
 215             case InputEvent.CTRL_DOWN_MASK:
 216                 dropAction = DnDConstants.ACTION_COPY;
 217                 break;
 218 
 219             case InputEvent.SHIFT_DOWN_MASK:
 220                 dropAction = DnDConstants.ACTION_MOVE;
 221                 break;
 222 
 223             default:
 224                 dropAction = DnDConstants.ACTION_MOVE;
 225                 break;
 226         }
 227 
 228         return dropAction;
 229     }
 230 
 231     public static void main(String args[]) {
 232         RecognizedActionTest actionTest = new RecognizedActionTest();
 233         actionTest.init();
 234         actionTest.dispose();
 235     }
 236 }