changeset 6081:e13fa6df0ab3

RT-35247 [Monocle] Integrate with input device synthesizer
author Daniel Blaukopf <daniel.blaukopf@oracle.com>
date Tue, 14 Jan 2014 17:17:35 +0200
parents 2910f4be0016
children 4a567170426a
files modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleRobot.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/headless/HeadlessPlatform.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchInput.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchLookahead.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchState.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchStates.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/AbsoluteInputCapabilities.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDevice.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDeviceRegistry.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxPlatform.java modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxTouchProcessor.java
diffstat 12 files changed, 222 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleApplication.java	Tue Jan 14 17:17:35 2014 +0200
@@ -220,8 +220,7 @@
 
     @Override
     public Robot createRobot() {
-        Thread.dumpStack();
-        throw new UnsupportedOperationException();
+        return new MonocleRobot();
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/MonocleRobot.java	Tue Jan 14 17:17:35 2014 +0200
@@ -0,0 +1,124 @@
+/*
+ * 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;
+
+import com.sun.glass.events.MouseEvent;
+import com.sun.glass.ui.Pixels;
+import com.sun.glass.ui.Robot;
+import com.sun.glass.ui.monocle.input.MouseInput;
+import com.sun.glass.ui.monocle.input.MouseState;
+
+public class MonocleRobot extends Robot {
+    @Override
+    protected void _create() {
+    }
+
+    @Override
+    protected void _destroy() {
+    }
+
+    @Override
+    protected void _keyPress(int code) {
+        // TODO: robot key press
+    }
+
+    @Override
+    protected void _keyRelease(int code) {
+        // TODO: robot key release
+    }
+
+    @Override
+    protected void _mouseMove(int x, int y) {
+        MouseState state = new MouseState();
+        MouseInput.getInstance().getState(state);
+        state.setX(x);
+        state.setY(y);
+        MouseInput.getInstance().setState(state, false);
+    }
+
+    @Override
+    protected void _mousePress(int buttons) {
+        MouseState state = new MouseState();
+        MouseInput.getInstance().getState(state);
+        if ((buttons & MOUSE_LEFT_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_LEFT);
+        }
+        if ((buttons & MOUSE_MIDDLE_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_OTHER);
+        }
+        if ((buttons & MOUSE_RIGHT_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_RIGHT);
+        }
+        MouseInput.getInstance().setState(state, false);
+    }
+
+    @Override
+    protected void _mouseRelease(int buttons) {
+        MouseState state = new MouseState();
+        MouseInput.getInstance().getState(state);
+        if ((buttons & MOUSE_LEFT_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_LEFT);
+        }
+        if ((buttons & MOUSE_MIDDLE_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_OTHER);
+        }
+        if ((buttons & MOUSE_RIGHT_BTN) != 0) {
+            state.pressButton(MouseEvent.BUTTON_RIGHT);
+        }
+        MouseInput.getInstance().setState(state, false);
+    }
+
+    @Override
+    protected void _mouseWheel(int wheelAmt) {
+        // TODO: Mouse wheel robot
+    }
+
+    @Override
+    protected int _getMouseX() {
+        MouseState state = new MouseState();
+        MouseInput.getInstance().getState(state);
+        return state.getX();
+    }
+
+    @Override
+    protected int _getMouseY() {
+        MouseState state = new MouseState();
+        MouseInput.getInstance().getState(state);
+        return state.getY();
+    }
+
+    @Override
+    protected int _getPixelColor(int x, int y) {
+        return 0;
+    }
+
+    @Override
+    protected Pixels _getScreenCapture(int x, int y, int width, int height,
+                                       boolean isHiDPI) {
+        // TODO: screen capture
+        return null;
+    }
+}
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/headless/HeadlessPlatform.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/headless/HeadlessPlatform.java	Tue Jan 14 17:17:35 2014 +0200
@@ -28,12 +28,15 @@
 import com.sun.glass.ui.monocle.NativeScreen;
 import com.sun.glass.ui.monocle.NullCursor;
 import com.sun.glass.ui.monocle.input.InputDeviceRegistry;
+import com.sun.glass.ui.monocle.linux.LinuxInputDeviceRegistry;
 
 public class HeadlessPlatform extends NativePlatform {
 
     @Override
     protected InputDeviceRegistry createInputDeviceRegistry() {
-        return new InputDeviceRegistry();
+        // use of a LinuxInputDeviceRegistry lets us simulate
+        // Linux input devices on any system
+        return new LinuxInputDeviceRegistry(true);
     }
 
     @Override
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchInput.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchInput.java	Tue Jan 14 17:17:35 2014 +0200
@@ -138,13 +138,19 @@
      * @param eventType The type of TouchEvent to send (e.g. TouchEvent.PRESSED)
      */
     private void dispatchAllPoints(TouchState state, int eventType) {
+
         Window window = state.getWindow(false, null);
         View view = window == null ? null : window.getView();
         if (view != null) {
             touches.notifyBeginTouchEvent(view, 0, true, state.getPointCount());
             for (int i = 0; i < state.getPointCount(); i++) {
                 TouchState.Point oldPoint = state.getPoint(i);
-                dispatchPoint(window, view, eventType, oldPoint);
+                try {
+                    dispatchPoint(window, view, eventType, oldPoint);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    System.exit(0);
+                }
             }
             touches.notifyEndTouchEvent(view);
         }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchLookahead.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchLookahead.java	Tue Jan 14 17:17:35 2014 +0200
@@ -64,7 +64,6 @@
      */
     public void pullState(boolean clearPoints) {
         touch.getState(state);
-        processedFirstEvent = false;
         if (clearPoints) {
             state.clear();
         }
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchState.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchState.java	Tue Jan 14 17:17:35 2014 +0200
@@ -113,8 +113,7 @@
     void assignPrimaryID() {
         if (pointCount == 0) {
             primaryID = -1;
-        }
-        if (primaryID <= 0) {
+        } else if (primaryID <= 0) {
             // No primary ID is assigned. Assign a new ID arbitrarily.
             primaryID = points[0].id;
         } else {
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchStates.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/input/TouchStates.java	Tue Jan 14 17:17:35 2014 +0200
@@ -112,7 +112,7 @@
                 Arrays.fill(mappedIndices, 0);
             }
             int mappedIndexCount = 0;
-            for (int i = 0; i < oldState.getPointCount()
+            for (int i = 0; i < state.getPointCount()
                     && mappedIndexCount < oldState.getPointCount(); i++) {
                 TouchState.Point newPoint = state.getPoint(i);
                 int x = newPoint.x;
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/AbsoluteInputCapabilities.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/AbsoluteInputCapabilities.java	Tue Jan 14 17:17:35 2014 +0200
@@ -33,7 +33,7 @@
 
 /** Describes the capabilities of Linux input devices with absolute
  * coordinates. See /usr/include/linux/input.h */
-class AbsoluteInputCapabilities {
+public class AbsoluteInputCapabilities {
 
     private int value;
     private int minimum;
@@ -42,6 +42,16 @@
     private int flat;
     private int resolution;
 
+    public AbsoluteInputCapabilities(int value, int maximum, int minimum,
+                                     int fuzz, int flat, int resolution) {
+        this.value = value;
+        this.maximum = maximum;
+        this.minimum = minimum;
+        this.fuzz = fuzz;
+        this.flat = flat;
+        this.resolution = resolution;
+    }
+
     private AbsoluteInputCapabilities(LinuxSystem system,
                                       LinuxSystem.InputAbsInfo info,
                                       long fd, int axis) throws IOException {
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDevice.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDevice.java	Tue Jan 14 17:17:35 2014 +0200
@@ -92,6 +92,28 @@
         this.uevent = SysFS.readUEvent(sysPath);
     }
 
+    /**
+     * Create a new simulated LinuxInputDevice
+     *
+     * @param capabilities Simulated capabilities
+     * @param absCaps Simulated absolute axis capabilities
+     * @param in Channel f  or simulated input events
+     * @param uevent Simulated uevent data
+     */
+    public LinuxInputDevice(
+            Map<String, BitSet> capabilities,
+            Map<Integer, AbsoluteInputCapabilities> absCaps,
+            ReadableByteChannel in,
+            Map<String, String> udevManifest,
+            Map<String, String> uevent) {
+        this.capabilities = capabilities;
+        this.absCaps = absCaps;
+        this.in = in;
+        this.udevManifest = udevManifest;
+        this.uevent = uevent;
+        this.executor = NativePlatformFactory.getNativePlatform().getExecutor();
+    }
+
     public void setInputProcessor(LinuxInputProcessor inputProcessor) {
         this.inputProcessor = inputProcessor;
     }
@@ -158,7 +180,7 @@
      * @return a string describing this input device
      */
     public String toString() {
-        return devNode.toString();
+        return devNode == null ? "Robot" : devNode.toString();
     }
 
     BitSet getCapability(String type) {
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDeviceRegistry.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxInputDeviceRegistry.java	Tue Jan 14 17:17:35 2014 +0200
@@ -29,13 +29,18 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.security.AllPermission;
 import java.util.BitSet;
 import java.util.HashMap;
 import java.util.Map;
 
-class LinuxInputDeviceRegistry extends InputDeviceRegistry {
+public class LinuxInputDeviceRegistry extends InputDeviceRegistry {
 
-    LinuxInputDeviceRegistry() {
+    public LinuxInputDeviceRegistry(boolean headless) {
+        if (headless) {
+            // Keep the registry but do not bind it to udev.
+            return;
+        }
         Map<File, LinuxInputDevice> deviceMap = new HashMap<>();
         UdevListener udevListener = new UdevListener() {
             @Override
@@ -55,7 +60,6 @@
                                     devNode, sysPath, event);
                             if (device != null) {
                                 deviceMap.put(sysPath, device);
-                                devices.add(device);
                             }
                         } else if (action.equals("remove")) {
                             LinuxInputDevice device = deviceMap.get(devPath);
@@ -81,19 +85,40 @@
             throws IOException {
         LinuxInputDevice device = new LinuxInputDevice(
                 devNode, sysPath, udevManifest);
+        return addDeviceInternal(device, "Linux input: " + devNode.toString());
+    }
+
+    public LinuxInputDevice addDevice(LinuxInputDevice device, String name) {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkPermission(new AllPermission());
+        }
+        return addDeviceInternal(device, name);
+    }
+
+    private LinuxInputDevice addDeviceInternal(LinuxInputDevice device, String name) {
         LinuxInputProcessor processor = createInputProcessor(device);
         if (processor == null) {
             return null;
         } else {
             device.setInputProcessor(createInputProcessor(device));
             Thread thread = new Thread(device);
-            thread.setName("Linux input: " + devNode.toString());
+            thread.setName(name);
             thread.setDaemon(true);
             thread.start();
+            devices.add(device);
             return device;
         }
     }
 
+    public void removeDevice(LinuxInputDevice device) {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkPermission(new AllPermission());
+        }
+        devices.remove(device);
+    }
+
     private LinuxInputProcessor createInputProcessor(LinuxInputDevice device) {
         if (device.isTouch()) {
             return new LinuxTouchProcessor(device);
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxPlatform.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxPlatform.java	Tue Jan 14 17:17:35 2014 +0200
@@ -16,7 +16,7 @@
 
     @Override
     protected InputDeviceRegistry createInputDeviceRegistry() {
-        return new LinuxInputDeviceRegistry();
+        return new LinuxInputDeviceRegistry(false);
     }
 
     @Override
--- a/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxTouchProcessor.java	Mon Jan 13 10:27:00 2014 -0800
+++ b/modules/graphics/src/main/java/com/sun/glass/ui/monocle/linux/LinuxTouchProcessor.java	Tue Jan 14 17:17:35 2014 +0200
@@ -41,23 +41,43 @@
     public void processEvents(LinuxInputDevice device) {
         LinuxEventBuffer buffer = device.getBuffer();
         tl.pullState(true);
+        boolean touchReleased = false;
         while (buffer.hasNextEvent()) {
             switch (buffer.getEventType()) {
                 case Input.EV_ABS: {
                     int value = transform.getValue(buffer);
                     switch (transform.getAxis(buffer)) {
                         case Input.ABS_X:
+                        case Input.ABS_MT_POSITION_X:
                             tl.getState().getPointForID(0, true).x = value;
                             break;
                         case Input.ABS_Y:
+                        case Input.ABS_MT_POSITION_Y:
                             tl.getState().getPointForID(0, true).y = value;
                             break;
                     }
                     break;
                 }
+                case Input.EV_KEY:
+                    switch (buffer.getEventCode()) {
+                        case Input.BTN_TOUCH:
+                            if (buffer.getEventValue() == 0) {
+                                touchReleased = true;
+                            } else {
+                                // restore an old point
+                                tl.getState().getPointForID(0, true);
+                            }
+                            break;
+                    }
+                    break;
                 case Input.EV_SYN:
                     switch (buffer.getEventCode()) {
                         case Input.SYN_REPORT:
+                            if (touchReleased) {
+                                // remove points
+                                tl.getState().clear();
+                                touchReleased = false;
+                            }
                             tl.pushState();
                             tl.pullState(true);
                             break;