All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jemmy.input.awt.RobotDriver Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2007, 2017, 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 org.jemmy.input.awt;


import org.jemmy.Point;
import java.awt.event.InputEvent;

import org.jemmy.Rectangle;
import org.jemmy.env.Timeout;
import org.jemmy.env.Environment;
import org.jemmy.image.Image;
import static org.jemmy.input.awt.AWTRobotInputFactory.*;

import org.jemmy.interfaces.Keyboard.KeyboardButton;
import org.jemmy.interfaces.Keyboard.KeyboardButtons;
import org.jemmy.interfaces.Keyboard.KeyboardModifiers;
import org.jemmy.interfaces.Modifier;
import org.jemmy.interfaces.Mouse.MouseButton;


/**
 * @author shura
 * @author mrkam
 *
 */
public class RobotDriver {

    private static boolean haveOldPos = false;
    private static int smoothness;
    private static double oldX;
    private static double oldY;

    static {
        Environment.getEnvironment().setTimeout(
                new Timeout(ROBOT_DELAY_TIMEOUT_NAME, 10));
        Environment.getEnvironment().setPropertyIfNotSet(
                AWTRobotInputFactory.ROBOT_MOUSE_SMOOTHNESS_PROPERTY,
                Integer.toString(Integer.MAX_VALUE));
        smoothness =  Integer.parseInt(
                (String)Environment.getEnvironment().getProperty(
                AWTRobotInputFactory.ROBOT_MOUSE_SMOOTHNESS_PROPERTY));
    }

    /**
     * Sets mouse smoothness
     * @param mouseSmoothness the maximum distance in pixels between
     * mouse positions during movement
     * @see #moveMouse(Point)
     */
    public static void setMouseSmoothness(int mouseSmoothness) {
        smoothness = mouseSmoothness;
    }

    /**
     * Gets mouse smoothness
     * @return the maximum distance in pixels between
     * mouse positions during movement
     * @see #setMouseSmoothness(int)
     * @see #moveMouse(Point)
     */
    public static int getMouseSmoothness() {
        return smoothness;
    }

    /**
     * Constructs a RobotDriver object.
     * @param autoDelay Time for Robot.setAutoDelay(long) method.
     */
    public RobotDriver(Timeout autoDelay) {
        RobotExecutor.get().setAutoDelay(autoDelay);
    }

    /**
     * Constructs a RobotDriver object.
     * @param env Environment with ROBOT_DELAY_TIMEOUT_NAME timeout
     * @see AWTRobotInputFactory#ROBOT_DELAY_TIMEOUT_NAME
     */
    public RobotDriver(Environment env) {
        this(env.getTimeout(ROBOT_DELAY_TIMEOUT_NAME));
    }

    /**
     * Capture an image of specified rectangular area of screen
     * @param screenRect area on screen that will be captured
     * @return image of specified rectangular area of screen
     */
    public static Image createScreenCapture(Rectangle screenRect) {
        return RobotExecutor.get().createScreenCapture(screenRect);
    }

    /**
     * Presses mouse button specified by mouseButton preceding pressing of
     * modifier keys or buttons specified by modifiers
     * @param mouseButton One of MouseEvent.BUTTON*_MASK
     * @param modifiers Combination of InputEvent.*_DOWN_MASK
     * @see java.awt.event.InputEvent
     * @see java.awt.event.MouseEvent
     */
    public void pressMouse(MouseButton mouseButton, Modifier... modifiers) {
        pressModifiers(modifiers);
        makeAnOperation("mousePress",
                new Object[]{mouseButton},
                new Class[]{MouseButton.class});
    }

    /**
     * Releases mouse button specified by mouseButton then releasing
     * modifier keys or buttons specified by modifiers
     * @param mouseButton One of MouseEvent.BUTTON*_MASK
     * @param modifiers Combination of InputEvent.*_DOWN_MASK
     * @see java.awt.event.InputEvent
     * @see java.awt.event.MouseEvent
     */
    public void releaseMouse(MouseButton mouseButton, Modifier... modifiers) {
        makeAnOperation("mouseRelease",
                new Object[]{mouseButton},
                new Class[]{MouseButton.class});
        releaseModifiers(modifiers);
    }

