changeset 7995:1d08d9490df0 8u40-b05

RT-38393 [Monocle] Mouse Events stop coming on embedded Fixes in modules/graphics/src/main/java/com/sun/glass/ui/monocle/ contributed by fheidric
author Daniel Blaukopf <daniel.blaukopf@oracle.com>
date Mon, 08 Sep 2014 10:51:13 +0300
parents e9b4c69a744f
children c1f4fb709cde b2acb41b44b1 6e4d117f2c7a
files modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxInputDeviceRegistry.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxStatefulMultiTouchProcessor.java tests/system/src/test/java/com/sun/glass/ui/monocle/MultiTouch2Test.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice1.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice2.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice3.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice4.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDeviceBase.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/TestTouchDevices.java
diffstat 9 files changed, 341 insertions(+), 191 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxInputDeviceRegistry.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxInputDeviceRegistry.java	Mon Sep 08 10:51:13 2014 +0300
@@ -96,7 +96,7 @@
         if (processor == null) {
             return null;
         } else {
-            device.setInputProcessor(createInputProcessor(device));
+            device.setInputProcessor(processor);
             Thread thread = new Thread(device);
             thread.setName(name);
             thread.setDaemon(true);
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxStatefulMultiTouchProcessor.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/LinuxStatefulMultiTouchProcessor.java	Mon Sep 08 10:51:13 2014 +0300
@@ -51,6 +51,9 @@
         LinuxEventBuffer buffer = device.getBuffer();
         int x = COORD_UNDEFINED;
         int y = COORD_UNDEFINED;
+        // Some devices send EV_KEY BTN_TOUCH 0 to notify that all
+        // touch points are released.
+        boolean allPointsReleased = false;
         while (buffer.hasNextEvent()) {
             switch (buffer.getEventType()) {
                 case LinuxInput.EV_ABS: {
@@ -96,6 +99,19 @@
                     }
                     break;
                 }
+
+                case LinuxInput.EV_KEY:
+                    switch (buffer.getEventCode()) {
+                        case LinuxInput.BTN_TOUCH:
+                            if (buffer.getEventValue() == 0) {
+                                allPointsReleased = true;
+                            }
+                            break;
+
+                    }
+                    break;
+
+
                 case LinuxInput.EV_SYN:
                     switch (buffer.getEventCode()) {
                         case LinuxInput.SYN_MT_REPORT: {
@@ -118,9 +134,12 @@
                                 // but no SYN_MT_REPORT event. Assign these
                                 // coordinates to the current ID.
                                 updatePoint(x, y);
+                            } else if (allPointsReleased) {
+                                state.clear();
                             }
                             pipeline.pushState(state);
                             x = y = COORD_UNDEFINED;
+                            allPointsReleased = false;
                             break;
                         default: // ignore
                     }
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/MultiTouch2Test.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/MultiTouch2Test.java	Mon Sep 08 10:51:13 2014 +0300
@@ -167,6 +167,13 @@
         device.sync();
         TestLog.waitForLogContaining("Touch released: %d, %d", x2, y2);
         TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x2, y2);
+        TestLog.reset();
+        // tap to cancel inertia
+        int p3 = device.addPoint(x1, y1);
+        device.sync();
+        device.removePoint(p3);
+        device.sync();
+        TestLog.waitForLog("Mouse clicked: %d, %d", x1, y1);
     }
 
     /**
@@ -219,4 +226,53 @@
         TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x2, y2);
     }
 
+    @Test
+    public void twoFingerDragSingleFingerTap() throws Exception {
+        final int x1 = (int) Math.round(width * 0.5f);
+        final int y1 = (int) Math.round(height * 0.5f);
+        final int x2 = (int) Math.round(width * 0.75f);
+        final int y2 = (int) Math.round(height * 0.75f);
+        final int dx = device.getTapRadius();
+        final int dy = device.getTapRadius();
+        // first finger
+        int p1 = device.addPoint(x1, y1);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: PRESSED %d, %d", x1, y1);
+        // add a second finger
+        int p2 = device.addPoint(x2, y2);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: STATIONARY %d, %d", x1, y1);
+        TestLog.waitForLogContaining("TouchPoint: PRESSED %d, %d", x2, y2);
+        // drag both fingers
+        device.setPoint(p1, x1 + dx, y1);
+        device.setPoint(p2, x2 + dx, y2);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: MOVED %d, %d", x1 + dx, y1);
+        TestLog.waitForLogContaining("TouchPoint: MOVED %d, %d", x2 + dx, y2);
+
+        // release first finger
+        TestLog.reset();
+        device.removePoint(p1);
+        device.sync();
+        TestLog.waitForLogContaining("Touch released: %d, %d", x1 + dx, y1);
+        TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x1 + dx, y1);
+        TestLog.waitForLogContaining("TouchPoint: STATIONARY %d, %d", x2 + dx, y2);
+        // release second finger
+        TestLog.reset();
+        device.removePoint(p2);
+        device.sync();
+        TestLog.waitForLogContaining("Touch released: %d, %d", x2 + dx, y2);
+        TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x2 + dx, y2);
+
+        // tap
+        int p3 = device.addPoint(x1, y1 + dy);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: PRESSED %d, %d", x1, y1 + dy);
+        // release
+        device.removePoint(p3);
+        device.sync();
+        TestLog.waitForLogContaining("TouchPoint: RELEASED %d, %d", x1, y1 + dy);
+    }
+
+
 }
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice1.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice1.java	Mon Sep 08 10:51:13 2014 +0300
@@ -25,101 +25,15 @@
 
 package com.sun.glass.ui.monocle.input.devices;
 
-import com.sun.glass.ui.monocle.TestApplication;
-import com.sun.glass.ui.monocle.TestLog;
-import com.sun.glass.ui.monocle.UInput;
-import org.junit.Assume;
-
 /** The touch screen used in the Freescale i.MX6Q Sabre Device Platform,
  * extrapolated to five touch points. There is some guesswork here as to
  * whether the screen always resends stationary points. This class assumes that
  * it does not resend stationary points.
  */
