1 /*
   2  * Copyright (c) 2014, 2018, 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 /*
  25   @test
  26   @key headful
  27   @bug 4658741
  28   @summary verifies that getDropSuccess() returns correct value for inter-JVM DnD
  29   @run main InterJVMGetDropSuccessTest
  30 */
  31 
  32 import java.awt.*;
  33 import java.awt.datatransfer.*;
  34 import java.awt.dnd.*;
  35 import java.awt.event.*;
  36 import java.io.*;
  37 
  38 public class InterJVMGetDropSuccessTest {
  39 
  40     private int returnCode = Util.CODE_NOT_RETURNED;
  41     private boolean successCodes[] = { true, false };
  42     private int dropCount = 0;
  43 
  44     final Frame frame = new Frame("Target Frame");
  45 
  46     final DropTargetListener dropTargetListener = new DropTargetAdapter() {
  47             public void drop(DropTargetDropEvent dtde) {
  48                 dtde.acceptDrop(DnDConstants.ACTION_COPY);
  49                 dtde.dropComplete(successCodes[dropCount]);
  50                 dropCount++;
  51             }
  52         };
  53     final DropTarget dropTarget = new DropTarget(frame, dropTargetListener);
  54 
  55     public static void main(final String[] args) {
  56         InterJVMGetDropSuccessTest app = new InterJVMGetDropSuccessTest();
  57         app.init();
  58         app.start();
  59     }
  60 
  61     public void init() {
  62         frame.setTitle("Test frame");
  63         frame.setBounds(100, 100, 150, 150);
  64     } // init()
  65 
  66     public void start() {
  67 
  68         frame.setVisible(true);
  69 
  70         try {
  71             Thread.sleep(Util.FRAME_ACTIVATION_TIMEOUT);
  72 
  73             Point p = frame.getLocationOnScreen();
  74             Dimension d = frame.getSize();
  75 
  76             String javaPath = System.getProperty("java.home", "");
  77             String command = javaPath + File.separator + "bin" +
  78                 File.separator + "java -cp " + System.getProperty("test.classes", ".") +
  79                 " Child " +
  80                 p.x + " " + p.y + " " + d.width + " " + d.height;
  81 
  82             Process process = Runtime.getRuntime().exec(command);
  83             returnCode = process.waitFor();
  84 
  85             InputStream errorStream = process.getErrorStream();
  86             int count = errorStream.available();
  87             if (count > 0) {
  88                 byte[] b = new byte[count];
  89                 errorStream.read(b);
  90                 System.err.println("========= Child VM System.err ========");
  91                 System.err.print(new String(b));
  92                 System.err.println("======================================");
  93             }
  94 
  95             InputStream outputStream = process.getInputStream();
  96             count = outputStream.available();
  97             if (count > 0) {
  98                 byte[] b = new byte[count];
  99                 outputStream.read(b);
 100                 System.err.println("========= Child VM System.out ========");
 101                 System.err.print(new String(b));
 102                 System.err.println("======================================");
 103             }
 104         } catch (Throwable e) {
 105             e.printStackTrace();
 106             throw new RuntimeException(e);
 107         }
 108         switch (returnCode) {
 109         case Util.CODE_NOT_RETURNED:
 110             throw new RuntimeException("Child VM: failed to start");
 111         case Util.CODE_FAILURE:
 112             throw new RuntimeException("Child VM: abnormal termination");
 113         default:
 114             if (dropCount == 2) {
 115                 int expectedRetCode = 0;
 116                 if (successCodes[0]) {
 117                     expectedRetCode |= Util.CODE_FIRST_SUCCESS;
 118                 }
 119                 if (successCodes[1]) {
 120                     expectedRetCode |= Util.CODE_SECOND_SUCCESS;
 121                 }
 122                 if (expectedRetCode != returnCode) {
 123                     throw new RuntimeException("The test failed. Expected:" +
 124                                                expectedRetCode + ". Returned:" +
 125                                                returnCode);
 126                 }
 127             }
 128             break;
 129         }
 130     } // start()
 131 } // class InterJVMGetDropSuccessTest
 132 
 133 final class Util implements AWTEventListener {
 134     public static final int CODE_NOT_RETURNED = -1;
 135     public static final int CODE_FIRST_SUCCESS = 0x2;
 136     public static final int CODE_SECOND_SUCCESS = 0x2;
 137     public static final int CODE_FAILURE = 0x1;
 138 
 139     public static final int FRAME_ACTIVATION_TIMEOUT = 3000;
 140 
 141     static final Object SYNC_LOCK = new Object();
 142     static final int MOUSE_RELEASE_TIMEOUT = 1000;
 143 
 144     static final Util theInstance = new Util();
 145 
 146     static {
 147         Toolkit.getDefaultToolkit().addAWTEventListener(theInstance, AWTEvent.MOUSE_EVENT_MASK);
 148     }
 149 
 150     public static Point getCenterLocationOnScreen(Component c) {
 151         Point p = c.getLocationOnScreen();
 152         Dimension d = c.getSize();
 153         p.translate(d.width / 2, d.height / 2);
 154         return p;
 155     }
 156 
 157     public static int sign(int n) {
 158         return n < 0 ? -1 : n == 0 ? 0 : 1;
 159     }
 160 
 161     private Component clickedComponent = null;
 162 
 163     private void reset() {
 164         clickedComponent = null;
 165     }
 166 
 167     public void eventDispatched(AWTEvent e) {
 168         if (e.getID() == MouseEvent.MOUSE_RELEASED) {
 169             clickedComponent = (Component)e.getSource();
 170             synchronized (SYNC_LOCK) {
 171                 SYNC_LOCK.notifyAll();
 172             }
 173         }
 174     }
 175 
 176     public static boolean pointInComponent(Robot robot, Point p, Component comp)
 177       throws InterruptedException {
 178         return theInstance.pointInComponentImpl(robot, p, comp);
 179     }
 180 
 181     private boolean pointInComponentImpl(Robot robot, Point p, Component comp)
 182       throws InterruptedException {
 183         robot.waitForIdle();
 184         reset();
 185         robot.mouseMove(p.x, p.y);
 186         robot.mousePress(InputEvent.BUTTON1_MASK);
 187         synchronized (SYNC_LOCK) {
 188             robot.mouseRelease(InputEvent.BUTTON1_MASK);
 189             SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT);
 190         }
 191 
 192         Component c = clickedComponent;
 193 
 194         while (c != null && c != comp) {
 195             c = c.getParent();
 196         }
 197 
 198         return c == comp;
 199     }
 200 }
 201 
 202 class Child {
 203     static class DragSourceDropListener extends DragSourceAdapter {
 204         private boolean finished = false;
 205         private boolean dropSuccess = false;
 206 
 207         public void reset() {
 208             finished = false;
 209             dropSuccess = false;
 210         }
 211 
 212         public boolean isDropFinished() {
 213             return finished;
 214         }
 215 
 216         public boolean getDropSuccess() {
 217             return dropSuccess;
 218         }
 219 
 220         public void dragDropEnd(DragSourceDropEvent dsde) {
 221             finished = true;
 222             dropSuccess = dsde.getDropSuccess();
 223             synchronized (Util.SYNC_LOCK) {
 224                 Util.SYNC_LOCK.notifyAll();
 225             }
 226         }
 227     }
 228 
 229     final Frame frame = new Frame("Source Frame");
 230     final DragSource dragSource = DragSource.getDefaultDragSource();
 231     final DragSourceDropListener dragSourceListener = new DragSourceDropListener();
 232     final Transferable transferable = new StringSelection("TEXT");
 233     final DragGestureListener dragGestureListener = new DragGestureListener() {
 234             public void dragGestureRecognized(DragGestureEvent dge) {
 235                 dge.startDrag(null, transferable, dragSourceListener);
 236             }
 237         };
 238     final DragGestureRecognizer dragGestureRecognizer =
 239         dragSource.createDefaultDragGestureRecognizer(frame, DnDConstants.ACTION_COPY,
 240                                                       dragGestureListener);
 241 
 242     public static void main(String[] args) {
 243         Child child = new Child();
 244         child.run(args);
 245     }
 246 
 247     public void run(String[] args) {
 248         try {
 249             if (args.length != 4) {
 250                 throw new RuntimeException("Incorrect command line arguments.");
 251             }
 252 
 253             int x = Integer.parseInt(args[0]);
 254             int y = Integer.parseInt(args[1]);
 255             int w = Integer.parseInt(args[2]);
 256             int h = Integer.parseInt(args[3]);
 257 
 258             frame.setBounds(300, 200, 150, 150);
 259             frame.setVisible(true);
 260 
 261             Thread.sleep(Util.FRAME_ACTIVATION_TIMEOUT);
 262 
 263             Point sourcePoint = Util.getCenterLocationOnScreen(frame);
 264 
 265             Point targetPoint = new Point(x + w / 2, y + h / 2);
 266 
 267             Robot robot = new Robot();
 268             robot.mouseMove(sourcePoint.x, sourcePoint.y);
 269             robot.mousePress(InputEvent.BUTTON1_MASK);
 270             for (Point p = new Point(sourcePoint); !p.equals(targetPoint);
 271                  p.translate(Util.sign(targetPoint.x - p.x),
 272                              Util.sign(targetPoint.y - p.y))) {
 273                 robot.mouseMove(p.x, p.y);
 274                 Thread.sleep(50);
 275             }
 276 
 277             synchronized (Util.SYNC_LOCK) {
 278                 robot.mouseRelease(InputEvent.BUTTON1_MASK);
 279                 Util.SYNC_LOCK.wait(Util.FRAME_ACTIVATION_TIMEOUT);
 280             }
 281 
 282             if (!dragSourceListener.isDropFinished()) {
 283                 throw new RuntimeException("Drop not finished");
 284             }
 285 
 286             boolean success1 = dragSourceListener.getDropSuccess();
 287 
 288             dragSourceListener.reset();
 289             robot.mouseMove(sourcePoint.x, sourcePoint.y);
 290             robot.mousePress(InputEvent.BUTTON1_MASK);
 291             for (Point p = new Point(sourcePoint); !p.equals(targetPoint);
 292                  p.translate(Util.sign(targetPoint.x - p.x),
 293                              Util.sign(targetPoint.y - p.y))) {
 294                 robot.mouseMove(p.x, p.y);
 295                 Thread.sleep(50);
 296             }
 297 
 298             synchronized (Util.SYNC_LOCK) {
 299                 robot.mouseRelease(InputEvent.BUTTON1_MASK);
 300                 Util.SYNC_LOCK.wait(Util.FRAME_ACTIVATION_TIMEOUT);
 301             }
 302 
 303             if (!dragSourceListener.isDropFinished()) {
 304                 throw new RuntimeException("Drop not finished");
 305             }
 306 
 307             boolean success2 = dragSourceListener.getDropSuccess();
 308             int retCode = 0;
 309 
 310             if (success1) {
 311                 retCode |= Util.CODE_FIRST_SUCCESS;
 312             }
 313             if (success2) {
 314                 retCode |= Util.CODE_SECOND_SUCCESS;
 315             }
 316             // This returns the diagnostic code from the child VM
 317             System.exit(retCode);
 318         } catch (Throwable e) {
 319             e.printStackTrace();
 320             // This returns the diagnostic code from the child VM
 321             System.exit(Util.CODE_FAILURE);
 322         }
 323     } // run()
 324 } // class child