    /**
     * Moves mouse to the specified mouse. When previous mouse location is
     * remembered mouse moved smoothly between the points according to
     * mouse smoothness parameter. Otherwise it jumps to the specified point
     * @param point Position on the screen where to move mouse
     * @see #setMouseSmoothness(int)
     * @see #getMouseSmoothness()
     */
    public void moveMouse(Point point) {
        double targetX = point.x;
        double targetY = point.y;
        if (haveOldPos && (oldX != targetX || oldY != targetY)) {
            double currX = oldX;
            double currY = oldY;
            double hyp = Math.sqrt((targetX - currX) * (targetX - currX) +
                    (targetY - currY) * (targetY - currY));
            double steps = Math.ceil(hyp / Math.min(hyp, smoothness));
            double vx = (targetX - currX) / steps;
            double vy = (targetY - currY) / steps;
            assert (long)vx * vx + (long)vy * vy <= (long)smoothness * smoothness;
            while (Math.round(currX) != Math.round(targetX) ||
                    Math.round(currY) != Math.round(targetY)) {
                currX += vx;
                currY += vy;
                makeAnOperation("mouseMove", new Object[]{
                            new Integer((int) Math.round(currX)),
                            new Integer((int) Math.round(currY))},
                        new Class[]{Integer.TYPE, Integer.TYPE});
            }
        } else {
            makeAnOperation("mouseMove",
                    new Object[]{new Integer(point.x), new Integer(point.y)},
                    new Class[]{Integer.TYPE, Integer.TYPE});
        }
        haveOldPos = true;
        oldX = targetX;
        oldY = targetY;
    }

    /**
     * Clicks the mouse button specified by mouseButton at the specified point
     * specified number of times preceding it by pressing the modifiers key or
     * buttons and ending by releasing them. The last click is as long as
     * mouseClick timeout
     * @param point Screen location where to click mouse
     * @param clickCount Number of clicks
     * @param mouseButton One of MouseEvent.BUTTON*_MASK
     * @param modifiers Combination of InputEvent.*_DOWN_MASK
     * @param mouseClick Timeout of the last click
     * @see java.awt.event.InputEvent
     * @see java.awt.event.MouseEvent
     */
    public void clickMouse(Point point, int clickCount, MouseButton mouseButton, Timeout mouseClick, Modifier... modifiers) {
        pressModifiers(modifiers);
        moveMouse(point);
        makeAnOperation("mousePress", new Object[]{mouseButton}, new Class[]{MouseButton.class});
        for (int i = 1; i < clickCount; i++) {
            makeAnOperation("mouseRelease", new Object[]{mouseButton}, new Class[]{MouseButton.class});
            makeAnOperation("mousePress", new Object[]{mouseButton}, new Class[]{MouseButton.class});
        }
        mouseClick.sleep();
        makeAnOperation("mouseRelease", new Object[]{mouseButton}, new Class[]{MouseButton.class});
        releaseModifiers(modifiers);
    }

    /**
     * @deprecated Implementation doesn't seem to be correct as it ignores mouseButton and modifiers
     * @param point todo document
     * @param mouseButton One of MouseEvent.BUTTON*_MASK
     * @param modifiers todo document
     */
    public void dragMouse(Point point, int mouseButton, int modifiers) {
        moveMouse(point);
    }

    /**
     * Performs drag and drop from startPoint to endPoint using specified
     * mouseButton and modifiers to perform it.
     * @param startPoint Screen coordinates of drag start point
     * @param endPoint Screen coordinates of drag end point
     * @param mouseButton One of MouseEvent.BUTTON*_MASK
     * @param modifiers Combination of InputEvent.*_DOWN_MASK
     * @param before Timeout between pressing mouse at the startPoint and
     * mouse move
     * @param after Timeout between mouse move to the endPoint and mouse
     * release
     */
    public void dragNDrop(Point startPoint, Point endPoint, MouseButton mouseButton, Modifier modifiers[], Timeout before, Timeout after) {
        moveMouse(startPoint);
        pressMouse(mouseButton, modifiers);
        before.sleep();
        moveMouse(endPoint);
        after.sleep();
        releaseMouse(mouseButton, modifiers);
    }

