1 /*
2  * Copyright (c) 2017, 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 8159062
28  * @summary Tests DnD property with HIDPI scale set to non-interger value 2.5
29  * @run main/othervm -Dsun.java2d.uiScale=2.5 DragTestWithHIDPI
30  */
31 
32 import javax.swing.JList;
33 import javax.swing.TransferHandler;
34 import javax.swing.JFrame;
35 import javax.swing.JComponent;
36 import javax.swing.SwingUtilities;
37 
38 import java.awt.Robot;
39 import java.awt.BorderLayout;
40 import java.awt.Point;
41 import java.awt.Dimension;
42 import java.awt.MouseInfo;
43 import java.awt.event.InputEvent;
44 
45 public class DragTestWithHIDPI extends TransferHandler {
46 
47     private static boolean didDrag = false;
48     private static int threshold = 10;
49     private static int DEFAULT_DELAY = 550;
50 
51     private Robot robot = null;
52     private static JList list = null;
53     private static Point listLocation = null;
54     private static Dimension listSize = null;
55     private static JFrame f = null;
56 
57     private enum Direction {
58         RIGHT, LEFT, BOTTOM, TOP
59     }
60 
main(String[] args)61     public static void main(String[] args) throws Exception {
62         DragTestWithHIDPI test = new DragTestWithHIDPI();
63 
64         // set the mouse move drag threshold
65         System.setProperty("awt.dnd.drag.threshold", String.valueOf(threshold));
66 
67         test.createGUI();
68         test.doTest();
69         System.out.println("Test Passed");
70         test.disposeGUI();
71     }
72 
exportAsDrag(JComponent comp, InputEvent e, int action)73     public void exportAsDrag(JComponent comp, InputEvent e, int action) {
74         didDrag = true;
75     }
76 
DragTestWithHIDPI()77     public DragTestWithHIDPI() {
78         super("foreground");
79     }
80 
createGUI()81     private void createGUI() throws Exception{
82         SwingUtilities.invokeAndWait(() -> {
83             String[] listData =
84                     new String[]{"Pacific Ocean", "Atlantic Ocean", "Indian Ocean",
85                             "Arctic Ocean"};
86             list = new JList(listData);
87             list.setDragEnabled(true);
88             list.setTransferHandler(new DragTestWithHIDPI());
89 
90             f = new JFrame("DragTestWithHIDPI");
91             f.getContentPane().add(list, BorderLayout.CENTER);
92             f.pack();
93             f.toFront();
94             f.setVisible(true);
95 
96             listLocation = list.getLocationOnScreen();
97             listSize = list.getSize();
98         });
99     }
100 
disposeGUI()101     private void disposeGUI () throws  Exception {
102         SwingUtilities.invokeAndWait(() -> {
103             f.dispose();
104         });
105     }
106 
doTest()107     private void doTest() throws Exception {
108 
109         robot = new Robot();
110         robot.waitForIdle();
111 
112         for (Direction direction : Direction.values()) {
113             //Drag should not start only by moving (threshold - 1) pixels
114             didDrag = false;
115             test(threshold - 1, direction);
116             if (didDrag) {
117                 disposeGUI();
118                 throw new RuntimeException(
119                         "Shouldn't start drag until > " + threshold +
120                                 " pixels " + " while moving " + direction);
121             }
122 
123             // Drag should not start only by moving threshold pixels
124             didDrag = false;
125             test(threshold, direction);
126             if (didDrag) {
127                 disposeGUI();
128                 throw new RuntimeException(
129                         "Shouldn't start drag until > " + threshold +
130                                 " pixels" + " while moving " + direction);
131             }
132 
133             // Drag should start after moving threshold + 1 pixel
134             didDrag = false;
135             test(threshold + 1, direction);
136             if (!didDrag) {
137                 disposeGUI();
138                 throw new RuntimeException(
139                         "Should start drag after > " + threshold + " pixels" +
140                                 " while moving " + direction);
141             }
142         }
143     }
144 
test(int threshold, Direction direction)145     private void test(int threshold, Direction direction) {
146         clickMouseOnList(InputEvent.BUTTON1_DOWN_MASK);
147         Point p = MouseInfo.getPointerInfo().getLocation();
148         robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
149         robot.delay(DEFAULT_DELAY);
150         glide(p, direction, threshold);
151         robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
152     }
153 
glide(Point p, Direction direction, int toAdd)154     private void glide(Point p, Direction direction, int toAdd) {
155         switch (direction) {
156             case RIGHT:
157                 // move towards right
158                 glide(p.x, p.y, p.x + toAdd, p.y);
159                 break;
160             case LEFT:
161                 // move towards left
162                 glide(p.x, p.y, p.x - toAdd, p.y);
163                 break;
164             case BOTTOM:
165                 // move towards bottom
166                 glide(p.x, p.y, p.x, p.y + toAdd);
167                 break;
168             case TOP:
169                 // move towards top
170                 glide(p.x, p.y, p.x, p.y - toAdd);
171                 break;
172 
173         }
174     }
175 
176     /*
177     Some utilities functions from JRobot class.
178      */
moveMouseToList()179     private void moveMouseToList() {
180         int x = listLocation.x + listSize.width/2;
181         int y = listLocation.y + listSize.height/2;
182         robot.mouseMove(x, y);
183         robot.delay(DEFAULT_DELAY);
184     }
185 
clickMouse(int buttons)186     private void clickMouse(int buttons) {
187         robot.mousePress(buttons);
188         robot.mouseRelease(buttons);
189         robot.delay(DEFAULT_DELAY);
190     }
191 
clickMouseOnList(int buttons)192     private void clickMouseOnList(int buttons) {
193         moveMouseToList();
194         clickMouse(buttons);
195     }
196 
glide(int x0, int y0, int x1, int y1)197     private void glide(int x0, int y0, int x1, int y1) {
198         float dmax = (float)Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0));
199         float dx = (x1 - x0) / dmax;
200         float dy = (y1 - y0) / dmax;
201 
202         robot.mouseMove(x0, y0);
203         for (int i=1; i<=dmax; i++) {
204             robot.mouseMove((int)(x0 + dx*i), (int)(y0 + dy*i));
205         }
206         robot.delay(DEFAULT_DELAY);
207     }
208 }
209 
210