1 /*
   2  * Copyright (c) 2013, 2014, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package test.robot.com.sun.glass.ui.monocle;
  27 
  28 import com.sun.glass.ui.monocle.TestLogShim;
  29 import test.robot.com.sun.glass.ui.monocle.TestApplication;
  30 import javafx.geometry.Rectangle2D;
  31 import javafx.stage.Screen;
  32 import org.junit.After;
  33 import org.junit.Assert;
  34 import org.junit.Assume;
  35 import org.junit.Before;
  36 import org.junit.Rule;
  37 import org.junit.Test;
  38 import org.junit.rules.TestName;
  39 import test.com.sun.glass.ui.monocle.TestRunnable;
  40 
  41 public class SimpleMouseTest {
  42 
  43     private UInput ui;
  44     @Rule public TestName name = new TestName();
  45 
  46     @Before public void setUpScreen() throws Exception {
  47         TestLogShim.reset();
  48         TestLogShim.log(name.getMethodName());
  49         TestApplication.showFullScreenScene();
  50         TestApplication.addMouseListeners();
  51         TestApplication.movePointerTo(300, 300);
  52         initDevice();
  53     }
  54 
  55     public void initDevice() throws Exception {
  56         ui = new UInput();
  57         ui.processLine("OPEN");
  58         ui.processLine("EVBIT EV_KEY");
  59         ui.processLine("EVBIT EV_SYN");
  60         ui.processLine("KEYBIT BTN_LEFT");
  61         ui.processLine("EVBIT EV_REL");
  62         ui.processLine("RELBIT REL_X");
  63         ui.processLine("RELBIT REL_Y");
  64         ui.processLine("RELBIT REL_WHEEL");
  65         ui.processLine("PROPERTY ID_INPUT_MOUSE 1");
  66         ui.processLine("CREATE");
  67     }
  68 
  69     @After public void destroyDevice() throws Exception {
  70         if (ui != null) {
  71             ui.waitForQuiet();
  72             try {
  73                 ui.processLine("DESTROY");
  74             } catch (RuntimeException e) { }
  75             ui.processLine("CLOSE");
  76             ui.dispose();
  77         }
  78     }
  79 
  80     @Test
  81     public void testRelativeMove() throws Exception {
  82         ui.processLine("EV_REL REL_X -100");
  83         ui.processLine("EV_REL REL_Y -50");
  84         ui.processLine("EV_SYN");
  85         TestLogShim.waitForLog("Mouse moved: 200, 250", 3000);
  86     }
  87 
  88     @Test
  89     public void testRelativeDrag() throws Exception {
  90         ui.processLine("EV_KEY BTN_LEFT 1");
  91         ui.processLine("EV_SYN");
  92         ui.processLine("EV_REL REL_X -100");
  93         ui.processLine("EV_REL REL_Y -50");
  94         ui.processLine("EV_SYN");
  95         ui.processLine("EV_KEY BTN_LEFT 0");
  96         ui.processLine("EV_SYN");
  97         TestLogShim.waitForLog("Mouse pressed: 300, 300", 3000);
  98         TestLogShim.waitForLog("Mouse dragged: 200, 250", 3000);
  99         TestLogShim.waitForLog("Mouse released: 200, 250", 3000);
 100     }
 101 
 102     @Test
 103     public void testWheel() throws Exception {
 104         TestApplication.getStage().getScene().setOnScroll(
 105                 (e) -> TestLogShim.format("Scroll: %.0g",
 106                                       Math.signum(e.getDeltaY())));
 107         ui.processLine("EV_SYN");
 108         ui.processLine("EV_REL REL_WHEEL 1");
 109         ui.processLine("EV_SYN");
 110         ui.processLine("EV_REL REL_WHEEL 0");
 111         ui.processLine("EV_SYN");
 112         TestLogShim.waitForLog("Scroll: 1");
 113         TestLogShim.reset();
 114 
 115         ui.processLine("EV_REL REL_WHEEL -1");
 116         ui.processLine("EV_SYN");
 117         ui.processLine("EV_REL REL_WHEEL 0");
 118         ui.processLine("EV_SYN");
 119         TestLogShim.waitForLog("Scroll: -1");
 120     }
 121 
 122     @Test
 123     public void testWheelSequence() throws Exception {
 124         TestApplication.getStage().getScene().setOnScroll(
 125                 (e) -> TestLogShim.format("Scroll: %.0g",
 126                                       Math.signum(e.getDeltaY())));
 127         ui.processLine("EV_REL REL_WHEEL 1");
 128         ui.processLine("EV_SYN");
 129         ui.processLine("EV_REL REL_WHEEL 1");
 130         ui.processLine("EV_SYN");
 131         ui.processLine("EV_REL REL_WHEEL 1");
 132         ui.processLine("EV_SYN");
 133         new TestRunnable() {
 134             @Override
 135             public void test() {
 136                 Assert.assertEquals(3, TestLogShim.countLogContaining("Scroll: 1"));
 137             }
 138         }.invokeAndWaitUntilSuccess(3000l);
 139         TestLogShim.reset();
 140 
 141         ui.processLine("EV_REL REL_WHEEL -1");
 142         ui.processLine("EV_SYN");
 143         ui.processLine("EV_REL REL_WHEEL -1");
 144         ui.processLine("EV_SYN");
 145         ui.processLine("EV_REL REL_WHEEL -1");
 146         ui.processLine("EV_SYN");
 147         new TestRunnable() {
 148             @Override
 149             public void test() {
 150                 Assert.assertEquals(3, TestLogShim.countLogContaining("Scroll: -1"));
 151             }
 152         }.invokeAndWaitUntilSuccess(3000l);
 153     }
 154 
 155     @Test
 156     public void testClickLeft() throws Exception {
 157         ui.processLine("EV_KEY BTN_LEFT 1");
 158         ui.processLine("EV_SYN SYN_REPORT 0");
 159         ui.processLine("EV_KEY BTN_LEFT 0");
 160         ui.processLine("EV_SYN SYN_REPORT 0");
 161         TestLogShim.waitForLogContaining("Mouse pressed: 300, 300");
 162         TestLogShim.waitForLogContaining("Mouse released: 300, 300");
 163         TestLogShim.waitForLogContaining("Mouse clicked: 300, 300");
 164     }
 165 
 166     @Test
 167     public void testClickRight() throws Exception {
 168         ui.processLine("EV_KEY BTN_RIGHT 1");
 169         ui.processLine("EV_SYN SYN_REPORT 0");
 170         ui.processLine("EV_KEY BTN_RIGHT 0");
 171         ui.processLine("EV_SYN SYN_REPORT 0");
 172         TestLogShim.waitForLogContaining("Mouse pressed: 300, 300");
 173         TestLogShim.waitForLogContaining("Mouse released: 300, 300");
 174         TestLogShim.waitForLogContaining("Mouse clicked: 300, 300");
 175     }
 176 
 177     @Test
 178     public void testDragLookahead() throws Exception {
 179         Assume.assumeTrue(TestApplication.isMonocle());
 180         TestApplication.showFullScreenScene();
 181         TestApplication.addMouseListeners();
 182         TestLogShim.reset();
 183         Rectangle2D r = Screen.getPrimary().getBounds();
 184         final int width = (int) r.getWidth();
 185         final int height = (int) r.getHeight();
 186         final int x1 = (int) Math.round(width * 0.1);
 187         final int y1 = (int) Math.round(height * 0.1);
 188         final int delta = (int) Math.min(width / 2.0, height / 2.0);
 189         final int x2 = x1 + delta;
 190         final int y2 = y1 + delta;
 191         final int x3 = (int) Math.round(width * 0.9);
 192         final int y3 = (int) Math.round(height * 0.9);
 193         // Move the mouse to 0, 0
 194         ui.processLine("EV_REL REL_X " + -width);
 195         ui.processLine("EV_REL REL_Y " + -height);
 196         ui.processLine("EV_SYN");
 197         TestLogShim.waitForLog("Mouse moved: 0, 0");
 198         // Move to x1, y1
 199         ui.processLine("EV_REL REL_X " + x1);
 200         ui.processLine("EV_REL REL_Y " + y1);
 201         ui.processLine("EV_SYN");
 202         TestLogShim.waitForLog("Mouse moved: %d, %d", x1, y1);
 203         // Push events while on the event thread, making sure that events
 204         // will be buffered up and enabling filtering to take place
 205         TestRunnable.invokeAndWait(() -> {
 206             ui.processLine("EV_KEY BTN_LEFT 1");
 207             ui.processLine("EV_SYN");
 208             for (int i = 0; i < delta; i++) {
 209                 ui.processLine("EV_REL REL_X 1");
 210                 ui.processLine("EV_REL REL_Y 1");
 211                 ui.processLine("EV_SYN");
 212             }
 213             ui.processLine("EV_REL REL_X " + (x3 - x2));
 214             ui.processLine("EV_REL REL_Y " + (y3 - y2));
 215             ui.processLine("EV_SYN");
 216             ui.processLine("EV_KEY BTN_LEFT 0");
 217             ui.processLine("EV_SYN");
 218         });
 219         // Check that the initial point reported is correct
 220         TestLogShim.waitForLog("Mouse pressed: %d, %d", x1, y1);
 221         // Check that the final point reported is correct
 222         TestLogShim.waitForLog("Mouse released: %d, %d", x3, y3);
 223         TestLogShim.waitForLog("Mouse dragged: %d, %d", x3, y3);
 224         // Check that moves in between were filtered
 225         Assert.assertTrue(TestLogShim.countLogContaining("Mouse dragged") <= (x2 - x1) / 10);
 226     }
 227 
 228     @Test
 229     public void testMoveLookahead() throws Exception {
 230         Assume.assumeTrue(TestApplication.isMonocle());
 231         TestApplication.showFullScreenScene();
 232         TestApplication.addMouseListeners();
 233         TestLogShim.reset();
 234         Rectangle2D r = Screen.getPrimary().getBounds();
 235         final int width = (int) r.getWidth();
 236         final int height = (int) r.getHeight();
 237         final int x1 = (int) Math.round(width * 0.1);
 238         final int y1 = (int) Math.round(height * 0.1);
 239         final int delta = (int) Math.min(width / 2.0, height / 2.0);
 240         final int x2 = x1 + delta;
 241         final int y2 = y1 + delta;
 242         final int x3 = (int) Math.round(width * 0.9);
 243         final int y3 = (int) Math.round(height * 0.9);
 244         // Move the mouse to 0, 0
 245         ui.processLine("EV_REL REL_X " + -width);
 246         ui.processLine("EV_REL REL_Y " + -height);
 247         ui.processLine("EV_SYN");
 248         TestLogShim.waitForLog("Mouse moved: 0, 0");
 249         // Move to x1, y1
 250         ui.processLine("EV_REL REL_X " + x1);
 251         ui.processLine("EV_REL REL_Y " + y1);
 252         ui.processLine("EV_SYN");
 253         TestLogShim.waitForLog("Mouse moved: %d, %d", x1, y1);
 254         // Push events while on the event thread, making sure that events
 255         // will be buffered up and enabling filtering to take place
 256         TestRunnable.invokeAndWait(() -> {
 257             for (int i = 0; i < delta; i++) {
 258                 ui.processLine("EV_REL REL_X 1");
 259                 ui.processLine("EV_REL REL_Y 1");
 260                 ui.processLine("EV_SYN");
 261             }
 262             ui.processLine("EV_REL REL_X " + (x3 - x2));
 263             ui.processLine("EV_REL REL_Y " + (y3 - y2));
 264             ui.processLine("EV_SYN");
 265         });
 266         // Check that the final point reported is correct
 267         TestLogShim.waitForLog("Mouse moved: %d, %d", x3, y3);
 268         // Check that moves in between were filtered
 269         Assert.assertTrue(TestLogShim.countLogContaining("Mouse moved") <= (x2 - x1) / 10);
 270         // Check that we didn't get any other events
 271         Assert.assertEquals(0, TestLogShim.countLogContaining("Mouse pressed"));
 272         Assert.assertEquals(0, TestLogShim.countLogContaining("Mouse released"));
 273         Assert.assertEquals(0, TestLogShim.countLogContaining("Mouse clicked"));
 274     }
 275 
 276     @Test
 277     public void testGrab1() throws Exception {
 278         TestApplication.showInMiddleOfScreen();
 279         TestApplication.addMouseListeners();
 280         Rectangle2D r = TestApplication.getScreenBounds();
 281         final int width = (int) r.getWidth();
 282         final int height = (int) r.getHeight();
 283         final int x1 = (int) Math.round(width * 0.5);
 284         final int y1 = (int) Math.round(height * 0.5);
 285         final int x2 = (int) Math.round(width * 0.7);
 286         final int y2 = (int) Math.round(height * 0.7);
 287         final int x3 = (int) Math.round(width * 0.9);
 288         final int y3 = (int) Math.round(height * 0.9);
 289         TestApplication.movePointerTo(x1, y1);
 290         // press
 291         ui.processLine("EV_KEY BTN_LEFT 1");
 292         ui.processLine("EV_SYN");
 293         // drag to x2, y2
 294         ui.processLine("EV_REL REL_X " + (x2 - x1));
 295         ui.processLine("EV_REL REL_Y " + (y2 - y1));
 296         ui.processLine("EV_SYN");
 297         TestLogShim.waitForLog("Mouse dragged: %d, %d", x2, y2);
 298         // drag to x3, y3
 299         ui.processLine("EV_REL REL_X " + (x3 - x2));
 300         ui.processLine("EV_REL REL_Y " + (y3 - y2));
 301         ui.processLine("EV_SYN");
 302         TestLogShim.waitForLog("Mouse dragged: %d, %d", x3, y3);
 303         TestLogShim.waitForLog("Mouse exited: %d, %d", x3, y3);
 304         // drag to x2, y2
 305         ui.processLine("EV_REL REL_X " + (x2 - x3));
 306         ui.processLine("EV_REL REL_Y " + (y2 - y3));
 307         ui.processLine("EV_SYN");
 308         TestLogShim.waitForLog("Mouse dragged: %d, %d", x2, y2);
 309         TestLogShim.waitForLog("Mouse entered: %d, %d", x2, y2);
 310         // release
 311         ui.processLine("EV_KEY BTN_LEFT 0");
 312         ui.processLine("EV_SYN");
 313         TestLogShim.waitForLog("Mouse released: %d, %d", x2, y2);
 314         TestLogShim.waitForLog("Mouse clicked: %d, %d", x2, y2);
 315     }
 316 
 317     @Test
 318     public void testGrab2() throws Exception {
 319         TestApplication.showInMiddleOfScreen();
 320         TestApplication.addMouseListeners();
 321         Assume.assumeTrue(TestApplication.isMonocle());
 322         Rectangle2D r = TestApplication.getScreenBounds();
 323         final int width = (int) r.getWidth();
 324         final int height = (int) r.getHeight();
 325         final int x1 = (int) Math.round(width * 0.5);
 326         final int y1 = (int) Math.round(height * 0.5);
 327         final int x2 = (int) Math.round(width * 0.7);
 328         final int y2 = (int) Math.round(height * 0.7);
 329         final int x3 = (int) Math.round(width * 0.9);
 330         final int y3 = (int) Math.round(height * 0.9);
 331         TestApplication.movePointerTo(x1, y1);
 332         // press
 333         ui.processLine("EV_KEY BTN_LEFT 1");
 334         ui.processLine("EV_SYN");
 335         // drag to x2, y2
 336         ui.processLine("EV_REL REL_X " + (x2 - x1));
 337         ui.processLine("EV_REL REL_Y " + (y2 - y1));
 338         ui.processLine("EV_SYN");
 339         TestLogShim.waitForLog("Mouse dragged: %d, %d", x2, y2);
 340         // drag to x3, y3
 341         ui.processLine("EV_REL REL_X " + (x3 - x2));
 342         ui.processLine("EV_REL REL_Y " + (y3 - y2));
 343         ui.processLine("EV_SYN");
 344         TestLogShim.waitForLog("Mouse dragged: %d, %d", x3, y3);
 345         TestLogShim.waitForLog("Mouse exited: %d, %d", x3, y3);
 346         // release
 347         ui.processLine("EV_KEY BTN_LEFT 0");
 348         ui.processLine("EV_SYN");
 349         TestLogShim.waitForLog("Mouse released: %d, %d", x3, y3);
 350     }
 351 
 352 }