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 
main(String[] args)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 
createFrame(String title, int x, int y)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 
getCenterPoint(Window window)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 
mouseDragAndDrop(Robot robot, Point from, Point to)107     public static void mouseDragAndDrop(Robot robot, Point from, Point to) {
108         mouseDND(robot, from.x, from.y, to.x, to.y);
109     }
110 
mouseDND(Robot robot, int x1, int y1, int x2, int y2)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 
dragGestureRecognized(DragGestureEvent dge)130         public void dragGestureRecognized(DragGestureEvent dge) {
131             dge.startDrag(null, new StringTransferable());
132         }
133     }
134 
135     static class StringTransferable implements Transferable {
136 
137         @Override
getTransferDataFlavors()138         public DataFlavor[] getTransferDataFlavors() {
139             return new DataFlavor[]{DataFlavor.stringFlavor};
140         }
141 
142         @Override
isDataFlavorSupported(DataFlavor flavor)143         public boolean isDataFlavorSupported(DataFlavor flavor) {
144             return flavor.equals(DataFlavor.stringFlavor);
145         }
146 
147         @Override
getTransferData(DataFlavor flavor)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 
TestDropTargetListener(Frame targetFrame)157         public TestDropTargetListener(Frame targetFrame) {
158             this.targetFrame = targetFrame;
159         }
160 
161         @Override
dragEnter(DropTargetDragEvent dtde)162         public void dragEnter(DropTargetDragEvent dtde) {
163             dtde.acceptDrag(dtde.getDropAction());
164         }
165 
166         @Override
dragOver(DropTargetDragEvent dtde)167         public void dragOver(DropTargetDragEvent dtde) {
168             dtde.acceptDrag(dtde.getDropAction());
169         }
170 
171         @Override
dropActionChanged(DropTargetDragEvent dtde)172         public void dropActionChanged(DropTargetDragEvent dtde) {
173             dtde.acceptDrag(dtde.getDropAction());
174         }
175 
176         @Override
dragExit(DropTargetEvent dte)177         public void dragExit(DropTargetEvent dte) {
178         }
179 
180         @Override
drop(DropTargetDropEvent dtde)181         public void drop(DropTargetDropEvent dtde) {
182             dtde.acceptDrop(dtde.getDropAction());
183             showModalDialog(targetFrame);
184             dtde.dropComplete(true);
185         }
186     }
187 
showModalDialog(Frame targetFrame)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 
clickOnModalDialog(Dialog dialog)208     private static void clickOnModalDialog(Dialog dialog) {
209         new Thread(() -> {
210             clickOnDialog(dialog);
211         }).start();
212     }
213 
clickOnDialog(Dialog dialog)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 }
238