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.Before;
  35 import org.junit.Rule;
  36 import org.junit.Test;
  37 import org.junit.rules.TestName;
  38 
  39 public class TouchLagTest {
  40 
  41     private UInput ui;
  42     @Rule public TestName name = new TestName();
  43 
  44     @Before public void setUpScreen() throws Exception {
  45         TestLogShim.reset();
  46         TestLogShim.log(name.getMethodName());
  47         TestApplication.showFullScreenScene();
  48         TestApplication.addTouchListeners();
  49         TestApplication.addMouseListeners();
  50         initDevice();
  51     }
  52 
  53     public void initDevice() throws Exception {
  54         ui = new UInput();
  55         Rectangle2D r = Screen.getPrimary().getBounds();
  56         final int width = (int) r.getWidth();
  57         final int height = (int) r.getHeight();
  58         ui.processLine("OPEN");
  59         ui.processLine("EVBIT EV_SYN");
  60         ui.processLine("EVBIT EV_KEY");
  61         ui.processLine("KEYBIT BTN_TOUCH");
  62         ui.processLine("EVBIT EV_ABS");
  63         ui.processLine("ABSBIT ABS_X");
  64         ui.processLine("ABSBIT ABS_Y");
  65         ui.processLine("ABSBIT ABS_MT_POSITION_X");
  66         ui.processLine("ABSBIT ABS_MT_POSITION_Y");
  67         ui.processLine("ABSBIT ABS_MT_ORIENTATION");
  68         ui.processLine("ABSBIT ABS_MT_TOUCH_MAJOR");
  69         ui.processLine("ABSBIT ABS_MT_TOUCH_MINOR");
  70         ui.processLine("ABSMIN ABS_X 0");
  71         ui.processLine("ABSMAX ABS_X " + width);
  72         ui.processLine("ABSMIN ABS_Y 0");
  73         ui.processLine("ABSMAX ABS_Y " + height);
  74         ui.processLine("ABSMIN ABS_MT_POSITION_X 0");
  75         ui.processLine("ABSMAX ABS_MT_POSITION_X " + width);
  76         ui.processLine("ABSMIN ABS_MT_POSITION_Y 0");
  77         ui.processLine("ABSMAX ABS_MT_POSITION_Y " + height);
  78         ui.processLine("ABSMIN ABS_MT_ORIENTATION 0");
  79         ui.processLine("ABSMAX ABS_MT_ORIENTATION 1");
  80         ui.processLine("PROPBIT INPUT_PROP_POINTER");
  81         ui.processLine("PROPBIT INPUT_PROP_DIRECT");
  82         ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
  83         ui.processLine("CREATE");
  84     }
  85 
  86     @After public void destroyDevice() throws Exception {
  87         if (ui != null) {
  88             ui.waitForQuiet();
  89             try {
  90                 ui.processLine("DESTROY");
  91             } catch (RuntimeException e) { }
  92             ui.processLine("CLOSE");
  93             ui.dispose();
  94         }
  95     }
  96 
  97     /** Make sure we can process 1000 touch move events per second. We are
  98      * not required to report all these events, but must report the last one.
  99      */
 100     @Test
 101     public void testTouchLag() throws Exception {
 102         TestLogShim.reset();
 103         ui.processLine("EV_ABS ABS_X 300");
 104         ui.processLine("EV_ABS ABS_Y 300");
 105         ui.processLine("EV_KEY BTN_TOUCH 1");
 106         ui.processLine("EV_ABS ABS_MT_POSITION_X 300");
 107         ui.processLine("EV_ABS ABS_MT_POSITION_Y 300");
 108         ui.processLine("EV_SYN SYN_MT_REPORT 0");
 109         ui.processLine("EV_SYN SYN_REPORT 0");
 110         TestLogShim.waitForLogContaining("TouchPoint: PRESSED", 3000l);
 111         // pre-process move event data into a byte array. That way we don't
 112         // have to count the time it takes to convert string event descriptions
 113         // into a byte stream.
 114         byte[] b = new byte[1024];
 115         int offset = 0;
 116         int[] xs = new int[2];
 117         int[] ys = new int[2];
 118         offset = ui.writeLine(b, offset, "EV_ABS ABS_X 0");
 119         xs[0] = offset - 4;
 120         offset = ui.writeLine(b, offset, "EV_ABS ABS_Y 0");
 121         ys[0] = offset - 4;
 122         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_X 0");
 123         xs[1] = offset - 4;
 124         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_Y 0");
 125         ys[1] = offset - 4;
 126         offset = ui.writeLine(b, offset, "EV_SYN SYN_MT_REPORT 0");
 127         offset = ui.writeLine(b, offset, "EV_SYN SYN_REPORT 0");
 128         int moveLength = offset;
 129         // Spam JavaFX with touch move events
 130         long startTime = System.currentTimeMillis();
 131         for (int y = 300; y < 310; y++) {
 132             for (int x = 300; x > 150; x--) {
 133                 ui.writeValue(b, xs[0], x);
 134                 ui.writeValue(b, xs[1], x);
 135                 ui.writeValue(b, ys[0], y);
 136                 ui.writeValue(b, ys[1], y);
 137                 ui.write(b, 0, moveLength);
 138             }
 139             for (int x = 150; x < 300; x++) {
 140                 ui.writeValue(b, xs[0], x);
 141                 ui.writeValue(b, xs[1], x);
 142                 ui.writeValue(b, ys[0], y);
 143                 ui.writeValue(b, ys[1], y);
 144                 ui.write(b, 0, moveLength);
 145             }
 146         }
 147         long t = System.currentTimeMillis() - startTime;
 148         // Make sure events could be sent in the required time
 149         Assert.assertTrue("Took " + t + "ms to send 3000 events",
 150                           t < (long) (3000l * TestApplication.getTimeScale()));
 151         TestLogShim.log("Sent 3000 events in " + t + "ms");
 152         // move to 400, 410
 153         ui.writeValue(b, xs[0], 400);
 154         ui.writeValue(b, xs[1], 400);
 155         ui.writeValue(b, ys[0], 410);
 156         ui.writeValue(b, ys[1], 410);
 157         ui.write(b, 0, moveLength);
 158         // release 
 159         ui.processLine("EV_KEY BTN_TOUCH 0");
 160         ui.processLine("EV_SYN SYN_MT_REPORT 0");
 161         ui.processLine("EV_SYN SYN_REPORT 0");
 162         // Make sure events could be delivered in the required time
 163         TestLogShim.waitForLog("Touch moved: 400, 410", 3000l - t);
 164     }
 165 
 166     /** Make sure we can process 1000 multitouch move events per second. We are
 167      * not required to report all these events, but must report the last one.
 168      */
 169     @Test
 170     public void testMultitouchLag() throws Exception {
 171         TestLogShim.reset();
 172         ui.processLine("EV_ABS ABS_X 300");
 173         ui.processLine("EV_ABS ABS_Y 300");
 174         ui.processLine("EV_KEY BTN_TOUCH 1");
 175         ui.processLine("EV_ABS ABS_MT_POSITION_X 300");
 176         ui.processLine("EV_ABS ABS_MT_POSITION_Y 300");
 177         ui.processLine("EV_SYN SYN_MT_REPORT 0");
 178         ui.processLine("EV_SYN SYN_REPORT 0");
 179         TestLogShim.waitForLogContaining("TouchPoint: PRESSED", 3000);
 180         // pre-process move event data into a byte array. That way we don't
 181         // have to count the time it takes to convert string event descriptions
 182         // into a byte stream.
 183         byte[] b = new byte[1024];
 184         int offset = 0;
 185         int baseX, baseY;
 186         int[] xs = new int[2];
 187         int[] ys = new int[2];
 188         offset = ui.writeLine(b, offset, "EV_ABS ABS_X 0");
 189         baseX = offset - 4;
 190         offset = ui.writeLine(b, offset, "EV_ABS ABS_Y 0");
 191         baseY = offset - 4;
 192         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_X 0");
 193         xs[0] = offset - 4;
 194         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_Y 0");
 195         ys[0] = offset - 4;
 196         offset = ui.writeLine(b, offset, "EV_SYN SYN_MT_REPORT 0");
 197         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_X 0");
 198         xs[1] = offset - 4;
 199         offset = ui.writeLine(b, offset, "EV_ABS ABS_MT_POSITION_Y 0");
 200         ys[1] = offset - 4;
 201         offset = ui.writeLine(b, offset, "EV_SYN SYN_MT_REPORT 0");
 202         offset = ui.writeLine(b, offset, "EV_SYN SYN_REPORT 0");
 203         int moveLength = offset;
 204         // Spam JavaFX with touch move events
 205         long startTime = System.currentTimeMillis();
 206         for (int y = 300; y < 310; y++) {
 207             for (int x = 300; x > 150; x--) {
 208                 ui.writeValue(b, baseX, x);
 209                 ui.writeValue(b, baseY, y);
 210                 ui.writeValue(b, xs[0], x);
 211                 ui.writeValue(b, xs[1], (x * 3) / 2);
 212                 ui.writeValue(b, ys[0], y);
 213                 ui.writeValue(b, ys[1], (y * 2) / 3);
 214                 ui.write(b, 0, moveLength);
 215             }
 216             for (int x = 150; x < 300; x++) {
 217                 ui.writeValue(b, baseX, x);
 218                 ui.writeValue(b, baseY, y);
 219                 ui.writeValue(b, xs[0], x);
 220                 ui.writeValue(b, xs[1], (x * 3) / 2);
 221                 ui.writeValue(b, ys[0], y);
 222                 ui.writeValue(b, ys[1], (y * 2) / 3);
 223                 ui.write(b, 0, moveLength);
 224             }
 225         }
 226         long t = System.currentTimeMillis() - startTime;
 227         // Make sure events could be sent in the required time
 228         Assert.assertTrue("Took " + t + "ms to send 3000 events",
 229                           t < (long) (3000l * TestApplication.getTimeScale()));
 230         TestLogShim.log("Sent 3000 events in " + t + "ms");
 231         // move to (400, 410), (350, 360);
 232         ui.writeValue(b, baseX, 400);
 233         ui.writeValue(b, baseY, 410);
 234         ui.writeValue(b, xs[0], 400);
 235         ui.writeValue(b, ys[0], 410);
 236         ui.writeValue(b, xs[1], 350);
 237         ui.writeValue(b, ys[1], 360);
 238         ui.write(b, 0, moveLength);
 239         // release one finger at 350, 360
 240         ui.processLine("EV_ABS ABS_X 400");
 241         ui.processLine("EV_ABS ABS_Y 410");
 242         ui.processLine("EV_ABS ABS_MT_POSITION_X 400");
 243         ui.processLine("EV_ABS ABS_MT_POSITION_Y 410");
 244         ui.processLine("EV_SYN SYN_MT_REPORT 0");
 245         ui.processLine("EV_SYN SYN_REPORT 0");
 246         // release the other finger
 247         ui.processLine("EV_ABS ABS_X 400");
 248         ui.processLine("EV_ABS ABS_Y 410");
 249         ui.processLine("EV_KEY BTN_TOUCH 0");
 250         ui.processLine("EV_SYN SYN_MT_REPORT 0");
 251         ui.processLine("EV_SYN SYN_REPORT 0");
 252         // Make sure events could be delivered in the required time
 253         TestLogShim.waitForLog("Touch released: 400, 410", 3000l - t);
 254     }
 255 }