changeset 6865:37b4ef736543

RT-36808 [Monocle] LinuxMouseProcessor sends duplicate state updates Reviewed-by: kselle
author Daniel Blaukopf <daniel.blaukopf@oracle.com>
date Wed, 23 Apr 2014 20:30:40 +0300
parents cc9163819cf8
children 8398a33b81f8
files modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxMouseProcessor.java tests/system/src/test/java/com/sun/glass/ui/monocle/input/SimpleMouseTest.java
diffstat 2 files changed, 145 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxMouseProcessor.java	Wed Apr 23 10:48:53 2014 -0600
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxMouseProcessor.java	Wed Apr 23 20:30:40 2014 +0300
@@ -34,14 +34,18 @@
     private MouseInput mouse = MouseInput.getInstance();
     private MouseState previousState = new MouseState();
     private MouseState state = new MouseState();
-    private boolean processedFirstEvent;
+    /**
+     * does previousState hold an update that has not yet been sent to
+     * MouseInput?
+     */
+    private boolean hasPendingState;
 
     @Override
     public void processEvents(LinuxInputDevice device) {
         LinuxEventBuffer buffer = device.getBuffer();
         mouse.getState(previousState);
         mouse.getState(state);
-        processedFirstEvent = false;
+        hasPendingState = false;
         while (buffer.hasNextEvent()) {
             switch (buffer.getEventType()) {
                 case Input.EV_REL:
@@ -95,26 +99,24 @@
             }
             buffer.nextEvent();
         }
-        mouse.setState(previousState, false);
+        if (hasPendingState) {
+            mouse.setState(previousState, false);
+        }
     }
 
     private void sendEvent() {
-        if (!processedFirstEvent) {
-            mouse.getState(previousState);
-            if (state.canBeFoldedWith(previousState)) {
-                processedFirstEvent = true;
-            } else {
-                mouse.setState(state, false);
+        if (state.canBeFoldedWith(previousState)) {
+            // fold together MouseStates that differ only in their coordinates
+            hasPendingState = true;
+        } else {
+            // the events are different.
+            if (hasPendingState) {
+                // send and clear the pending state
+                mouse.setState(previousState, false);
+                hasPendingState = false;
             }
-        }
-        if (processedFirstEvent) {
-            // fold together MouseStates that differ only in their coordinates
-            if (!state.canBeFoldedWith(previousState)) {
-                // the events are different. Send "previousState".
-                mouse.setState(previousState, false);
-            }
-        } else {
-            processedFirstEvent = true;
+            // send this event
+            mouse.setState(state, false);
         }
         state.copyTo(previousState);
     }
--- a/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SimpleMouseTest.java	Wed Apr 23 10:48:53 2014 -0600
+++ b/tests/system/src/test/java/com/sun/glass/ui/monocle/input/SimpleMouseTest.java	Wed Apr 23 20:30:40 2014 +0300
@@ -25,7 +25,11 @@
 
 package com.sun.glass.ui.monocle.input;
 
+import javafx.geometry.Rectangle2D;
+import javafx.stage.Screen;
 import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -112,4 +116,125 @@
         TestLog.waitForLog("Scroll: -1");
     }
 
+    @Test
+    public void testClickLeft() throws Exception {
+        ui.processLine("EV_KEY BTN_LEFT 1");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        ui.processLine("EV_KEY BTN_LEFT 0");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        TestLog.waitForLogContaining("Mouse pressed: 300, 300");
+        TestLog.waitForLogContaining("Mouse released: 300, 300");
+        TestLog.waitForLogContaining("Mouse clicked: 300, 300");
+    }
+
+    @Test
+    public void testClickRight() throws Exception {
+        ui.processLine("EV_KEY BTN_RIGHT 1");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        ui.processLine("EV_KEY BTN_RIGHT 0");
+        ui.processLine("EV_SYN SYN_REPORT 0");
+        TestLog.waitForLogContaining("Mouse pressed: 300, 300");
+        TestLog.waitForLogContaining("Mouse released: 300, 300");
+        TestLog.waitForLogContaining("Mouse clicked: 300, 300");
+    }
+
+    @Test
+    public void testDragLookahead() throws Exception {
+        Assume.assumeTrue(TestApplication.isMonocle());
+        TestApplication.showFullScreenScene();
+        TestApplication.addMouseListeners();
+        TestLog.reset();
+        Rectangle2D r = Screen.getPrimary().getBounds();
+        final int width = (int) r.getWidth();
+        final int height = (int) r.getHeight();
+        final int x1 = (int) Math.round(width * 0.1);
+        final int y1 = (int) Math.round(height * 0.1);
+        final int delta = (int) Math.min(width / 2.0, height / 2.0);
+        final int x2 = x1 + delta;
+        final int y2 = y1 + delta;
+        final int x3 = (int) Math.round(width * 0.9);
+        final int y3 = (int) Math.round(height * 0.9);
+        // Move the mouse to 0, 0
+        ui.processLine("EV_REL REL_X " + -width);
+        ui.processLine("EV_REL REL_Y " + -height);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: 0, 0");
+        // Move to x1, y1
+        ui.processLine("EV_REL REL_X " + x1);
+        ui.processLine("EV_REL REL_Y " + y1);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: %d, %d", x1, y1);
+        // Push events while on the event thread, making sure that events
+        // will be buffered up and enabling filtering to take place
+        TestRunnable.invokeAndWait(() -> {
+            ui.processLine("EV_KEY BTN_LEFT 1");
+            ui.processLine("EV_SYN");
+            for (int i = 0; i < delta; i++) {
+                ui.processLine("EV_REL REL_X 1");
+                ui.processLine("EV_REL REL_Y 1");
+                ui.processLine("EV_SYN");
+            }
+            ui.processLine("EV_REL REL_X " + (x3 - x2));
+            ui.processLine("EV_REL REL_Y " + (y3 - y2));
+            ui.processLine("EV_SYN");
+            ui.processLine("EV_KEY BTN_LEFT 0");
+            ui.processLine("EV_SYN");
+        });
+        // Check that the initial point reported is correct
+        TestLog.waitForLog("Mouse pressed: %d, %d", x1, y1);
+        // Check that the final point reported is correct
+        TestLog.waitForLog("Mouse released: %d, %d", x3, y3);
+        TestLog.waitForLog("Mouse dragged: %d, %d", x3, y3);
+        // Check that moves in between were filtered
+        Assert.assertTrue(TestLog.countLogContaining("Mouse dragged") <= (x2 - x1) / 10);
+    }
+
+    @Test
+    public void testMoveLookahead() throws Exception {
+        Assume.assumeTrue(TestApplication.isMonocle());
+        TestApplication.showFullScreenScene();
+        TestApplication.addMouseListeners();
+        TestLog.reset();
+        Rectangle2D r = Screen.getPrimary().getBounds();
+        final int width = (int) r.getWidth();
+        final int height = (int) r.getHeight();
+        final int x1 = (int) Math.round(width * 0.1);
+        final int y1 = (int) Math.round(height * 0.1);
+        final int delta = (int) Math.min(width / 2.0, height / 2.0);
+        final int x2 = x1 + delta;
+        final int y2 = y1 + delta;
+        final int x3 = (int) Math.round(width * 0.9);
+        final int y3 = (int) Math.round(height * 0.9);
+        // Move the mouse to 0, 0
+        ui.processLine("EV_REL REL_X " + -width);
+        ui.processLine("EV_REL REL_Y " + -height);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: 0, 0");
+        // Move to x1, y1
+        ui.processLine("EV_REL REL_X " + x1);
+        ui.processLine("EV_REL REL_Y " + y1);
+        ui.processLine("EV_SYN");
+        TestLog.waitForLog("Mouse moved: %d, %d", x1, y1);
+        // Push events while on the event thread, making sure that events
+        // will be buffered up and enabling filtering to take place
+        TestRunnable.invokeAndWait(() -> {
+            for (int i = 0; i < delta; i++) {
+                ui.processLine("EV_REL REL_X 1");
+                ui.processLine("EV_REL REL_Y 1");
+                ui.processLine("EV_SYN");
+            }
+            ui.processLine("EV_REL REL_X " + (x3 - x2));
+            ui.processLine("EV_REL REL_Y " + (y3 - y2));
+            ui.processLine("EV_SYN");
+        });
+        // Check that the final point reported is correct
+        TestLog.waitForLog("Mouse moved: %d, %d", x3, y3);
+        // Check that moves in between were filtered
+        Assert.assertTrue(TestLog.countLogContaining("Mouse moved") <= (x2 - x1) / 10);
+        // Check that we didn't get any other events
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse pressed"));
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse released"));
+        Assert.assertEquals(0, TestLog.countLogContaining("Mouse clicked"));
+    }
+
 }