    /**
     * Presses a key.
     * @param kbdButton Key code (KeyEventVK_* field.
     * @param modifiers a combination of InputEvent.*_MASK fields.
     */
    public void pressKey(KeyboardButton kbdButton, Modifier... modifiers) {
        pressModifiers(modifiers);
        makeAnOperation("keyPress",
                new Object[]{kbdButton},
                new Class[]{KeyboardButton.class});
    }

    /**
     * Releases a key.
     * @param kbdButton Key code (KeyEventVK_* field.
     * @param modifiers a combination of InputEvent.*_MASK fields.
     */
    public void releaseKey(KeyboardButton kbdButton, Modifier... modifiers) {
        makeAnOperation("keyRelease",
                new Object[]{kbdButton},
                new Class[]{KeyboardButton.class});
        releaseModifiers(modifiers);
    }

    /**
     * Turns the wheel.
     * @param p todo document
     * @param amount Either positive or negative
     * @param modifiers a combination of InputEvent.*_MASK fields.
     */
    public void turnWheel(Point p, int amount, Modifier... modifiers) {
        pressModifiers(modifiers);
        moveMouse(p);
        java.awt.Robot r = null;
        makeAnOperation("mouseWheel",
                new Object[]{amount},
                new Class[]{Integer.TYPE});
        releaseModifiers(modifiers);
    }

    /**
     * Performs a single operation.
     * @param method a name of java.awt.Robot method.
     * @param params method parameters
     * @param paramClasses method parameters classes
     */
    public void makeAnOperation(final String method, final Object[] params, final Class[] paramClasses) {
        RobotExecutor.get().makeAnOperation(method, params, paramClasses);
    }

    final static int SHIFT_MASK = InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK;
    final static int ALT_GRAPH_MASK = InputEvent.ALT_GRAPH_DOWN_MASK | InputEvent.ALT_GRAPH_MASK;
    final static int ALT_MASK = InputEvent.ALT_DOWN_MASK | InputEvent.ALT_MASK;
    final static int META_MASK = InputEvent.META_DOWN_MASK | InputEvent.META_MASK;
    final static int CTRL_MASK = InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK;

    /**
     * Presses modifiers keys by robot.
     * @param modifiers a combination of InputEvent.*_MASK fields.
     */
    protected void pressModifiers(Modifier... modifiers) {
        for (Modifier modifier : modifiers) { // TODO: ALT_GRAPH_MASK?
            if (modifier == KeyboardModifiers.ALT_DOWN_MASK) {
                pressKey(KeyboardButtons.ALT);
            } else if (modifier == KeyboardModifiers.CTRL_DOWN_MASK) {
                pressKey(KeyboardButtons.CONTROL);
            } else if (modifier == KeyboardModifiers.META_DOWN_MASK) {
                pressKey(KeyboardButtons.META);
            } else if (modifier == KeyboardModifiers.SHIFT_DOWN_MASK) {
                pressKey(KeyboardButtons.SHIFT);
            }
        }
    }

    /**
     * Releases modifiers keys by robot.
     * @param modifiers a combination of InputEvent.*_MASK fields.
     */
    protected void releaseModifiers(Modifier... modifiers) {
        for (Modifier modifier : modifiers) { // TODO: ALT_GRAPH_MASK?
            if (modifier == KeyboardModifiers.ALT_DOWN_MASK) {
                releaseKey(KeyboardButtons.ALT);
            } else if (modifier == KeyboardModifiers.CTRL_DOWN_MASK) {
                releaseKey(KeyboardButtons.CONTROL);
            } else if (modifier == KeyboardModifiers.META_DOWN_MASK) {
                releaseKey(KeyboardButtons.META);
            } else if (modifier == KeyboardModifiers.SHIFT_DOWN_MASK) {
                releaseKey(KeyboardButtons.SHIFT);
            }
        }
    }
    /**
     * If java.awt.Robot is running in other JVM, it shutdowns that JVM
     * @see AWTRobotInputFactory#runInOtherJVM(boolean)
     */
    public static void exit() {
        RobotExecutor.get().exit();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy