1 /*
   2  * Copyright (c) 2015, 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.Dialog;
  25 import java.awt.Frame;
  26 import java.awt.Point;
  27 import java.awt.Robot;
  28 import java.awt.Window;
  29 import java.awt.datatransfer.DataFlavor;
  30 import java.awt.datatransfer.Transferable;
  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.dnd.DropTarget;
  36 import java.awt.dnd.DropTargetDragEvent;
  37 import java.awt.dnd.DropTargetDropEvent;
  38 import java.awt.dnd.DropTargetEvent;
  39 import java.awt.dnd.DropTargetListener;
  40 import java.awt.event.InputEvent;
  41 import java.awt.event.MouseAdapter;
  42 import java.awt.event.MouseEvent;
  43 
  44 /*
  45  * @test
  46  * @bug 8134917
  47  * @summary [macosx] JOptionPane doesn't receive mouse events when opened from a drop event
  48  * @author Alexandr Scherbatiy
  49  */
  50 public class MissingEventsOnModalDialogTest {
  51 
  52     private static volatile boolean passed = false;
  53 
  54     public static void main(String[] args) throws Exception {
  55         Frame sourceFrame = createFrame("Source Frame", 0, 0);
  56         Frame targetFrame = createFrame("Target Frame", 250, 250);
  57 
  58         DragSource defaultDragSource
  59                 = DragSource.getDefaultDragSource();
  60         defaultDragSource.createDefaultDragGestureRecognizer(sourceFrame,
  61                 DnDConstants.ACTION_COPY_OR_MOVE,
  62                 new TestDragGestureListener());
  63         new DropTarget(targetFrame, DnDConstants.ACTION_COPY_OR_MOVE,
  64                 new TestDropTargetListener(targetFrame));
  65 
  66         Robot robot = new Robot();
  67         robot.setAutoDelay(50);
  68 
  69         sourceFrame.toFront();
  70         robot.waitForIdle();
  71 
  72         Point point = getCenterPoint(sourceFrame);
  73         robot.mouseMove(point.x, point.y);
  74         robot.waitForIdle();
  75 
  76         mouseDragAndDrop(robot, point, getCenterPoint(targetFrame));
  77 
  78         long time = System.currentTimeMillis() + 200;
  79 
  80         while (!passed) {
  81             if (time < System.currentTimeMillis()) {
  82                 sourceFrame.dispose();
  83                 targetFrame.dispose();
  84                 throw new RuntimeException("Mouse clicked event is lost!");
  85             }
  86             Thread.sleep(10);
  87         }
  88         sourceFrame.dispose();
  89         targetFrame.dispose();
  90     }
  91 
  92     private static Frame createFrame(String title, int x, int y) {
  93         Frame frame = new Frame();
  94         frame.setSize(200, 200);
  95         frame.setLocation(x, y);
  96         frame.setTitle(title);
  97         frame.setVisible(true);
  98         return frame;
  99     }
 100 
 101     private static Point getCenterPoint(Window window) {
 102         Point centerPoint = window.getLocationOnScreen();
 103         centerPoint.translate(window.getWidth() / 2, window.getHeight() / 2);
 104         return centerPoint;
 105     }
 106 
 107     public static void mouseDragAndDrop(Robot robot, Point from, Point to) {
 108         mouseDND(robot, from.x, from.y, to.x, to.y);
 109     }
 110 
 111     public static void mouseDND(Robot robot, int x1, int y1, int x2, int y2) {
 112 
 113         int N = 20;
 114         int x = x1;
 115         int y = y1;
 116         int dx = (x2 - x1) / N;
 117         int dy = (y2 - y1) / N;
 118 
 119         robot.mousePress(InputEvent.BUTTON1_MASK);
 120 
 121         for (int i = 0; i < N; i++) {
 122             robot.mouseMove(x += dx, y += dy);
 123         }
 124 
 125         robot.mouseRelease(InputEvent.BUTTON1_MASK);
 126     }
 127 
 128     private static class TestDragGestureListener implements DragGestureListener {
 129 
 130         public void dragGestureRecognized(DragGestureEvent dge) {
 131             dge.startDrag(null, new StringTransferable());
 132         }
 133     }
 134 
 135     static class StringTransferable implements Transferable {
 136 
 137         @Override
 138         public DataFlavor[] getTransferDataFlavors() {
 139             return new DataFlavor[]{DataFlavor.stringFlavor};
 140         }
 141 
 142         @Override
 143         public boolean isDataFlavorSupported(DataFlavor flavor) {
 144             return flavor.equals(DataFlavor.stringFlavor);
 145         }
 146 
 147         @Override
 148         public Object getTransferData(DataFlavor flavor) {
 149             return "Hello World!";
 150         }
 151     }
 152 
 153     private static class TestDropTargetListener implements DropTargetListener {
 154 
 155         private final Frame targetFrame;
 156 
 157         public TestDropTargetListener(Frame targetFrame) {
 158             this.targetFrame = targetFrame;
 159         }
 160 
 161         @Override
 162         public void dragEnter(DropTargetDragEvent dtde) {
 163             dtde.acceptDrag(dtde.getDropAction());
 164         }
 165 
 166         @Override
 167         public void dragOver(DropTargetDragEvent dtde) {
 168             dtde.acceptDrag(dtde.getDropAction());
 169         }
 170 
 171         @Override
 172         public void dropActionChanged(DropTargetDragEvent dtde) {
 173             dtde.acceptDrag(dtde.getDropAction());
 174         }
 175 
 176         @Override
 177         public void dragExit(DropTargetEvent dte) {
 178         }
 179 
 180         @Override
 181         public void drop(DropTargetDropEvent dtde) {
 182             dtde.acceptDrop(dtde.getDropAction());
 183             showModalDialog(targetFrame);
 184             dtde.dropComplete(true);
 185         }
 186     }
 187 
 188     private static void showModalDialog(Frame targetFrame) {
 189 
 190         Dialog dialog = new Dialog(targetFrame, true);
 191 
 192         dialog.addMouseListener(new MouseAdapter() {
 193 
 194             @Override
 195             public void mouseClicked(MouseEvent e) {
 196                 passed = true;
 197                 dialog.dispose();
 198             }
 199         });
 200 
 201         dialog.setSize(400, 300);
 202         dialog.setTitle("Modal Dialog!");
 203 
 204         clickOnModalDialog(dialog);
 205         dialog.setVisible(true);
 206     }
 207 
 208     private static void clickOnModalDialog(Dialog dialog) {
 209         new Thread(() -> {
 210             clickOnDialog(dialog);
 211         }).start();
 212     }
 213 
 214     private static void clickOnDialog(Dialog dialog) {
 215         try {
 216             long time = System.currentTimeMillis() + 200;
 217 
 218             while (!dialog.isVisible()) {
 219                 if (time < System.currentTimeMillis()) {
 220                     throw new RuntimeException("Dialog is not visible!");
 221                 }
 222                 Thread.sleep(10);
 223             }
 224 
 225             Point point = getCenterPoint(dialog);
 226             Robot robot = new Robot();
 227             robot.setAutoDelay(50);
 228 
 229             robot.mouseMove(point.x, point.y);
 230             robot.mousePress(InputEvent.BUTTON1_MASK);
 231             robot.mouseRelease(InputEvent.BUTTON1_MASK);
 232 
 233         } catch (Exception e) {
 234             throw new RuntimeException(e);
 235         }
 236     }
 237 }