-public class EGalaxMultiTouchDevice1 extends TestTouchDevice {
+public class EGalaxMultiTouchDevice1 extends EGalaxMultiTouchDeviceBase {
 
     public EGalaxMultiTouchDevice1() {
-        super(5);
-    }
-
-    @Override
-    public void create() {
-        // this device fails multitouch tests on Lens
-        Assume.assumeTrue(TestApplication.isMonocle());
-        ui = new UInput();
-        ui.processLine("OPEN");
-        ui.processLine("EVBIT EV_SYN");
-        ui.processLine("ABSBIT ABS_MT_TRACKING_ID");
-        ui.processLine("ABSBIT ABS_MT_POSITION_X");
-        ui.processLine("ABSBIT ABS_MT_POSITION_Y");
-        ui.processLine("ABSBIT ABS_MT_TOUCH_MAJOR");
-        ui.processLine("ABSMIN ABS_MT_TRACKING_ID 0");
-        ui.processLine("ABSMAX ABS_MT_TRACKING_ID 5");
-        ui.processLine("ABSMIN ABS_MT_POSITION_X 0");
-        ui.processLine("ABSMAX ABS_MT_POSITION_X 32767");
-        ui.processLine("ABSMIN ABS_MT_POSITION_Y 0");
-        ui.processLine("ABSMAX ABS_MT_POSITION_Y 32767");
-        ui.processLine("ABSMIN ABS_MT_TOUCH_MAJOR 0");
-        ui.processLine("ABSMAX ABS_MT_TOUCH_MAJOR 255");
-        ui.processLine("PROPBIT INPUT_PROP_POINTER");
-        ui.processLine("PROPBIT INPUT_PROP_DIRECT");
-        ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
-        ui.processLine("CREATE");
-        setAbsScale(32768, 32768);
-    }
-
-    @Override
-    public int addPoint(double x, double y) {
-        int p = super.addPoint(x, y);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-        return p;
-    }
-
-    @Override
-    public void removePoint(int p) {
-        super.removePoint(p);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 0");
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-    }
-
-    @Override
-    public void setPoint(int p, double x, double y) {
-        super.setPoint(p, x, y);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-    }
-
-    @Override
-    public void setAndRemovePoint(int p, double x, double y) {
-        // This device doesn't send move and release at the same time
-        removePoint(p);
-    }
-
-    @Override
-    public void sync() {
-        super.sync();
-    }
-
-    @Override
-    public void resendStateAndSync() {
-        TestLog.log("TestTouchDevice: sync");
-        for (int p = 0; p < points.length; p++) {
-            if (points[p]) {
-                ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-                ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-                ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-                ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-                ui.processLine("EV_SYN SYN_MT_REPORT 0");
-            }
-        }
-        sync();
+        super(false, false);
     }
 
 }
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice2.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice2.java	Mon Sep 08 10:51:13 2014 +0300
@@ -25,115 +25,15 @@
 
 package com.sun.glass.ui.monocle.input.devices;
 
-import com.sun.glass.ui.monocle.TestLog;
-import com.sun.glass.ui.monocle.UInput;
-
-import java.util.HashSet;
-import java.util.Set;
-
 /** The touch screen used in the Freescale i.MX6Q Sabre Device Platform,
  * extrapolated to five touch points. There is some guesswork here as to
  * whether the screen always resends stationary points. This class assumes that
  * it resends stationary points.
  */
-public class EGalaxMultiTouchDevice2 extends TestTouchDevice {
-
-    private Set<Integer> modifiedPoints = new HashSet<>();
+public class EGalaxMultiTouchDevice2 extends EGalaxMultiTouchDeviceBase {
 
     public EGalaxMultiTouchDevice2() {
-        super(5);
-    }
-
-    @Override
-    public void create() {
-        ui = new UInput();
-        ui.processLine("OPEN");
-        ui.processLine("EVBIT EV_SYN");
-        ui.processLine("ABSBIT ABS_MT_TRACKING_ID");
-        ui.processLine("ABSBIT ABS_MT_POSITION_X");
-        ui.processLine("ABSBIT ABS_MT_POSITION_Y");
-        ui.processLine("ABSBIT ABS_MT_TOUCH_MAJOR");
-        ui.processLine("ABSMIN ABS_MT_TRACKING_ID 0");
-        ui.processLine("ABSMAX ABS_MT_TRACKING_ID 5");
-        ui.processLine("ABSMIN ABS_MT_POSITION_X 0");
-        ui.processLine("ABSMAX ABS_MT_POSITION_X 32767");
-        ui.processLine("ABSMIN ABS_MT_POSITION_Y 0");
-        ui.processLine("ABSMAX ABS_MT_POSITION_Y 32767");
-        ui.processLine("ABSMIN ABS_MT_TOUCH_MAJOR 0");
-        ui.processLine("ABSMAX ABS_MT_TOUCH_MAJOR 255");
-        ui.processLine("PROPBIT INPUT_PROP_POINTER");
-        ui.processLine("PROPBIT INPUT_PROP_DIRECT");
-        ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
-        ui.processLine("CREATE");
-        setAbsScale(32768, 32768);
-    }
-
-    @Override
-    public int addPoint(double x, double y) {
-        int p = super.addPoint(x, y);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-        modifiedPoints.add(p);
-        return p;
-    }
-
-    @Override
-    public void removePoint(int p) {
-        super.removePoint(p);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 0");
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-    }
-
-    @Override
-    public void setPoint(int p, double x, double y) {
-        super.setPoint(p, x, y);
-        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-        ui.processLine("EV_SYN SYN_MT_REPORT 0");
-        modifiedPoints.add(p);
-    }
-
-    @Override
-    public void setAndRemovePoint(int p, double x, double y) {
-        // This device doesn't send move and release at the same time
-        removePoint(p);
-    }
-
-    @Override
-    public void sync() {
-        for (int p = 0; p < points.length; p++) {
-            if (points[p] && !modifiedPoints.contains(p)) {
-                ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-                ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-                ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-                ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-                ui.processLine("EV_SYN SYN_MT_REPORT 0");
-            }
-        }
-        modifiedPoints.clear();
-        super.sync();
-    }
-
-    @Override
-    public void resendStateAndSync() {
-        TestLog.log("TestTouchDevice: sync");
-        for (int p = 0; p < points.length; p++) {
-            if (points[p]) {
-                ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
-                ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
-                ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
-                ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
-                ui.processLine("EV_SYN SYN_MT_REPORT 0");
-            }
-        }
-        modifiedPoints.clear();
-        super.sync();
+        super(true, false);
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice3.java	Mon Sep 08 10:51:13 2014 +0300
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+/** The touch screen used in the Freescale i.MX6Q Sabre Device Platform,
+ * extrapolated to five touch points. There is some guesswork here as to
+ * whether the screen always resends stationary points. This class assumes that
+ * it does not resend stationary points.
+ * On release of the last point this device does not send a tracking ID.
+ * Instead it sends:
+ *
+ * EV_ABS ABS_MT_TOUCH_MAJOR 0
+ * EV_KEY BTN_TOUCH 0
+ * EV_SYN SYN_MT_REPORT 0
+ */
+public class EGalaxMultiTouchDevice3 extends EGalaxMultiTouchDeviceBase {
+
+    public EGalaxMultiTouchDevice3() {
+        super(false, true);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDevice4.java	Mon Sep 08 10:51:13 2014 +0300
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+/** The touch screen used in the Freescale i.MX6Q Sabre Device Platform,
+ * extrapolated to five touch points. There is some guesswork here as to
+ * whether the screen always resends stationary points. This class assumes that
+ * it resends stationary points.
+ * On release of the last point this device does not send a tracking ID.
+ * Instead it sends:
+ *
+ * EV_ABS ABS_MT_TOUCH_MAJOR 0
+ * EV_KEY BTN_TOUCH 0
+ * EV_SYN SYN_MT_REPORT 0
+ */
+public class EGalaxMultiTouchDevice4 extends EGalaxMultiTouchDeviceBase {
+
+    public EGalaxMultiTouchDevice4() {
+        super(true, true);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/EGalaxMultiTouchDeviceBase.java	Mon Sep 08 10:51:13 2014 +0300
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.glass.ui.monocle.input.devices;
+
+import com.sun.glass.ui.monocle.TestApplication;
+import com.sun.glass.ui.monocle.TestLog;
+import com.sun.glass.ui.monocle.UInput;
+import org.junit.Assume;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/** The touch screen used in the Freescale i.MX6Q Sabre Device Platform,
+ * extrapolated to five touch points. There is some guesswork here as to
+ * whether the screen always resends stationary points and what happens when
+ * all fingers are removed from the screen. Also, on some devices on release
+ * of the last point no tracking ID is sent. Instead we get the following event
+ * sequence:
+ *
+ *   EV_ABS ABS_MT_TOUCH_MAJOR 0
+ *   EV_KEY BTN_TOUCH 0
+ *   EV_SYN SYN_MT_REPORT 0
+ *
+ * These questions are resolved in different ways in subclasses.
+ */
+public class EGalaxMultiTouchDeviceBase extends TestTouchDevice {
+
+    protected final boolean resendStationaryPoints;
+    protected final boolean sendBtnTouch;
+    private Set<Integer> modifiedPoints = new HashSet<>();
+
+    public EGalaxMultiTouchDeviceBase(boolean resendStationaryPoints, boolean sendBtnTouch) {
+        super(5);
+        this.resendStationaryPoints = resendStationaryPoints;
+        this.sendBtnTouch = sendBtnTouch;
+    }
+
+    @Override
+    public void create() {
+        // this device fails multitouch tests on Lens
+        Assume.assumeTrue(TestApplication.isMonocle());
+        ui = new UInput();
+        ui.processLine("OPEN");
+        ui.processLine("EVBIT EV_SYN");
+        if (sendBtnTouch) {
+            ui.processLine("EVBIT EV_KEY");
+            ui.processLine("KEYBIT BTN_TOUCH");
+        }
+        ui.processLine("ABSBIT ABS_MT_TRACKING_ID");
+        ui.processLine("ABSBIT ABS_MT_POSITION_X");
+        ui.processLine("ABSBIT ABS_MT_POSITION_Y");
+        ui.processLine("ABSBIT ABS_MT_TOUCH_MAJOR");
+        ui.processLine("ABSMIN ABS_MT_TRACKING_ID 0");
+        ui.processLine("ABSMAX ABS_MT_TRACKING_ID 5");
+        ui.processLine("ABSMIN ABS_MT_POSITION_X 0");
+        ui.processLine("ABSMAX ABS_MT_POSITION_X 32767");
+        ui.processLine("ABSMIN ABS_MT_POSITION_Y 0");
+        ui.processLine("ABSMAX ABS_MT_POSITION_Y 32767");
+        ui.processLine("ABSMIN ABS_MT_TOUCH_MAJOR 0");
+        ui.processLine("ABSMAX ABS_MT_TOUCH_MAJOR 255");
+        ui.processLine("PROPBIT INPUT_PROP_POINTER");
+        ui.processLine("PROPBIT INPUT_PROP_DIRECT");
+        ui.processLine("PROPERTY ID_INPUT_TOUCHSCREEN 1");
+        ui.processLine("CREATE");
+        setAbsScale(32768, 32768);
+    }
+
+    @Override
+    public int addPoint(double x, double y) {
+        int p = super.addPoint(x, y);
+        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
+        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
+        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
+        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
+        ui.processLine("EV_SYN SYN_MT_REPORT 0");
+        modifiedPoints.add(p);
+        if (sendBtnTouch && pressedPoints == 1) {
+            ui.processLine("EV_KEY BTN_TOUCH 1");
+        }
+        return p;
+    }
+
+    @Override
+    public void removePoint(int p) {
+        super.removePoint(p);
+        if (sendBtnTouch && pressedPoints == 0) {
+            ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 0");
+            ui.processLine("EV_KEY BTN_TOUCH 0");
+        } else {
+            ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
+            ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 0");
+            ui.processLine("EV_SYN SYN_MT_REPORT 0");
+        }
+    }
+
+    @Override
+    public void setPoint(int p, double x, double y) {
+        super.setPoint(p, x, y);
+        ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
+        ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
+        ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
+        ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
+        ui.processLine("EV_SYN SYN_MT_REPORT 0");
+        modifiedPoints.add(p);
+    }
+
+    @Override
+    public void setAndRemovePoint(int p, double x, double y) {
+        // This device doesn't send move and release at the same time
+        removePoint(p);
+    }
+
+    @Override
+    public void sync() {
+        if (resendStationaryPoints) {
+            for (int p = 0; p < points.length; p++) {
+                if (points[p] && !modifiedPoints.contains(p)) {
+                    ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
+                    ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
+                    ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
+                    ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
+                    ui.processLine("EV_SYN SYN_MT_REPORT 0");
+                }
+            }
+        }
+        modifiedPoints.clear();
+        super.sync();
+    }
+
+    @Override
+    public void resendStateAndSync() {
+        TestLog.log("TestTouchDevice: sync");
+        for (int p = 0; p < points.length; p++) {
+            if (points[p]) {
+                ui.processLine("EV_ABS ABS_MT_TRACKING_ID " + p);
+                ui.processLine("EV_ABS ABS_MT_TOUCH_MAJOR 1");
+                ui.processLine("EV_ABS ABS_MT_POSITION_X " + transformedXs[p]);
+                ui.processLine("EV_ABS ABS_MT_POSITION_Y " + transformedYs[p]);
+                ui.processLine("EV_SYN SYN_MT_REPORT 0");
+            }
+        }
+        modifiedPoints.clear();
+        sync();
+    }
+
+}
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/TestTouchDevices.java	Fri Sep 05 10:02:29 2014 -0700
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/devices/TestTouchDevices.java	Mon Sep 08 10:51:13 2014 +0300
@@ -56,6 +56,8 @@
                 new EGalaxSingleTouchDevice2(),
                 new EGalaxMultiTouchDevice1(),
                 new EGalaxMultiTouchDevice2(),
+                new EGalaxMultiTouchDevice3(),
+                new EGalaxMultiTouchDevice4(),
                 new TouchRevolutionFusionDevice(),
                 new NTrigDevice(),
                 new SamsungLMS700KF07004Device(),